get version comparison from semver
since Python is removing version string parsing from the standard library
moves Julia-specific semver utilities to top-level
MODIFY
repo2docker/buildpacks/_r_base.py
repo2docker/buildpacks/_r_base.py
@@ -3,7 +3,7 @@ Base information for using R in BuildPacks.
Keeping this in r.py would lead to cyclic imports.
"""
-from distutils.version import LooseVersion as V
+from ..semver import parse_version as V
def rstudio_base_scripts(r_version):

MODIFY
repo2docker/buildpacks/julia/julia_project.py
repo2docker/buildpacks/julia/julia_project.py
"""Generates a Dockerfile based on an input matrix for Julia"""
import functools
import os
+
import requests
+import semver
import toml
+
from ..python import PythonBuildPack
-from .semver import find_semver_match, semver
+from ...semver import find_semver_match
class JuliaProjectTomlBuildPack(PythonBuildPack):

MODIFY
repo2docker/buildpacks/julia/julia_require.py
repo2docker/buildpacks/julia/julia_require.py
"""Generates a Dockerfile based on an input matrix with REQUIRE for legacy Julia"""
-from distutils.version import LooseVersion as V
import os
from ..python import PythonBuildPack
+from ...semver import parse_version as V
class JuliaRequireBuildPack(PythonBuildPack):

MODIFY
repo2docker/buildpacks/r.py
repo2docker/buildpacks/r.py
@@ -3,8 +3,8 @@ import os
import datetime
import requests
-from distutils.version import LooseVersion as V
+from ..semver import parse_version as V
from .python import PythonBuildPack
from ._r_base import rstudio_base_scripts

RENAME
repo2docker/buildpacks/julia/semver.py
repo2docker/semver.py
@@ -12,11 +12,13 @@ constraints.
import re
+from functools import lru_cache
import semver
def find_semver_match(constraint, versions_list):
+ """Find first version in a list of versions that matches a constraint"""
matcher = create_semver_matcher(constraint)
for vstr in reversed(versions_list):
if matcher.match(str_to_version(vstr)):
@@ -25,9 +27,29 @@ def find_semver_match(constraint, versions_list):
def str_to_version(vstr):
+ """Convert a simple x[.y[.z]] version string to a tuple of ints"""
return tuple([int(n) for n in vstr.split(".")])
+@lru_cache()
+def parse_version(vstr):
+ """Convert a simple 'x[.y[.z]]' version string to a comparable VersionInfo
+
+ Wraps semver.VersionInfo.parse with zero-padding,
+ so it can accept '1.0', where upstream only accepts exactly 3 version fields.
+ """
+ try:
+ return semver.VersionInfo.parse(vstr)
+ except ValueError:
+ # may fail for e.g. short 1.0 versions
+ n_fields = vstr.count(".")
+ if n_fields < 2:
+ vstr = vstr + (".0" * (2 - n_fields))
+ return semver.VersionInfo.parse(vstr)
+ else:
+ raise
+
+
# Helpers
def major(v):
return v[0]
@@ -41,6 +63,7 @@ def patch(v):
return v[2] if len(v) >= 3 else 0
+@lru_cache()
def create_semver_matcher(constraint_str):
"""Create a matcher that can be used to match version tuples

MODIFY
tests/unit/test_semver.py
tests/unit/test_semver.py
import pytest
-from repo2docker.buildpacks.julia import semver
+from semver import VersionInfo
+from repo2docker import semver
@pytest.mark.parametrize("test_input, expected", [("1.5.2", (1, 5, 2)), ("1", (1,))])
@@ -145,3 +146,20 @@ def test_largerthan_equal():
semver.create_semver_matcher(">=1.2.3").match(semver.str_to_version("1.2.2"))
== False
)
+
+
+@pytest.mark.parametrize(
+ "vstr, expected",
+ [
+ ("1.2.3", "1.2.3"),
+ ("1.2", "1.2.0"),
+ ("1", "1.0.0"),
+ ],
+)
+def test_parse_version(vstr, expected):
+ version_info = semver.parse_version(vstr)
+ assert isinstance(version_info, semver.semver.VersionInfo)
+ assert str(version_info) == expected
+ # satisfies itself, since this is how we use it
+ assert semver.parse_version(expected) <= version_info
+ assert semver.parse_version(expected) >= version_info

get version comparison from semver

since Python is removing version string parsing from the standard library

moves Julia-specific semver utilities to top-level