Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .changelog/5231.fixed
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Suppress ``SelectableGroups`` ``DeprecationWarning`` emitted by
``importlib.metadata.entry_points()`` on Python 3.10 and 3.11 when
``opentelemetry.context`` (or any module that calls ``entry_points()``) is
imported.
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@

- https://github.com/open-telemetry/opentelemetry-python/pull/4735
- https://github.com/open-telemetry/opentelemetry-python/pull/5203
- https://github.com/open-telemetry/opentelemetry-python/issues/5231
"""

import warnings
from functools import cache
from importlib.metadata import (
Distribution,
Expand All @@ -34,7 +36,19 @@ def _as_entry_points(eps: Any) -> EntryPoints:

@cache
def _original_entry_points_cached() -> EntryPoints:
return _as_entry_points(original_entry_points())
# On Python 3.10 and 3.11, calling entry_points() without arguments returns
# a SelectableGroups object. Its .values() method emits a DeprecationWarning
# ("SelectableGroups dict interface is deprecated. Use select.") that cannot
# be avoided while caching all entry points in a single upfront call.
# The @cache decorator ensures this path runs only once per interpreter
# session, so suppressing the warning here is both safe and targeted.
with warnings.catch_warnings():
warnings.filterwarnings(
"ignore",
category=DeprecationWarning,
message="SelectableGroups dict interface is deprecated",
)
return _as_entry_points(original_entry_points())


def entry_points(**params) -> EntryPoints:
Expand Down
35 changes: 35 additions & 0 deletions opentelemetry-api/tests/util/test__importlib_metadata.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
# Copyright The OpenTelemetry Authors
# SPDX-License-Identifier: Apache-2.0

import warnings
from unittest import TestCase

from opentelemetry.metrics import MeterProvider
from opentelemetry.util._importlib_metadata import (
EntryPoint,
EntryPoints,
_as_entry_points,
_original_entry_points_cached,
version,
)
from opentelemetry.util._importlib_metadata import (
Expand Down Expand Up @@ -102,6 +104,39 @@ def test_uniform_behavior(self):

self.assertIsInstance(version("opentelemetry-api"), str)

def test_no_deprecation_warning_from_entry_points(self):
"""entry_points() must not emit DeprecationWarning on any supported Python version.

On Python 3.10/3.11, importlib.metadata.entry_points() called without
arguments returns a SelectableGroups object. Accessing its .values()
attribute emits ``DeprecationWarning: SelectableGroups dict interface is
deprecated. Use select.``, which breaks projects that run their test
suites with ``-W error``. The wrapper in _importlib_metadata.py must
suppress that warning before it propagates.

Regression test for https://github.com/open-telemetry/opentelemetry-python/issues/5231
"""
with warnings.catch_warnings(record=True) as caught:
warnings.simplefilter("always")
# Clear the cache so the cached path is exercised fresh inside the
# catch_warnings context, making the assertion reliable.
_original_entry_points_cached.cache_clear()
importlib_metadata_entry_points()
# Restore cache state for the rest of the test run.
_original_entry_points_cached.cache_clear()

selectable_groups_warnings = [
w
for w in caught
if issubclass(w.category, DeprecationWarning)
and "SelectableGroups" in str(w.message)
]
self.assertEqual(
selectable_groups_warnings,
[],
"entry_points() must not emit a SelectableGroups DeprecationWarning",
)

def test_as_entry_points_selectable_groups_compat(self):
"""Test that _as_entry_points correctly normalizes dict-like SelectableGroups
(returned by importlib.metadata.entry_points() in Python 3.10) into EntryPoints.
Expand Down
Loading