Skip to content

Commit c7a75ba

Browse files
authored
[BUG] Accepting prereleases as valid python version (#389)
#### Reference Issues/PRs Fixes: sktime/sktime#7517 Make "rc" python version recognizable during python version checking. Introducing a parameter `prereleases=True` The following code snipped now returns true: ```python "3.11.0rc1" in SpecifierSet(">3.8", prereleases=True) ```
1 parent 35e4953 commit c7a75ba

File tree

3 files changed

+76
-3
lines changed

3 files changed

+76
-3
lines changed

.all-contributorsrc

+9
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,15 @@
103103
"contributions": [
104104
"maintenance"
105105
]
106+
},
107+
{
108+
"login": "Abelarm",
109+
"name": "Luigi Giugliano",
110+
"avatar_url": "https://avatars.githubusercontent.com/u/6976921?v=4",
111+
"profile": "https://github.com/Abelarm",
112+
"contributions": [
113+
"code"
114+
]
106115
}
107116
],
108117
"projectName": "skbase",

skbase/utils/dependencies/_dependencies.py

+14-2
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,9 @@ def _get_pkg_version(package_name):
236236
return pkg_env_version
237237

238238

239-
def _check_python_version(obj, package=None, msg=None, severity="error"):
239+
def _check_python_version(
240+
obj, package=None, msg=None, severity="error", prereleases=True
241+
):
240242
"""Check if system python version is compatible with requirements of obj.
241243
242244
Parameters
@@ -259,6 +261,13 @@ def _check_python_version(obj, package=None, msg=None, severity="error"):
259261
* "none" - does not raise exception or warning
260262
function returns False if one of packages is not installed, otherwise True
261263
264+
prereleases: str, default = True
265+
Whether prerelease versions are considered compatible.
266+
If True, allows prerelease versions to be considered compatible.
267+
If False, always considers prerelease versions as incompatible, i.e., always
268+
raises error, warning, or returns False, if the system python version is a
269+
prerelease.
270+
262271
Returns
263272
-------
264273
compatible : bool, whether obj is compatible with system python version
@@ -276,7 +285,7 @@ def _check_python_version(obj, package=None, msg=None, severity="error"):
276285
return True
277286

278287
try:
279-
est_specifier = SpecifierSet(est_specifier_tag)
288+
est_specifier = SpecifierSet(est_specifier_tag, prereleases=prereleases)
280289
except InvalidSpecifier:
281290
msg_version = (
282291
f"wrong format for python_version tag, "
@@ -303,6 +312,9 @@ def _check_python_version(obj, package=None, msg=None, severity="error"):
303312
f" but system python version is {sys.version}."
304313
)
305314

315+
if "rc" in sys_version:
316+
msg += " This is due to the release candidate status of your system Python."
317+
306318
if package is not None:
307319
msg += (
308320
f" This is due to python version requirements of the {package} package."

skbase/utils/dependencies/tests/test_check_dependencies.py

+53-1
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
# -*- coding: utf-8 -*-
22
"""Tests for _check_soft_dependencies utility."""
3+
from unittest.mock import patch
4+
35
import pytest
46
from packaging.requirements import InvalidRequirement
57

6-
from skbase.utils.dependencies._dependencies import _check_soft_dependencies
8+
from skbase.utils.dependencies import _check_python_version, _check_soft_dependencies
79

810

911
def test_check_soft_deps():
@@ -47,3 +49,53 @@ def test_check_soft_deps():
4749
assert _check_soft_dependencies(
4850
("pytest", "!!numpy<~><>0.1.0"), severity="none"
4951
)
52+
53+
54+
@patch("skbase.utils.dependencies._dependencies.sys")
55+
@pytest.mark.parametrize(
56+
"mock_release_version, prereleases, expect_exception",
57+
[
58+
(True, True, False),
59+
(True, False, True),
60+
(False, False, False),
61+
(False, True, False),
62+
],
63+
)
64+
def test_check_python_version(
65+
mock_sys, mock_release_version, prereleases, expect_exception
66+
):
67+
from skbase.base import BaseObject
68+
69+
if mock_release_version:
70+
mock_sys.version = "3.8.1rc"
71+
else:
72+
mock_sys.version = "3.8.1"
73+
74+
class DummyObjectClass(BaseObject):
75+
_tags = {
76+
"python_version": ">=3.7.1", # PEP 440 version specifier, e.g., ">=3.7"
77+
"python_dependencies": None, # PEP 440 dependency strs, e.g., "pandas>=1.0"
78+
"env_marker": None, # PEP 508 environment marker, e.g., "os_name=='posix'"
79+
}
80+
"""Define dummy class to test set_tags."""
81+
82+
dummy_object_instance = DummyObjectClass()
83+
84+
try:
85+
_check_python_version(dummy_object_instance, prereleases=prereleases)
86+
except ModuleNotFoundError as exception:
87+
expected_msg = (
88+
f"{type(dummy_object_instance).__name__} requires python version "
89+
f"to be {dummy_object_instance.get_tags()['python_version']}, "
90+
f"but system python version is {mock_sys.version}. "
91+
"This is due to the release candidate status of your system Python."
92+
)
93+
94+
if not expect_exception or exception.msg != expected_msg:
95+
# Throw Error since exception is not expected or has not the correct message
96+
raise AssertionError(
97+
"ModuleNotFoundError should be NOT raised by:",
98+
f"\n\t - mock_release_version: {mock_release_version},",
99+
f"\n\t - prereleases: {prereleases},",
100+
f"\nERROR MESSAGE: {exception.msg}",
101+
) from exception

0 commit comments

Comments
 (0)