Skip to content
This repository was archived by the owner on Feb 23, 2026. It is now read-only.

Commit b575a16

Browse files
committed
refactor: used namedtuple
1 parent 187f848 commit b575a16

2 files changed

Lines changed: 35 additions & 28 deletions

File tree

google/api_core/_python_package_support.py

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -16,18 +16,23 @@
1616

1717
import warnings
1818
import sys
19-
from typing import Optional, Tuple
19+
from typing import Optional
20+
21+
from collections import namedtuple
22+
2023
from ._python_version_support import (
2124
_flatten_message,
2225
_get_distribution_and_import_packages,
2326
)
2427

25-
from packaging.version import parse as parse_version, Version as PackagingVersion
28+
from packaging.version import parse as parse_version
29+
30+
DependencyVersion = namedtuple("DependencyVersion", ["version", "version_string"])
2631

2732

2833
def get_dependency_version(
2934
dependency_name: str,
30-
) -> Tuple[Optional[PackagingVersion], str]:
35+
) -> DependencyVersion:
3136
"""Get the parsed version of an installed package dependency.
3237
3338
This function checks for an installed package and returns its version
@@ -38,16 +43,16 @@ def get_dependency_version(
3843
dependency_name: The distribution name of the package (e.g., 'requests').
3944
4045
Returns:
41-
A tuple containing the `packaging.version.Version` object and the
42-
version string, or `(None, '--')` if the package is not found or
43-
another error occurs during version discovery.
46+
A DependencyVersion namedtuple with `version` and `version_string`
47+
attributes, or `DependencyVersion(None, '--')` if the package is not
48+
found or another error occurs during version discovery.
4449
"""
4550
try:
4651
if sys.version_info >= (3, 8):
4752
from importlib import metadata
4853

4954
version_string = metadata.version(dependency_name)
50-
return (parse_version(version_string), version_string)
55+
return DependencyVersion(parse_version(version_string), version_string)
5156

