Skip to content

Commit f939014

Browse files
Package Version Performance Regression (#970)
* Fix package version performance regression * Update tests/agent_unittests/test_package_version_utils.py * Update tests/agent_unittests/test_package_version_utils.py * Update tests/agent_unittests/test_package_version_utils.py * Skip test in python 2 --------- Co-authored-by: Hannah Stepanek <[email protected]>
1 parent 72aa6e8 commit f939014

File tree

2 files changed

+46
-27
lines changed

2 files changed

+46
-27
lines changed

newrelic/common/package_version_utils.py

+18-14
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
# limitations under the License.
1414

1515
import sys
16+
import warnings
1617

1718
try:
1819
from functools import cache as _cache_package_versions
@@ -110,6 +111,23 @@ def _get_package_version(name):
110111
module = sys.modules.get(name, None)
111112
version = None
112113

114+
with warnings.catch_warnings(record=True):
115+
for attr in VERSION_ATTRS:
116+
try:
117+
version = getattr(module, attr, None)
118+
119+
# In certain cases like importlib_metadata.version, version is a callable
120+
# function.
121+
if callable(version):
122+
continue
123+
124+
# Cast any version specified as a list into a tuple.
125+
version = tuple(version) if isinstance(version, list) else version
126+
if version not in NULL_VERSIONS:
127+
return version
128+
except Exception:
129+
pass
130+
113131
# importlib was introduced into the standard library starting in Python3.8.
114132
if "importlib" in sys.modules and hasattr(sys.modules["importlib"], "metadata"):
115133
try:
@@ -126,20 +144,6 @@ def _get_package_version(name):
126144
except Exception:
127145
pass
128146

129-
for attr in VERSION_ATTRS:
130-
try:
131-
version = getattr(module, attr, None)
132-
# In certain cases like importlib_metadata.version, version is a callable
133-
# function.
134-
if callable(version):
135-
continue
136-
# Cast any version specified as a list into a tuple.
137-
version = tuple(version) if isinstance(version, list) else version
138-
if version not in NULL_VERSIONS:
139-
return version
140-
except Exception:
141-
pass
142-
143147
if "pkg_resources" in sys.modules:
144148
try:
145149
version = sys.modules["pkg_resources"].get_distribution(name).version

tests/agent_unittests/test_package_version_utils.py

+28-13
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,10 @@
1313
# limitations under the License.
1414

1515
import sys
16+
import warnings
1617

1718
import pytest
19+
import six
1820
from testing_support.validators.validate_function_called import validate_function_called
1921

2022
from newrelic.common.package_version_utils import (
@@ -66,30 +68,26 @@ def cleared_package_version_cache():
6668
("version_tuple", [3, 1, "0b2"], "3.1.0b2"),
6769
),
6870
)
69-
def test_get_package_version(attr, value, expected_value):
71+
def test_get_package_version(monkeypatch, attr, value, expected_value):
7072
# There is no file/module here, so we monkeypatch
7173
# pytest instead for our purposes
72-
setattr(pytest, attr, value)
74+
monkeypatch.setattr(pytest, attr, value, raising=False)
7375
version = get_package_version("pytest")
7476
assert version == expected_value
75-
delattr(pytest, attr)
7677

7778

7879
# This test only works on Python 3.7
7980
@SKIP_IF_IMPORTLIB_METADATA
80-
def test_skips_version_callables():
81+
def test_skips_version_callables(monkeypatch):
8182
# There is no file/module here, so we monkeypatch
8283
# pytest instead for our purposes
83-
setattr(pytest, "version", lambda x: "1.2.3.4")
84-
setattr(pytest, "version_tuple", [3, 1, "0b2"])
84+
monkeypatch.setattr(pytest, "version", lambda x: "1.2.3.4", raising=False)
85+
monkeypatch.setattr(pytest, "version_tuple", [3, 1, "0b2"], raising=False)
8586

8687
version = get_package_version("pytest")
8788

8889
assert version == "3.1.0b2"
8990

90-
delattr(pytest, "version")
91-
delattr(pytest, "version_tuple")
92-
9391

9492
# This test only works on Python 3.7
9593
@SKIP_IF_IMPORTLIB_METADATA
@@ -102,13 +100,12 @@ def test_skips_version_callables():
102100
("version_tuple", [3, 1, "0b2"], (3, 1, "0b2")),
103101
),
104102
)
105-
def test_get_package_version_tuple(attr, value, expected_value):
103+
def test_get_package_version_tuple(monkeypatch, attr, value, expected_value):
106104
# There is no file/module here, so we monkeypatch
107105
# pytest instead for our purposes
108-
setattr(pytest, attr, value)
106+
monkeypatch.setattr(pytest, attr, value, raising=False)
109107
version = get_package_version_tuple("pytest")
110108
assert version == expected_value
111-
delattr(pytest, attr)
112109

113110

114111
@SKIP_IF_NOT_IMPORTLIB_METADATA
@@ -132,10 +129,28 @@ def test_pkg_resources_metadata():
132129
assert version not in NULL_VERSIONS, version
133130

134131

132+
def _getattr_deprecation_warning(attr):
133+
if attr == "__version__":
134+
warnings.warn("Testing deprecation warnings.", DeprecationWarning)
135+
return "3.2.1"
136+
else:
137+
raise NotImplementedError()
138+
139+
140+
@pytest.mark.skipif(six.PY2, reason="Can't add Deprecation in __version__ in Python 2.")
141+
def test_deprecation_warning_suppression(monkeypatch, recwarn):
142+
# Add fake module to be deleted later
143+
monkeypatch.setattr(pytest, "__getattr__", _getattr_deprecation_warning, raising=False)
144+
145+
assert get_package_version("pytest") == "3.2.1"
146+
147+
assert not recwarn.list, "Warnings not suppressed."
148+
149+
135150
def test_version_caching(monkeypatch):
136151
# Add fake module to be deleted later
137152
sys.modules["mymodule"] = sys.modules["pytest"]
138-
setattr(pytest, "__version__", "1.0.0")
153+
monkeypatch.setattr(pytest, "__version__", "1.0.0", raising=False)
139154
version = get_package_version("mymodule")
140155
assert version not in NULL_VERSIONS, version
141156

0 commit comments

Comments
 (0)