Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove deprecated constructs #491

Merged
merged 2 commits into from
Jun 23, 2024
Merged
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
2 changes: 0 additions & 2 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,4 @@
('py:class', 'importlib_metadata._meta._T'),
# Workaround for #435
('py:class', '_T'),
# Other workarounds
('py:class', 'importlib_metadata.DeprecatedNonAbstract'),
]
23 changes: 1 addition & 22 deletions importlib_metadata/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
import pathlib
import operator
import textwrap
import warnings
import functools
import itertools
import posixpath
Expand Down Expand Up @@ -334,27 +333,7 @@ def __repr__(self) -> str:
return f'<FileHash mode: {self.mode} value: {self.value}>'


class DeprecatedNonAbstract:
# Required until Python 3.14
def __new__(cls, *args, **kwargs):
all_names = {
name for subclass in inspect.getmro(cls) for name in vars(subclass)
}
abstract = {
name
for name in all_names
if getattr(getattr(cls, name), '__isabstractmethod__', False)
}
if abstract:
warnings.warn(
f"Unimplemented abstract methods {abstract}",
DeprecationWarning,
stacklevel=2,
)
return super().__new__(cls)


class Distribution(DeprecatedNonAbstract):
class Distribution(metaclass=abc.ABCMeta):
"""
An abstract Python distribution package.

Expand Down
23 changes: 8 additions & 15 deletions importlib_metadata/_adapters.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,8 @@
import functools
import warnings
import re
import textwrap
import email.message

from ._text import FoldedCase
from ._compat import pypy_partial


# Do not remove prior to 2024-01-01 or Python 3.14
_warn = functools.partial(
warnings.warn,
"Implicit None on return values is deprecated and will raise KeyErrors.",
DeprecationWarning,
stacklevel=pypy_partial(2),
)


class Message(email.message.Message):
Expand Down Expand Up @@ -53,12 +41,17 @@ def __iter__(self):

def __getitem__(self, item):
"""
Warn users that a ``KeyError`` can be expected when a
missing key is supplied. Ref python/importlib_metadata#371.
Override parent behavior to typical dict behavior.

``email.message.Message`` will emit None values for missing
keys. Typical mappings, including this ``Message``, will raise
a key error for missing keys.

Ref python/importlib_metadata#371.
"""
res = super().__getitem__(item)
if res is None:
_warn()
raise KeyError(item)
return res

def _repair_headers(self):
Expand Down
1 change: 1 addition & 0 deletions newsfragments/+8256a9d7.removal.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Removed deprecated support for Distribution subclasses not implementing abstract methods.
1 change: 1 addition & 0 deletions newsfragments/371.removal.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Message.__getitem__ now raises a KeyError on missing keys.
17 changes: 4 additions & 13 deletions tests/test_api.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import re
import textwrap
import unittest
import warnings
import importlib
import contextlib

from . import fixtures
from importlib_metadata import (
Expand All @@ -18,13 +16,6 @@
)


@contextlib.contextmanager
def suppress_known_deprecation():
with warnings.catch_warnings(record=True) as ctx:
warnings.simplefilter('default', category=DeprecationWarning)
yield ctx


class APITests(
fixtures.EggInfoPkg,
fixtures.EggInfoPkgPipInstalledNoToplevel,
Expand Down Expand Up @@ -157,13 +148,13 @@ def test_importlib_metadata_version(self):
resolved = version('importlib-metadata')
assert re.match(self.version_pattern, resolved)

def test_missing_key_legacy(self):
def test_missing_key(self):
"""
Requesting a missing key will still return None, but warn.
Requesting a missing key raises KeyError.
"""
md = metadata('distinfo-pkg')
with suppress_known_deprecation():
assert md['does-not-exist'] is None
with self.assertRaises(KeyError):
md['does-not-exist']

def test_get_key(self):
"""
Expand Down
13 changes: 0 additions & 13 deletions tests/test_main.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,13 @@
import re
import pickle
import unittest
import warnings
import importlib
import importlib_metadata
import contextlib
from .compat.py39 import os_helper

import pyfakefs.fake_filesystem_unittest as ffs

from . import fixtures
from ._context import suppress
from ._path import Symlink
from importlib_metadata import (
Distribution,
Expand All @@ -25,13 +22,6 @@
)


@contextlib.contextmanager
def suppress_known_deprecation():
with warnings.catch_warnings(record=True) as ctx:
warnings.simplefilter('default', category=DeprecationWarning)
yield ctx


class BasicTests(fixtures.DistInfoPkg, unittest.TestCase):
version_pattern = r'\d+\.\d+(\.\d)?'

Expand All @@ -56,9 +46,6 @@ def test_package_not_found_mentions_metadata(self):

assert "metadata" in str(ctx.exception)

# expected to fail until ABC is enforced
@suppress(AssertionError)
@suppress_known_deprecation()
def test_abc_enforced(self):
with self.assertRaises(TypeError):
type('DistributionSubclass', (Distribution,), {})()
Expand Down
Loading