5257
# TODO(https://github.com/googleapis/python-api-core/issues/835): Remove
5358
# this code path once we drop support for Python 3.7
@@ -56,10 +61,10 @@ def get_dependency_version(
5661
import pkg_resources
5762

5863
version_string = pkg_resources.get_distribution(dependency_name).version
59-
return (parse_version(version_string), version_string)
64+
return DependencyVersion(parse_version(version_string), version_string)
6065

6166
except Exception:
62-
return (None, "--")
67+
return DependencyVersion(None, "--")
6368

6469

6570
def warn_deprecation_for_versions_less_than(
@@ -107,12 +112,10 @@ def warn_deprecation_for_versions_less_than(
107112
or not next_supported_version
108113
): # pragma: NO COVER
109114
return
110-
(version_used, version_used_string) = get_dependency_version(
111-
dependency_import_package
112-
)
113-
if not version_used:
115+
dependency_version = get_dependency_version(dependency_import_package)
116+
if not dependency_version.version:
114117
return
115-
if version_used < parse_version(next_supported_version):
118+
if dependency_version.version < parse_version(next_supported_version):
116119
(
117120
dependency_package,
118121
dependency_distribution_package,
@@ -151,8 +154,8 @@ def warn_deprecation_for_versions_less_than(
151154
dependent_package=dependent_package,
152155
next_supported_version=next_supported_version,
153156
recommendation=recommendation,
154-
version_used=version_used,
155-
version_used_string=version_used_string,
157+
version_used=dependency_version.version,
158+
version_used_string=dependency_version.version_string,
156159
),
157160
FutureWarning,
158161
)

tests/unit/test_python_package_support.py

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
from google.api_core._python_package_support import (
2323
get_dependency_version,
2424
warn_deprecation_for_versions_less_than,
25+
DependencyVersion,
2526
)
2627

2728

@@ -32,12 +33,13 @@
3233
def test_get_dependency_version_py38_plus(mock_version):
3334
"""Test get_dependency_version on Python 3.8+."""
3435
mock_version.return_value = "1.2.3"
35-
assert get_dependency_version("some-package") == (parse_version("1.2.3"), "1.2.3")
36+
expected = DependencyVersion(parse_version("1.2.3"), "1.2.3")
37+
assert get_dependency_version("some-package") == expected
3638
mock_version.assert_called_once_with("some-package")
3739

3840
# Test package not found
3941
mock_version.side_effect = ImportError
40-
assert get_dependency_version("not-a-package") == (None, "--")
42+
assert get_dependency_version("not-a-package") == DependencyVersion(None, "--")
4143

4244

4345
# TODO(https://github.com/googleapis/python-api-core/issues/835): Remove
@@ -49,17 +51,15 @@ def test_get_dependency_version_py37(mock_get_distribution):
4951
mock_dist = MagicMock()
5052
mock_dist.version = "4.5.6"
5153
mock_get_distribution.return_value = mock_dist
52-
assert get_dependency_version("another-package") == (
53-
parse_version("4.5.6"),
54-
"4.5.6",
55-
)
54+
expected = DependencyVersion(parse_version("4.5.6"), "4.5.6")
55+
assert get_dependency_version("another-package") == expected
5656
mock_get_distribution.assert_called_once_with("another-package")
5757

5858
# Test package not found
5959
mock_get_distribution.side_effect = (
6060
Exception # pkg_resources has its own exception types
6161
)
62-
assert get_dependency_version("not-a-package") == (None, "--")
62+
assert get_dependency_version("not-a-package") == DependencyVersion(None, "--")
6363

6464

6565
@patch("google.api_core._python_package_support._get_distribution_and_import_packages")
@@ -72,7 +72,7 @@ def test_warn_deprecation_for_versions_less_than(mock_get_version, mock_get_pack
7272
("my-package (my.package)", "my-package"),
7373
]
7474

75-
mock_get_version.return_value = (parse_version("1.0.0"), "1.0.0")
75+
mock_get_version.return_value = DependencyVersion(parse_version("1.0.0"), "1.0.0")
7676
with pytest.warns(FutureWarning) as record:
7777
warn_deprecation_for_versions_less_than("my.package", "dep.package", "2.0.0")
7878
assert len(record) == 1
@@ -87,17 +87,21 @@ def test_warn_deprecation_for_versions_less_than(mock_get_version, mock_get_pack
8787

8888
# Case 2: Installed version is equal to required, should not warn.
8989
mock_get_packages.reset_mock()
90-
mock_get_version.return_value = (parse_version("2.0.0"), "2.0.0")
90+
mock_get_version.return_value = DependencyVersion(
91+
parse_version("2.0.0"), "2.0.0"
92+
)
9193
warn_deprecation_for_versions_less_than("my.package", "dep.package", "2.0.0")
9294

9395
# Case 3: Installed version is greater than required, should not warn.
9496
mock_get_packages.reset_mock()
95-
mock_get_version.return_value = (parse_version("3.0.0"), "3.0.0")
97+
mock_get_version.return_value = DependencyVersion(
98+
parse_version("3.0.0"), "3.0.0"
99+
)
96100
warn_deprecation_for_versions_less_than("my.package", "dep.package", "2.0.0")
97101

98102
# Case 4: Dependency not found, should not warn.
99103
mock_get_packages.reset_mock()
100-
mock_get_version.return_value = (None, "--")
104+
mock_get_version.return_value = DependencyVersion(None, "--")
101105
warn_deprecation_for_versions_less_than("my.package", "dep.package", "2.0.0")
102106

103107
# Assert that no warnings were recorded
@@ -109,7 +113,7 @@ def test_warn_deprecation_for_versions_less_than(mock_get_version, mock_get_pack
109113
("dep-package (dep.package)", "dep-package"),
110114
("my-package (my.package)", "my-package"),
111115
]
112-
mock_get_version.return_value = (parse_version("1.0.0"), "1.0.0")
116+
mock_get_version.return_value = DependencyVersion(parse_version("1.0.0"), "1.0.0")
113117
template = "Custom warning for {dependency_package} used by {dependent_package}."
114118
with pytest.warns(FutureWarning) as record:
115119
warn_deprecation_for_versions_less_than(

0 commit comments

Comments
 (0)