Skip to content

Commit

Permalink
Updates according to code review
Browse files Browse the repository at this point in the history
Co-authored-by: Daniel Marchand <[email protected]>
  • Loading branch information
CasperWA and daniel-sintef committed Nov 23, 2023
1 parent 227cc1a commit 1609b64
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 39 deletions.
22 changes: 18 additions & 4 deletions ci_cd/tasks/update_deps.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
from invoke import task
from packaging.markers import default_environment
from packaging.requirements import InvalidRequirement, Requirement
from packaging.version import Version
from packaging.version import InvalidVersion, Version
from tomlkit.exceptions import TOMLKitError

from ci_cd.exceptions import InputError, UnableToResolve
Expand Down Expand Up @@ -281,7 +281,7 @@ def update_deps( # pylint: disable=too-many-branches,too-many-locals,too-many-s
hide=True,
)
package_latest_version_line = out.stdout.split(sep="\n", maxsplit=1)[0]
match = re.search(
match = re.match(
r"(?P<package>\S+) \((?P<version>\S+)\)", package_latest_version_line
)
if match is None:
Expand All @@ -297,7 +297,21 @@ def update_deps( # pylint: disable=too-many-branches,too-many-locals,too-many-s
error = True
continue

latest_version = Version(match.group("version"))
try:
latest_version = Version(match.group("version"))
except InvalidVersion as exc:
msg = (

Check warning on line 303 in ci_cd/tasks/update_deps.py

View check run for this annotation

Codecov / codecov/patch

ci_cd/tasks/update_deps.py#L302-L303

Added lines #L302 - L303 were not covered by tests
f"Could not parse version {match.group('version')!r} from 'pip index "
f"versions' output for line:\n {package_latest_version_line}.\n"
f"Exception: {exc}"
)
LOGGER.error(msg)
if fail_fast:
sys.exit(f"{Emoji.CROSS_MARK.value} {error_msg(msg)}")
print(error_msg(msg), file=sys.stderr, flush=True)
error = True
continue

Check warning on line 313 in ci_cd/tasks/update_deps.py

View check run for this annotation

Codecov / codecov/patch

ci_cd/tasks/update_deps.py#L308-L313

Added lines #L308 - L313 were not covered by tests
LOGGER.debug("Retrieved latest version: %r", latest_version)

# Here used to be a sanity check to ensure that the package name parsed from
# pyproject.toml matches the name returned from 'pip index versions'.
Expand Down Expand Up @@ -377,7 +391,7 @@ def update_deps( # pylint: disable=too-many-branches,too-many-locals,too-many-s
current_version = specifier.version.split(".")
break
else:
if latest_version.epoch != 0:
if latest_version.epoch == 0:
current_version = "0.0.0".split(".")
else:
current_version = f"{latest_version.epoch}!0.0.0".split(".")
Expand Down
74 changes: 40 additions & 34 deletions ci_cd/utils/versions.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,12 +74,15 @@ class SemanticVersion(str):
"""

_regex = (
_semver_regex = (
r"^(?P<major>0|[1-9]\d*)(?:\.(?P<minor>0|[1-9]\d*))?(?:\.(?P<patch>0|[1-9]\d*))?"
r"(?:-(?P<pre_release>(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)"
r"(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?"
r"(?:\+(?P<build>[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$"
)
"""The regular expression for a semantic version.
See
https://semver.org/#is-there-a-suggested-regular-expression-regex-to-check-a-semver-string."""

@no_type_check
def __new__(
Expand Down Expand Up @@ -111,7 +114,7 @@ def __init__(
self._python_version = version
version = ".".join(str(_) for _ in version.release)

match = re.match(self._regex, version)
match = re.match(self._semver_regex, version)
if match is None:
# Try to parse it as a Python version and try again
try:
Expand All @@ -125,7 +128,8 @@ def __init__(
# Success. Now let's redo the SemVer.org regular expression match
self._python_version = _python_version
match = re.match(
self._regex, ".".join(str(_) for _ in _python_version.release)
self._semver_regex,
".".join(str(_) for _ in _python_version.release),
)
if match is None: # pragma: no cover
# This should not really be possible at this point, as the
Expand Down Expand Up @@ -219,45 +223,47 @@ def python_version(self) -> Version | None:

def as_python_version(self, shortened: bool = True) -> Version:
"""Return the Python version as defined by `packaging.version.Version`."""
if self.python_version:
# If the SemanticVersion was generated from a Version, return the original
# epoch (and the rest, if the release equals the current version).
# Otherwise, return it as a "base_version".

# epoch
redone_version = (
f"{self.python_version.epoch}!"
if self.python_version.epoch != 0
else ""
if not self.python_version:
return Version(
self.shortened()
if shortened
else ".".join(str(_) for _ in (self.major, self.minor, self.patch))
)

# release
if shortened:
redone_version += self.shortened()
else:
redone_version += ".".join(
str(_) for _ in (self.major, self.minor, self.patch)
)
# The SemanticVersion was generated from a Version. Return the original
# epoch (and the rest, if the release equals the current version).

if (self.major, self.minor, self.patch)[
: len(self.python_version.release)
] == self.python_version.release:
# pre, post, dev, local
if self.python_version.pre is not None:
redone_version += "".join(str(_) for _ in self.python_version.pre)
# epoch
redone_version = (
f"{self.python_version.epoch}!" if self.python_version.epoch != 0 else ""
)

# release
if shortened:
redone_version += self.shortened()
else:
redone_version += ".".join(
str(_) for _ in (self.major, self.minor, self.patch)
)

if self.python_version.post is not None:
redone_version += f".post{self.python_version.post}"
if (self.major, self.minor, self.patch)[
: len(self.python_version.release)
] == self.python_version.release:
# The release is the same as the current version. Add the pre, post, dev,
# and local parts, if any.
if self.python_version.pre is not None:
redone_version += "".join(str(_) for _ in self.python_version.pre)

if self.python_version.dev is not None:
redone_version += f".dev{self.python_version.dev}"
if self.python_version.post is not None:
redone_version += f".post{self.python_version.post}"

if self.python_version.local is not None:
redone_version += f"+{self.python_version.local}"
if self.python_version.dev is not None:
redone_version += f".dev{self.python_version.dev}"

return Version(redone_version)
if self.python_version.local is not None:
redone_version += f"+{self.python_version.local}"

return Version(self.shortened())
return Version(redone_version)

def __str__(self) -> str:
"""Return the full version."""
Expand Down
3 changes: 2 additions & 1 deletion tests/utils/test_versions.py
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,8 @@ def test_semanticversion_python_version(
if isinstance(version_, Version) or (
isinstance(version_, str)
and re.match(
SemanticVersion._regex, version_ # pylint: disable=protected-access
SemanticVersion._semver_regex, # pylint: disable=protected-access
version_,
)
is None
):
Expand Down

0 comments on commit 1609b64

Please sign in to comment.