Bug 1858065 - Replace distutils' StrictVersion r=saschanaz,perftest-reviewers,sparky

distutils have been removed from Python 3.12, so replace it:

Sometimes using packaging's Version, sometimes providing our own in the
case of mozrelease/versions.py. Add more tests for the latter.

Differential Revision: https://phabricator.services.mozilla.com/D190540
This commit is contained in:
serge-sans-paille
2023-10-18 07:58:03 +00:00
parent 25b272ca14
commit 840d5bbbc7
7 changed files with 86 additions and 18 deletions

View File

@@ -5,14 +5,14 @@
import os
import platform
import subprocess
from distutils.version import StrictVersion
from mozboot.util import get_tools_dir
from mozfile import which
from packaging.version import Version
from six import PY3
NODE_MIN_VERSION = StrictVersion("12.22.12")
NPM_MIN_VERSION = StrictVersion("6.14.16")
NODE_MIN_VERSION = Version("12.22.12")
NPM_MIN_VERSION = Version("6.14.16")
def find_node_paths():
@@ -68,7 +68,7 @@ def check_executable_version(exe, wrap_call_with_node=False):
.lstrip("v")
.rstrip()
)
return StrictVersion(out)
return Version(out)
def find_node_executable(
@@ -87,7 +87,7 @@ def find_node_executable(
return None, None
if version >= min_version:
return nodejs_exe, version.version
return nodejs_exe, version.release
return None, None
@@ -123,4 +123,4 @@ def find_executable(name, min_version, use_node_for_version_check=False):
if version < min_version:
return None, None
return exe, version.version
return exe, version.release

View File

@@ -3,9 +3,59 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
import re
from distutils.version import StrictVersion
from looseversion import LooseVersion
from packaging.version import InvalidVersion
class StrictVersion:
def __init__(self, vstring):
self.parse(vstring)
def __repr__(self):
return "%s ('%s')" % (self.__class__.__name__, str(self))
def __eq__(self, other):
return self._cmp(other) == 0
def __lt__(self, other):
return self._cmp(other) < 0
def parse(self, vstring):
match = self.version_re.match(vstring)
if not match:
raise InvalidVersion("invalid version number '%s'" % vstring)
major, minor, patch, pre, pre_num = match.group(1, 2, 4, 5, 6)
self.version = int(major), int(minor), int(patch or 0)
self.pre = (pre[0], int(pre_num)) if pre else ()
def __str__(self):
return ".".join(map(str, self.version)) + (
"".join(map(str, self.pre)) if self.pre else ""
)
def _cmp(self, other):
if isinstance(other, str):
other = StrictVersion(other)
elif not isinstance(other, StrictVersion):
raise NotImplementedError
if self.version < other.version:
return -1
elif self.version == other.version:
if self.pre == other.pre:
return 0
elif not self.pre:
return 1
elif not other.pre:
return -1
elif self.pre < other.pre:
return -1
else:
return 1
else:
return 1
class MozillaVersionCompareMixin:
@@ -93,12 +143,12 @@ class LooseModernMozillaVersion(MozillaVersionCompareMixin, LooseVersion):
def MozillaVersion(version):
try:
return ModernMozillaVersion(version)
except ValueError:
except InvalidVersion:
pass
try:
if version.count(".") == 3:
return AncientMozillaVersion(version)
except ValueError:
except InvalidVersion:
pass
try:
return LooseModernMozillaVersion(version)

View File

@@ -1,7 +1,11 @@
import mozunit
import pytest
from mozrelease.versions import MozillaVersion
from mozrelease.versions import (
AncientMozillaVersion,
ModernMozillaVersion,
MozillaVersion,
)
ALL_VERSIONS = [ # Keep this sorted
"3.0",
@@ -91,6 +95,21 @@ def test_versions_compare_greater(comparable_versions):
assert MozillaVersion(larger_version) > MozillaVersion(smaller_version)
def test_ModernMozillaVersion():
"""Test properties specific to ModernMozillaVersion"""
assert isinstance(MozillaVersion("1.2.4"), ModernMozillaVersion)
assert isinstance(MozillaVersion("1.2.4rc3"), ModernMozillaVersion)
assert MozillaVersion("1.2rc3") == MozillaVersion("1.2.0rc3")
def test_AncientMozillaVersion():
"""Test properties specific to AncientMozillaVersion"""
assert isinstance(MozillaVersion("1.2.0.4"), AncientMozillaVersion)
assert isinstance(MozillaVersion("1.2.0.4pre1"), AncientMozillaVersion)
assert MozillaVersion("1.2pre1") == MozillaVersion("1.2.0pre1")
assert MozillaVersion("1.2.0.4pre1") == MozillaVersion("1.2.4pre1")
@pytest.mark.parametrize("version", ALL_VERSIONS)
def test_versions_compare_equal(version):
"""Test that versions properly compare as equal through multiple passes."""

View File

@@ -263,10 +263,10 @@ class RaptorRunner(MozbuildObject):
def setup_node(command_context):
"""Fetch the latest node-16 binary and install it into the .mozbuild directory."""
import platform
from distutils.version import StrictVersion
from mozbuild.artifact_commands import artifact_toolchain
from mozbuild.nodeutil import find_node_executable
from packaging.version import Version
print("Setting up node for browsertime...")
state_dir = get_state_dir()
@@ -274,7 +274,7 @@ def setup_node(command_context):
def __check_for_node():
# Check standard locations first
node_exe = find_node_executable(min_version=StrictVersion("16.0.0"))
node_exe = find_node_executable(min_version=Version("16.0.0"))
if node_exe and (node_exe[0] is not None):
return node_exe[0]
if not os.path.exists(cache_path):

View File

@@ -81,9 +81,9 @@ def silence():
def node_path(command_context):
import platform
from distutils.version import StrictVersion
from mozbuild.nodeutil import find_node_executable
from packaging.version import Version
state_dir = command_context._mach_context.state_dir
cache_path = os.path.join(state_dir, "browsertime", "node-16")
@@ -97,7 +97,7 @@ def node_path(command_context):
)
# Check standard locations first
node_exe = find_node_executable(min_version=StrictVersion(MIN_NODE_VERSION))
node_exe = find_node_executable(min_version=Version(MIN_NODE_VERSION))
if node_exe and (node_exe[0] is not None):
return os.path.abspath(node_exe[0])
if not os.path.exists(cache_path):

View File

@@ -104,7 +104,7 @@ clippy:
# the version of cargo-clippy is:
# clippy 0.1.65 (2019147 2022-09-19)
# we use the date instead to facilitate the check
# replacing - by . because Python StrictVersion expects this
# replacing - by . because Python packaging.version.Version expects this
min_clippy_version: 2022.09.19
type: external
payload: clippy:lint

View File

@@ -2,16 +2,15 @@
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
from distutils.version import StrictVersion
from mach.decorators import Command, CommandArgument
from packaging.version import Version
def is_osx_10_10_or_greater(cls):
import platform
release = platform.mac_ver()[0]
return release and StrictVersion(release) >= StrictVersion("10.10")
return release and Version(release) >= Version("10.10")
# Get system power consumption and related measurements.