diff --git a/repo2docker/buildpacks/julia/julia_project.py b/repo2docker/buildpacks/julia/julia_project.py index 0d039aae7..0e9f9daa4 100644 --- a/repo2docker/buildpacks/julia/julia_project.py +++ b/repo2docker/buildpacks/julia/julia_project.py @@ -1,8 +1,10 @@ """Generates a Dockerfile based on an input matrix for Julia""" +import functools import os +import requests import toml from ..python import PythonBuildPack -from .semver import find_semver_match +from .semver import find_semver_match, semver class JuliaProjectTomlBuildPack(PythonBuildPack): @@ -13,48 +15,44 @@ class JuliaProjectTomlBuildPack(PythonBuildPack): # ALL EXISTING JULIA VERSIONS # Note that these must remain ordered, in order for the find_semver_match() # function to behave correctly. - all_julias = [ - "0.7.0", - "1.0.0", - "1.0.1", - "1.0.2", - "1.0.3", - "1.0.4", - "1.0.5", - "1.1.0", - "1.1.1", - "1.2.0", - "1.3.0", - "1.3.1", - "1.4.0", - "1.4.1", - "1.4.2", - "1.5.0", - "1.5.1", - "1.5.2", - "1.5.3", - ] + @property + @functools.lru_cache(maxsize=1) + def all_julias(self): + try: + json = requests.get( + "https://julialang-s3.julialang.org/bin/versions.json" + ).json() + except Exception as e: + raise RuntimeError("Failed to fetch available Julia versions: {e}") + vers = [semver.VersionInfo.parse(v) for v in json.keys()] + # filter out pre-release versions not supported by find_semver_match() + filtered_vers = [v for v in vers if v.prerelease is None] + # properly sort list of VersionInfo + sorted_vers = sorted( + filtered_vers, key=functools.cmp_to_key(semver.VersionInfo.compare) + ) + # return list of semver string + return [str(v) for v in sorted_vers] @property def julia_version(self): - default_julia_version = self.all_julias[-1] - if os.path.exists(self.binder_path("JuliaProject.toml")): project_toml = toml.load(self.binder_path("JuliaProject.toml")) else: project_toml = toml.load(self.binder_path("Project.toml")) - if "compat" in project_toml: - if "julia" in project_toml["compat"]: - julia_version_str = project_toml["compat"]["julia"] - - # For Project.toml files, install the latest julia version that - # satisfies the given semver. - _julia_version = find_semver_match(julia_version_str, self.all_julias) - if _julia_version is not None: - return _julia_version - - return default_julia_version + try: + # For Project.toml files, install the latest julia version that + # satisfies the given semver. + compat = project_toml["compat"]["julia"] + except: + # Default version which needs to be manually updated with new major.minor releases + compat = "1.5" + + match = find_semver_match(compat, self.all_julias) + if match is None: + raise RuntimeError("Failed to find a matching Julia version: {compat}") + return match def get_build_env(self): """Get additional environment settings for Julia and Jupyter diff --git a/repo2docker/buildpacks/julia/semver.py b/repo2docker/buildpacks/julia/semver.py index accd31922..da9bf7c77 100644 --- a/repo2docker/buildpacks/julia/semver.py +++ b/repo2docker/buildpacks/julia/semver.py @@ -113,7 +113,8 @@ def match(self, v): while len(v) < 3: v = v + (0,) v_str = ".".join(map(str, v)) - return semver.match(v_str, self.constraint_str) + v_ver = semver.VersionInfo.parse(v_str) + return semver.VersionInfo.match(v_ver, self.constraint_str) def __eq__(self, rhs): return self.constraint_str == rhs.constraint_str