Skip to content

Commit

Permalink
Deprecate construction of Distribution and subclasses without impleme…
Browse files Browse the repository at this point in the history
…nting abstract methods. Fixes #422.
  • Loading branch information
jaraco committed Apr 17, 2023
1 parent 6ebb1f9 commit 95654e0
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 1 deletion.
21 changes: 20 additions & 1 deletion importlib_metadata/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,26 @@ def __repr__(self):
return f'<FileHash mode: {self.mode} value: {self.value}>'


class Distribution(metaclass=abc.ABCMeta):
class DeprecatedNonAbstract:
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):
"""A Python distribution package."""

@abc.abstractmethod
Expand Down
13 changes: 13 additions & 0 deletions tests/_context.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import contextlib


# from jaraco.context 4.3
class suppress(contextlib.suppress, contextlib.ContextDecorator):
"""
A version of contextlib.suppress with decorator support.
>>> @suppress(KeyError)
... def key_error():
... {}['']
>>> key_error()
"""
13 changes: 13 additions & 0 deletions tests/test_main.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
import re
import pickle
import unittest
import warnings
import importlib
import importlib_metadata
import contextlib
import itertools
import pyfakefs.fake_filesystem_unittest as ffs

from . import fixtures
from ._context import suppress
from importlib_metadata import (
Distribution,
EntryPoint,
Expand All @@ -20,6 +23,13 @@
)


@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 @@ -44,6 +54,9 @@ 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

0 comments on commit 95654e0

Please sign in to comment.