sagemaker_image_builder/dependency_upgrader.py (36 lines of code) (raw):
from semver import Version
_MAJOR = "major"
_MINOR = "minor"
_PATCH = "patch"
def _get_dependency_upper_bound_for_runtime_upgrade(dependency_name: str, lower_bound: str, runtime_upgrade_type):
metadata = _dependency_metadata.get(dependency_name, None)
version_upgrade_strategy = "semver" if metadata is None else metadata["version_upgrade_strategy"]
func = _version_upgrade_metadata[version_upgrade_strategy]["func"]
# Version strings on conda-forge follow PEP standards rather than SemVer, which support
# version strings such as X.Y.Z.postN, X.Y.Z.preN. These cause errors in semver.Version.parse
# so we keep the first 3 entries as version string.
if lower_bound.count(".") > 2:
lower_bound = ".".join(lower_bound.split(".")[:3])
return func(lower_bound, runtime_upgrade_type)
def _get_dependency_upper_bound_for_semver(lower_bound: str, runtime_upgrade_type):
lower_semver = Version.parse(lower_bound, optional_minor_and_patch=True)
if runtime_upgrade_type == _MAJOR:
return "" # No upper bound.
elif runtime_upgrade_type == _MINOR:
return f",<{lower_semver.bump_major()}"
elif runtime_upgrade_type == _PATCH:
return f",<{lower_semver.bump_minor()}"
else:
raise Exception()
def _get_dependency_upper_bound_for_pythonesque(lower_bound: str, runtime_upgrade_type):
lower_semver = Version.parse(lower_bound, optional_minor_and_patch=True)
if runtime_upgrade_type == _MAJOR:
return "" # No upper bound.
elif runtime_upgrade_type == _MINOR:
return f",<{lower_semver.bump_minor()}"
elif runtime_upgrade_type == _PATCH:
return f",<{lower_semver.bump_minor()}"
else:
raise Exception()
_version_upgrade_metadata = {
# Semver is a well-known version upgrade strategy. See: https://semver.org/
#
# Somewhat interestingly, 'calver' (see: https://calver.org/) also falls in the same category. Take Dask as an
# example. Its versioning strategy is 'YYYY.MM.n' (where 'n' starts as 0 and increases by 1 every time a release
# happens in the given month). So, 2nd release in December 2022 was versioned as '2022.12.1'.
"semver": {"func": _get_dependency_upper_bound_for_semver},
# Some dependencies follow, for lack of a better word, "python style" release cycles. For e.g., even if Python does
# a minor version upgrade from 3.9 to 3.10, we will only introduce 3.10 in an image as part of a major version upgrade.
# In other words, for dependencies below, minor version upgrades are treated as major version upgrades in an image.
"pythonesque": {"func": _get_dependency_upper_bound_for_pythonesque},
}
_dependency_metadata = {"python": {"version_upgrade_strategy": "pythonesque"}}