Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 40 additions & 17 deletions repo2docker/buildpacks/conda/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""BuildPack for conda environments"""

import os
import re
import warnings
Expand All @@ -13,10 +14,10 @@
from .._r_base import rstudio_base_scripts
from ..base import BaseImage
from .matlab import (
matlab_requirements_scripts,
matlab_installation_scripts,
matlab_python_engine_installation_scripts,
matlab_proxy_installation_scripts,
matlab_python_engine_installation_scripts,
matlab_requirements_scripts,
)

# pattern for parsing conda dependency line
Expand Down Expand Up @@ -483,7 +484,7 @@ def _get_assemble_scripts_for_r(self):
installR_path = self.binder_path("install.R")
if not os.path.exists(installR_path):
return []
repo_url = 'https://cloud.r-project.org/'
repo_url = "https://cloud.r-project.org/"
return [
(
"${NB_USER}",
Expand Down Expand Up @@ -512,8 +513,12 @@ def _get_assemble_scripts_for_matlab(self):
raise ValueError("mpm.yml must contain a 'release' field")
scripts = matlab_requirements_scripts(config["release"], self.base_image)
matlab_dir = "/opt/matlab"
scripts += matlab_installation_scripts(config["release"], config.get("products", []), matlab_dir)
scripts += matlab_python_engine_installation_scripts(config["release"], matlab_dir)
scripts += matlab_installation_scripts(
config["release"], config.get("products", []), matlab_dir
)
scripts += matlab_python_engine_installation_scripts(
config["release"], matlab_dir
)
scripts += matlab_proxy_installation_scripts()
return scripts

Expand All @@ -524,18 +529,23 @@ def _get_env_for_matlab(self):
return [("MW_CONTEXT_TAGS", "MATLAB_PROXY:JUPYTER:MPM:V1")]

def _get_jlab_extension_script(
self, grdm_jlab_release_tag, grdm_jlab_filename_body, jupyter_resource_usage_tag,
self,
grdm_jlab_release_tag,
grdm_jlab_filename_body,
jupyter_resource_usage_tag,
perform_labextension_install=True,
perform_nbextension_install=True,
perform_jlpm_cache_clean=True,
perform_npm_cache_clean=True,
):
grdm_jlab_release_url = (
f"https://github.com/RCOSDP/CS-jupyterlab-grdm/releases/download/{grdm_jlab_release_tag}"
grdm_jlab_release_url = f"https://github.com/RCOSDP/CS-jupyterlab-grdm/releases/download/{grdm_jlab_release_tag}"
jupyter_resource_usage_release_url = (
"https://github.com/RCOSDP/CS-jupyter-resource-usage"
)
jupyter_resource_usage_release_url = "https://github.com/RCOSDP/CS-jupyter-resource-usage"
grdm_jlab_filename_tar_gz = f"{grdm_jlab_filename_body}.tar.gz"
grdm_jlab_filename_tgz = "{}.tgz".format(grdm_jlab_filename_body.replace("_", "-"))
grdm_jlab_filename_tgz = "{}.tgz".format(
grdm_jlab_filename_body.replace("_", "-")
)
jlpm_cache_clean = ""
if perform_jlpm_cache_clean:
jlpm_cache_clean = "jlpm cache clean"
Expand Down Expand Up @@ -578,26 +588,39 @@ def _get_jlab_extension_script(

def get_custom_extension_script(self, post):
grdm_jlab3_release_tag = "0.2.0"
grdm_jlab3_filename_body = f"rdm_binderhub_jlabextension-refs.tags.{grdm_jlab3_release_tag}"
grdm_jlab3_filename_body = (
f"rdm_binderhub_jlabextension-refs.tags.{grdm_jlab3_release_tag}"
)

grdm_jlab4_release_tag = "0.3.0"
grdm_jlab4_filename_body = f"rdm_binderhub_jlabextension-{grdm_jlab4_release_tag}"
grdm_jlab4_filename_body = (
f"rdm_binderhub_jlabextension-{grdm_jlab4_release_tag}"
)

jlab3_ext_script = self._get_jlab_extension_script(
grdm_jlab3_release_tag, grdm_jlab3_filename_body, 'v2023.07',
grdm_jlab3_release_tag,
grdm_jlab3_filename_body,
"v2023.07",
)
jlab4_ext_script = self._get_jlab_extension_script(
grdm_jlab4_release_tag, grdm_jlab4_filename_body, 'v2024.04',
grdm_jlab4_release_tag,
grdm_jlab4_filename_body,
"v2024.04",
perform_labextension_install=False,
perform_nbextension_install=False,
perform_jlpm_cache_clean=False,
perform_npm_cache_clean=False,
)

if post:
install_grdm = 'options(repos = c(CRAN = \\"https://cloud.r-project.org/\\")); ' \
+ 'if (!(\\"remotes\\" %in% rownames(installed.packages()))) install.packages(\\"remotes\\"); ' \
+ 'remotes::install_github(\\"RCOSDP/CS-rstudio-grdm\\", type = \\"source\\")'
# install from the GitHub archive tarball; install_github queries
# api.github.com, which is rate-limited for unauthenticated builds
install_grdm = (
'options(repos = c(CRAN = \\"https://cloud.r-project.org/\\")); '
+ 'if (!(\\"remotes\\" %in% rownames(installed.packages()))) install.packages(\\"remotes\\"); '
+ 'remotes::install_url(\\"https://github.com/RCOSDP/CS-rstudio-grdm/archive/refs/heads/master.tar.gz\\"); '
+ 'stopifnot(\\"rdmaddins\\" %in% rownames(installed.packages()))'
)
bash_scripts = f"""
if [ -x \\"$(command -v R)\\" ]; then R -e '{install_grdm}'; fi
"""
Expand Down
15 changes: 9 additions & 6 deletions repo2docker/buildpacks/r.py
Original file line number Diff line number Diff line change
Expand Up @@ -350,11 +350,11 @@ def get_build_scripts(self):
),
(
"${NB_USER}",
# Install a pinned version of devtools, IRKernel and shiny
# Install a pinned version of remotes, devtools, IRKernel and shiny
rf"""
export EXPANDED_CRAN_MIRROR_URL="$(. /etc/os-release && echo {cran_mirror_url} | envsubst)" && \
R --quiet -e "install.packages(c('devtools', 'IRkernel', 'shiny'), repos=Sys.getenv(\"EXPANDED_CRAN_MIRROR_URL\"))" && \
R --quiet -e "IRkernel::installspec(prefix=Sys.getenv(\"NB_PYTHON_PREFIX\"))"
R --no-save --no-restore --no-init-file --no-environ --quiet -e "install.packages(c('remotes', 'devtools', 'IRkernel', 'shiny'), repos=Sys.getenv(\"EXPANDED_CRAN_MIRROR_URL\"))" && \
R --no-save --no-restore --no-init-file --no-environ --quiet -e "IRkernel::installspec(prefix=Sys.getenv(\"NB_PYTHON_PREFIX\"))"
""",
),
]
Expand Down Expand Up @@ -390,7 +390,7 @@ def get_preassemble_scripts(self):
"${NB_USER}",
# Delete /tmp/downloaded_packages only if install.R fails, as the second
# invocation of install.R might be able to reuse them
f"Rscript {installR_path} && touch /tmp/.preassembled || true && rm -rf /tmp/downloaded_packages",
f"Rscript --no-save --no-restore --no-init-file --no-environ {installR_path} && touch /tmp/.preassembled || true && rm -rf /tmp/downloaded_packages",
)
]

Expand All @@ -408,14 +408,17 @@ def get_assemble_scripts(self):
"${NB_USER}",
# only run install.R if the pre-assembly failed
# Delete any downloaded packages in /tmp, as they aren't reused by R
f"""if [ ! -f /tmp/.preassembled ]; then Rscript {installR_path}; rm -rf /tmp/downloaded_packages; fi""",
f"""if [ ! -f /tmp/.preassembled ]; then Rscript --no-save --no-restore --no-init-file --no-environ {installR_path}; rm -rf /tmp/downloaded_packages; fi""",
)
]

description_R = "DESCRIPTION"
if not self.binder_dir and os.path.exists(description_R):
assemble_scripts += [
("${NB_USER}", 'R --quiet -e "devtools::install_local(getwd())"')
(
"${NB_USER}",
'R --no-save --no-restore --no-init-file --no-environ --quiet -e "remotes::install_local()"',
)
]

return assemble_scripts
4 changes: 3 additions & 1 deletion repo2docker/contentproviders/figshare.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,9 @@ def __init__(self):
# We may need to add other item types in future, see
# https://github.com/jupyterhub/repo2docker/pull/1001#issuecomment-760107436
# for a list
url_regex = re.compile(r"(.*)/articles/(code/|dataset/)?([^/]+)/(\d+)(/)?(\d+)?")
url_regex = re.compile(
r"(.*)/articles/(code/|dataset/|software/)?([^/]+)/(\d+)(/)?(\d+)?"
)

def detect(self, doi, ref=None, extra_args=None):
"""Trigger this provider for things that resolve to a Figshare article"""
Expand Down
16 changes: 4 additions & 12 deletions repo2docker/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from functools import partial
from shutil import copy2, copystat

import chardet
import charset_normalizer
from traitlets import Integer, TraitError


Expand Down Expand Up @@ -94,21 +94,13 @@ def chdir(path):
def open_guess_encoding(path):
"""
Open a file in text mode, specifying its encoding,
that we guess using chardet.
that we guess using charset_normalizer.
"""
detector = chardet.universaldetector.UniversalDetector()
with open(path, "rb") as f:
for line in f.readlines():
detector.feed(line)
if detector.done:
break
detector.close()
detector = charset_normalizer.from_fp(f)

file = open(path, encoding=detector.result["encoding"])
try:
with open(path, encoding=detector.best().encoding) as file:
yield file
finally:
file.close()


def validate_and_generate_port_mapping(port_mappings):
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ def get_identifier(json):
name="jupyter-repo2docker",
version=versioneer.get_version(),
install_requires=[
"chardet",
"charset-normalizer",
"docker!=5.0.0",
"entrypoints",
"escapism",
Expand Down
Loading