Remove support for Julia REQUIRE

it doesn't work anymore because build dependencies of the old ZMQ.jl have been removed.
pull/1350/head
Min RK 2024-05-27 15:02:48 +02:00
rodzic a4049fda33
commit d34f5c8039
Nie znaleziono w bazie danych klucza dla tego podpisu
11 zmienionych plików z 18 dodań i 296 usunięć

Wyświetl plik

@ -87,7 +87,7 @@ the `build` method of the `BuildPack` base class.
The **assemble** stage builds the specific environment that is requested by the repository.
This usually means installing required libraries specified in a format native to the language
(`requirements.txt`, `environment.yml`, `REQUIRE`, `install.R`, etc).
(`requirements.txt`, `environment.yml`, `Project.toml`, `install.R`, etc).
Most of this work is done in `get_assemble_scripts` method. It can return arbitrary bash script
lines that can be run as different users, and has access to the repository contents (unlike

Wyświetl plik

@ -102,14 +102,8 @@ of the Julia packages that are installed.
``REQUIRE`` - Install a Julia environment (legacy)
==================================================
A ``REQUIRE`` file can specify both the version of Julia to be used and
which Julia packages should be used. The use of ``REQUIRE`` is only
recommended for pre 1.0 Julia versions. The recommended way of installing
a Julia environment that uses Julia 1.0 or newer is to use a ``Project.toml``
file. If both a ``REQUIRE`` and a ``Project.toml`` file are detected,
the ``REQUIRE`` file is ignored. To see an example of a Julia repository
with ``REQUIRE`` and ``environment.yml``, visit
`binder-examples/julia-python <https://github.com/binder-examples/julia-python>`_.
``REQUIRE`` files no longer work, and are no longer supported.
The recommended way of installing a Julia environment is to use a ``Project.toml`` file.
.. _install.R:

Wyświetl plik

@ -57,7 +57,8 @@ Julia
All Julia versions since Julia 0.7.0 are supported via a :ref:`Project.toml <Project.toml>`
file, and this is the recommended way to install Julia environments.
Julia versions 0.6.x and earlier are supported via a :ref:`REQUIRE <REQUIRE>` file.
The older Julia REQUIRE file is no longer supported because required infrastructure has been removed.
R
~

Wyświetl plik

@ -5,14 +5,14 @@ The Reproducible Execution Environment Specification
====================================================
repo2docker scans a repository for particular :ref:`config-files`, such
as ``requirements.txt`` or ``REQUIRE``. The collection of files, their contents,
as ``requirements.txt`` or ``Project.toml``. The collection of files, their contents,
and the resulting actions that repo2docker takes is known
as the **Reproducible Execution Environment Specification** (or REES).
The goal of the REES is to automate and encourage existing community best practices
for reproducible computational environments. This includes installing pacakges using
community-standard specification files and their corresponding tools,
such as ``requirements.txt`` (with ``pip``), ``REQUIRE`` (with Julia), or
such as ``requirements.txt`` (with ``pip``), ``Project.toml`` (with Julia), or
``apt.txt`` (with ``apt``). While repo2docker automates the
creation of the environment, a human should be able to look at a REES-compliant
repository and reproduce the environment using common, clear steps without

Wyświetl plik

@ -1,36 +0,0 @@
#!/bin/julia
# Path to potential REQUIRE file is passed on the command line.
require_file = ARGS[1]
if VERSION < v"0.7-"
pkg_dir = "$(ENV["JULIA_PKGDIR"])/v$(VERSION.major).$(VERSION.minor)"
open("$pkg_dir/REQUIRE", "a") do io
write(io, read(require_file))
end
Pkg.resolve();
Reqs = Pkg.Reqs
else
using Pkg
Reqs = Pkg.Pkg2.Reqs
emptyversionlower = v"0.0.0-"
for reqline in Reqs.read(require_file)
if reqline isa Reqs.Requirement
pkg = String(reqline.package)
if pkg == "julia" continue end
version = try; reqline.versions.intervals[1].lower; catch; emptyversionlower; end
if version != emptyversionlower
Pkg.add(PackageSpec(name=pkg, version=version))
else
Pkg.add(pkg)
end
end
end
end
# Precompile the packages
for reqline in Reqs.read(require_file)
if reqline isa Reqs.Requirement
pkg = reqline.package
pkg != "julia" && eval(:(using $(Symbol(pkg))))
end
end

Wyświetl plik

@ -1,205 +1,29 @@
"""Generates a Dockerfile based on an input matrix with REQUIRE for legacy Julia"""
"""
DEPRECATED - Dependencies of REQUIRE have been removed
"""
import os
from functools import lru_cache
from ...semver import parse_version as V
from ..python import PythonBuildPack
class JuliaRequireBuildPack(PythonBuildPack):
"""
Julia build pack which uses conda and REQUIRE.
Now just an informative error message.
"""
minor_julias = {"0.6": "0.6.4", "0.7": "0.7.0", "1.0": "1.0.4", "1.1": "1.1.1"}
major_julias = {"1": "1.1.1"}
@property
def python_version(self):
# IJulia doesn't build on julia 0.6
# due to old incompatibilities with Jupyter-core >= 4.5,
# so use the similarly-old Python 3.5 base environment
if V(self.julia_version) < V("0.7"):
return "3.5"
else:
return super().python_version
@property
def julia_version(self):
require = self.binder_path("REQUIRE")
try:
with open(require) as f:
julia_version_line = (
f.readline().strip()
) # First line is optionally a julia version
except FileNotFoundError:
julia_version_line = ""
if not julia_version_line.startswith("julia "):
# not a Julia version line.
# use the default Julia.
self._julia_version = self.minor_julias["0.6"]
return self._julia_version
julia_version_info = julia_version_line.split(" ", 1)[1].split(".")
julia_version = ""
if len(julia_version_info) == 1:
julia_version = self.major_julias[julia_version_info[0]]
elif len(julia_version_info) == 2:
# get major.minor
julia_version = self.minor_julias[".".join(julia_version_info)]
else:
# use supplied julia version
julia_version = ".".join(julia_version_info)
self._julia_version = julia_version
return self._julia_version
@lru_cache()
def get_build_env(self):
"""Get additional environment settings for Julia and Jupyter
Returns:
an ordered list of environment setting tuples
The tuples contain a string of the environment variable name and
a string of the environment setting:
- `JULIA_PATH`: base path where all Julia Binaries and libraries
will be installed
- `JULIA_HOME`: path where all Julia Binaries will be installed
- `JULIA_PKGDIR`: path where all Julia libraries will be installed
- `JULIA_DEPOT_PATH`: path where Julia libraries are installed.
Similar to JULIA_PKGDIR, used in 1.x.
- `JULIA_VERSION`: default version of julia to be installed
- `JULIA_ARCH`: machine architecture used in Julia download URLs
- `JULIA_ARCH_SHORT`: machine architecture used in Julia download URLs
- `JUPYTER`: environment variable required by IJulia to point to
the `jupyter` executable
For example, a tuple may be `('JULIA_VERSION', '0.6.0')`.
"""
if self.platform == "linux/arm64":
julia_arch = julia_arch_short = "aarch64"
else:
julia_arch = "x86_64"
julia_arch_short = "x64"
if V(self.julia_version) < V("0.7"):
# IJulia with Julia 0.6 isn't compatible with more recent jupyter-core
# point it to the one in the kernel env
# I _think_ this is only relevant during installation
jupyter = "${KERNEL_PYTHON_PREFIX}/bin/jupyter"
else:
jupyter = "${NB_PYTHON_PREFIX}/bin/jupyter"
return super().get_build_env() + [
("JULIA_PATH", "${APP_BASE}/julia"),
("JULIA_HOME", "${JULIA_PATH}/bin"), # julia <= 0.6
("JULIA_BINDIR", "${JULIA_HOME}"), # julia >= 0.7
("JULIA_PKGDIR", "${JULIA_PATH}/pkg"),
("JULIA_DEPOT_PATH", "${JULIA_PKGDIR}"), # julia >= 0.7
("JULIA_VERSION", self.julia_version),
("JULIA_ARCH", julia_arch),
("JULIA_ARCH_SHORT", julia_arch_short),
("JUPYTER", jupyter),
]
@lru_cache()
def get_path(self):
"""Adds path to Julia binaries to user's PATH.
Returns:
an ordered list of path strings. The path to the Julia
executable is added to the list.
"""
return super().get_path() + ["${JULIA_HOME}"]
@lru_cache()
def get_build_scripts(self):
"""
Return series of build-steps common to "ALL" Julia repositories
All scripts found here should be independent of contents of a
particular repository.
This creates a directory with permissions for installing julia packages
(from get_assemble_scripts).
"""
return super().get_build_scripts() + [
(
"root",
r"""
mkdir -p ${JULIA_PATH} && \
curl -sSL "https://julialang-s3.julialang.org/bin/linux/${JULIA_ARCH_SHORT}/${JULIA_VERSION%[.-]*}/julia-${JULIA_VERSION}-linux-${JULIA_ARCH}.tar.gz" | tar -xz -C ${JULIA_PATH} --strip-components 1
""",
),
(
"root",
r"""
mkdir -p ${JULIA_PKGDIR} && \
chown ${NB_USER}:${NB_USER} ${JULIA_PKGDIR}
""",
),
(
"${NB_USER}",
# HACK: Can't seem to tell IJulia to install in sys-prefix
# FIXME: Find way to get it to install under /srv and not $HOME?
r"""
julia -e 'if (VERSION > v"0.7-") using Pkg; else Pkg.init(); end; Pkg.add("IJulia"); using IJulia;' && \
mv ${HOME}/.local/share/jupyter/kernels/julia-${JULIA_VERSION%[.-]*} ${NB_PYTHON_PREFIX}/share/jupyter/kernels/julia-${JULIA_VERSION%[.-]*}
""",
),
]
@lru_cache()
def get_assemble_scripts(self):
"""
Return series of build-steps specific to "this" Julia repository
Precompile all Julia libraries found in the repository's REQUIRE
file. The parent, CondaBuildPack, will add the build steps for
any needed Python packages found in environment.yml.
"""
require = self.binder_path("REQUIRE")
return super().get_assemble_scripts() + [
(
"${NB_USER}",
# Install and pre-compile all libraries if they've opted into it.
# In v0.6, Pkg.resolve() installs all the packages, but in v0.7+, we
# have to manually Pkg.add() each of them (since the REQUIRES file
# format is deprecated).
# The precompliation is done via `using {libraryname}`.
r"""
julia /tmp/install-repo-dependencies.jl "%(require)s"
"""
% {"require": require},
# TODO: For some reason, `rm`ing the file fails with permission denied.
# && rm /tmp/install-repo-dependencies.jl
)
]
@lru_cache()
def get_build_script_files(self):
files = {
"julia/install-repo-dependencies.jl": "/tmp/install-repo-dependencies.jl"
}
files.update(super().get_build_script_files())
return files
def build(self, *args, **kwargs):
raise ValueError(
"Julia REQUIRE no longer supported due to removed infrastructure. Use Project.toml."
)
def detect(self):
"""
Check if current repo should be built with the Julia Legacy Build pack
super().detect() is not called in this function - it would return
false unless an `environment.yml` is present and we do not want to
require the presence of a `environment.yml` to use Julia.
Instead we just check if the path to `REQUIRE` exists and that there is
no julia 1.0 style environment
Check if current repo exects tp be built with the Julia Legacy Build pack
This no longer works, but try to raise an informative error.
"""
return os.path.exists(self.binder_path("REQUIRE")) and not (
os.path.exists(self.binder_path("Project.toml"))

Wyświetl plik

@ -1,5 +0,0 @@
julia 1
# Julia packages:
PyCall
PyPlot

Wyświetl plik

@ -1,34 +0,0 @@
#!/usr/bin/env julia
using PyCall
using PyPlot
if ! (VERSION >= v"1" && VERSION < v"2")
println("Julia version was: ", VERSION)
println("Julia version expected to be 1.x when pinned to 1 in a REQUIRE file")
exit(1)
end
# Make sure we are re-using the same conda python
if ! startswith(PyCall.libpython, ENV["NB_PYTHON_PREFIX"] * "/lib")
println("Not re-using conda python! Using " * PyCall.libpython * " instead")
exit(1)
end
# We check that PyPlot is installed inside ${JULIA_DEPOT_PATH}
if ! isdir(ENV["JULIA_DEPOT_PATH"] * "/packages/PyPlot")
println("PyPlot not installed under JULIA_DEPOT_PATH")
exit(1)
end
# FIXME: Julia code that worked before v1, but now fails with:
#
# ERROR: LoadError: UndefVarError: linspace not defined
#
# x = linspace(0,2*pi,1000); y = sin(3*x + 4*cos(2*x))
# plot(x, y, color="red", linewidth=2.0, linestyle="--")
# savefig("graph.png")
# if isfile("graph.png")
# exit(0)
# else
# exit(1)
# end

Wyświetl plik

@ -1,2 +0,0 @@
# Julia packages:
Compat

Wyświetl plik

@ -1,19 +0,0 @@
#!/usr/bin/env julia
if VERSION != v"0.6.4"
println("Julia version was: ", VERSION)
println("Default Julia version expected to be 0.6.4 when unspecified in a REQUIRE file")
exit(1)
end
try
# Test that the package was installed.
using Compat
# Verify that the environment variables are set correctly for julia < 0.7
@assert "julia" ∈ readdir(Base.JULIA_HOME)
catch
exit(1)
end
exit(0)