Revert "gh-132947: Apply changes from importlib_metadata 8.7 (#137885)" (#137924)

This reverts commit 5292fc00f29df60af82b55fca6c8b360e3667f96.
diff --git a/Lib/importlib/metadata/__init__.py b/Lib/importlib/metadata/__init__.py
index 1e2cea4..b59587e 100644
--- a/Lib/importlib/metadata/__init__.py
+++ b/Lib/importlib/metadata/__init__.py
@@ -1,40 +1,33 @@
-"""
-APIs exposing metadata from third-party Python packages.
-
-This codebase is shared between importlib.metadata in the stdlib
-and importlib_metadata in PyPI. See
-https://github.com/python/importlib_metadata/wiki/Development-Methodology
-for more detail.
-"""
-
 from __future__ import annotations
 
+import os
+import re
 import abc
-import collections
+import sys
+import json
 import email
+import types
+import inspect
+import pathlib
+import zipfile
+import operator
+import textwrap
 import functools
 import itertools
-import operator
-import os
-import pathlib
 import posixpath
-import re
-import sys
-import textwrap
-import types
-from collections.abc import Iterable, Mapping
-from contextlib import suppress
-from importlib import import_module
-from importlib.abc import MetaPathFinder
-from itertools import starmap
-from typing import Any
+import collections
 
 from . import _meta
 from ._collections import FreezableDefaultDict, Pair
 from ._functools import method_cache, pass_none
 from ._itertools import always_iterable, bucket, unique_everseen
 from ._meta import PackageMetadata, SimplePath
-from ._typing import md_none
+
+from contextlib import suppress
+from importlib import import_module
+from importlib.abc import MetaPathFinder
+from itertools import starmap
+from typing import Any, Iterable, List, Mapping, Match, Optional, Set, cast
 
 __all__ = [
     'Distribution',
@@ -60,7 +53,7 @@ def __str__(self) -> str:
         return f"No package metadata was found for {self.name}"
 
     @property
-    def name(self) -> str:  # type: ignore[override] # make readonly
+    def name(self) -> str:  # type: ignore[override]
         (name,) = self.args
         return name
 
@@ -130,12 +123,6 @@ def valid(line: str):
         return line and not line.startswith('#')
 
 
-class _EntryPointMatch(types.SimpleNamespace):
-    module: str
-    attr: str
-    extras: str
-
-
 class EntryPoint:
     """An entry point as defined by Python packaging conventions.
 
@@ -151,30 +138,6 @@ class EntryPoint:
     'attr'
     >>> ep.extras
     ['extra1', 'extra2']
-
-    If the value package or module are not valid identifiers, a
-    ValueError is raised on access.
-
-    >>> EntryPoint(name=None, group=None, value='invalid-name').module
-    Traceback (most recent call last):
-    ...
-    ValueError: ('Invalid object reference...invalid-name...
-    >>> EntryPoint(name=None, group=None, value='invalid-name').attr
-    Traceback (most recent call last):
-    ...
-    ValueError: ('Invalid object reference...invalid-name...
-    >>> EntryPoint(name=None, group=None, value='invalid-name').extras
-    Traceback (most recent call last):
-    ...
-    ValueError: ('Invalid object reference...invalid-name...
-
-    The same thing happens on construction.
-
-    >>> EntryPoint(name=None, group=None, value='invalid-name')
-    Traceback (most recent call last):
-    ...
-    ValueError: ('Invalid object reference...invalid-name...
-
     """
 
     pattern = re.compile(
@@ -202,44 +165,38 @@ class EntryPoint:
     value: str
     group: str
 
-    dist: Distribution | None = None
+    dist: Optional[Distribution] = None
 
     def __init__(self, name: str, value: str, group: str) -> None:
         vars(self).update(name=name, value=value, group=group)
-        self.module
 
     def load(self) -> Any:
         """Load the entry point from its definition. If only a module
         is indicated by the value, return that module. Otherwise,
         return the named object.
         """
-        module = import_module(self.module)
-        attrs = filter(None, (self.attr or '').split('.'))
+        match = cast(Match, self.pattern.match(self.value))
+        module = import_module(match.group('module'))
+        attrs = filter(None, (match.group('attr') or '').split('.'))
         return functools.reduce(getattr, attrs, module)
 
     @property
     def module(self) -> str:
-        return self._match.module
+        match = self.pattern.match(self.value)
+        assert match is not None
+        return match.group('module')
 
     @property
     def attr(self) -> str:
-        return self._match.attr
+        match = self.pattern.match(self.value)
+        assert match is not None
+        return match.group('attr')
 
     @property
-    def extras(self) -> list[str]:
-        return re.findall(r'\w+', self._match.extras or '')
-
-    @functools.cached_property
-    def _match(self) -> _EntryPointMatch:
+    def extras(self) -> List[str]:
         match = self.pattern.match(self.value)
-        if not match:
-            raise ValueError(
-                'Invalid object reference. '
-                'See https://packaging.python.org'
-                '/en/latest/specifications/entry-points/#data-model',
-                self.value,
-            )
-        return _EntryPointMatch(**match.groupdict())
+        assert match is not None
+        return re.findall(r'\w+', match.group('extras') or '')
 
     def _for(self, dist):
         vars(self).update(dist=dist)
@@ -265,26 +222,9 @@ def matches(self, **params):
         >>> ep.matches(attr='bong')
         True
         """
-        self._disallow_dist(params)
         attrs = (getattr(self, param) for param in params)
         return all(map(operator.eq, params.values(), attrs))
 
-    @staticmethod
-    def _disallow_dist(params):
-        """
-        Querying by dist is not allowed (dist objects are not comparable).
-        >>> EntryPoint(name='fan', value='fav', group='fag').matches(dist='foo')
-        Traceback (most recent call last):
-        ...
-        ValueError: "dist" is not suitable for matching...
-        """
-        if "dist" in params:
-            raise ValueError(
-                '"dist" is not suitable for matching. '
-                "Instead, use Distribution.entry_points.select() on a "
-                "located distribution."
-            )
-
     def _key(self):
         return self.name, self.value, self.group
 
@@ -314,7 +254,7 @@ class EntryPoints(tuple):
 
     __slots__ = ()
 
-    def __getitem__(self, name: str) -> EntryPoint:  # type: ignore[override] # Work with str instead of int
+    def __getitem__(self, name: str) -> EntryPoint:  # type: ignore[override]
         """
         Get the EntryPoint in self matching name.
         """
@@ -338,14 +278,14 @@ def select(self, **params) -> EntryPoints:
         return EntryPoints(ep for ep in self if ep.matches(**params))
 
     @property
-    def names(self) -> set[str]:
+    def names(self) -> Set[str]:
         """
         Return the set of all names of all entry points.
         """
         return {ep.name for ep in self}
 
     @property
-    def groups(self) -> set[str]:
+    def groups(self) -> Set[str]:
         """
         Return the set of all groups of all entry points.
         """
@@ -366,11 +306,11 @@ def _from_text(text):
 class PackagePath(pathlib.PurePosixPath):
     """A reference to a path in a package"""
 
-    hash: FileHash | None
+    hash: Optional[FileHash]
     size: int
     dist: Distribution
 
-    def read_text(self, encoding: str = 'utf-8') -> str:
+    def read_text(self, encoding: str = 'utf-8') -> str:  # type: ignore[override]
         return self.locate().read_text(encoding=encoding)
 
     def read_binary(self) -> bytes:
@@ -401,7 +341,7 @@ class Distribution(metaclass=abc.ABCMeta):
     """
 
     @abc.abstractmethod
-    def read_text(self, filename) -> str | None:
+    def read_text(self, filename) -> Optional[str]:
         """Attempt to load metadata file given by the name.
 
         Python distribution metadata is organized by blobs of text
@@ -428,17 +368,6 @@ def locate_file(self, path: str | os.PathLike[str]) -> SimplePath:
         """
         Given a path to a file in this distribution, return a SimplePath
         to it.
-
-        This method is used by callers of ``Distribution.files()`` to
-        locate files within the distribution. If it's possible for a
-        Distribution to represent files in the distribution as
-        ``SimplePath`` objects, it should implement this method
-        to resolve such objects.
-
-        Some Distribution providers may elect not to resolve SimplePath
-        objects within the distribution by raising a
-        NotImplementedError, but consumers of such a Distribution would
-        be unable to invoke ``Distribution.files()``.
         """
 
     @classmethod
@@ -461,7 +390,7 @@ def from_name(cls, name: str) -> Distribution:
 
     @classmethod
     def discover(
-        cls, *, context: DistributionFinder.Context | None = None, **kwargs
+        cls, *, context: Optional[DistributionFinder.Context] = None, **kwargs
     ) -> Iterable[Distribution]:
         """Return an iterable of Distribution objects for all packages.
 
@@ -507,7 +436,7 @@ def _discover_resolvers():
         return filter(None, declared)
 
     @property
-    def metadata(self) -> _meta.PackageMetadata | None:
+    def metadata(self) -> _meta.PackageMetadata:
         """Return the parsed metadata for this Distribution.
 
         The returned object will have keys that name the various bits of
@@ -517,8 +446,10 @@ def metadata(self) -> _meta.PackageMetadata | None:
         Custom providers may provide the METADATA file or override this
         property.
         """
+        # deferred for performance (python/cpython#109829)
+        from . import _adapters
 
-        text = (
+        opt_text = (
             self.read_text('METADATA')
             or self.read_text('PKG-INFO')
             # This last clause is here to support old egg-info files.  Its
@@ -526,20 +457,13 @@ def metadata(self) -> _meta.PackageMetadata | None:
             # (which points to the egg-info file) attribute unchanged.
             or self.read_text('')
         )
-        return self._assemble_message(text)
-
-    @staticmethod
-    @pass_none
-    def _assemble_message(text: str) -> _meta.PackageMetadata:
-        # deferred for performance (python/cpython#109829)
-        from . import _adapters
-
+        text = cast(str, opt_text)
         return _adapters.Message(email.message_from_string(text))
 
     @property
     def name(self) -> str:
         """Return the 'Name' metadata for the distribution package."""
-        return md_none(self.metadata)['Name']
+        return self.metadata['Name']
 
     @property
     def _normalized_name(self):
@@ -549,7 +473,7 @@ def _normalized_name(self):
     @property
     def version(self) -> str:
         """Return the 'Version' metadata for the distribution package."""
-        return md_none(self.metadata)['Version']
+        return self.metadata['Version']
 
     @property
     def entry_points(self) -> EntryPoints:
@@ -562,7 +486,7 @@ def entry_points(self) -> EntryPoints:
         return EntryPoints._from_text_for(self.read_text('entry_points.txt'), self)
 
     @property
-    def files(self) -> list[PackagePath] | None:
+    def files(self) -> Optional[List[PackagePath]]:
         """Files in this distribution.
 
         :return: List of PackagePath for this distribution or None
@@ -655,7 +579,7 @@ def _read_files_egginfo_sources(self):
         return text and map('"{}"'.format, text.splitlines())
 
     @property
-    def requires(self) -> list[str] | None:
+    def requires(self) -> Optional[List[str]]:
         """Generated requirements specified for this Distribution"""
         reqs = self._read_dist_info_reqs() or self._read_egg_info_reqs()
         return reqs and list(reqs)
@@ -711,9 +635,6 @@ def origin(self):
         return self._load_json('direct_url.json')
 
     def _load_json(self, filename):
-        # Deferred for performance (python/importlib_metadata#503)
-        import json
-
         return pass_none(json.loads)(
             self.read_text(filename),
             object_hook=lambda data: types.SimpleNamespace(**data),
@@ -761,7 +682,7 @@ def __init__(self, **kwargs):
             vars(self).update(kwargs)
 
         @property
-        def path(self) -> list[str]:
+        def path(self) -> List[str]:
             """
             The sequence of directory path that a distribution finder
             should search.
@@ -798,7 +719,7 @@ class FastPath:
     True
     """
 
-    @functools.lru_cache()  # type: ignore[misc]
+    @functools.lru_cache()  # type: ignore
     def __new__(cls, root):
         return super().__new__(cls)
 
@@ -816,9 +737,6 @@ def children(self):
         return []
 
     def zip_children(self):
-        # deferred for performance (python/importlib_metadata#502)
-        import zipfile
-
         zip_path = zipfile.Path(self.root)
         names = zip_path.root.namelist()
         self.joinpath = zip_path.joinpath
@@ -913,7 +831,7 @@ class Prepared:
     normalized = None
     legacy_normalized = None
 
-    def __init__(self, name: str | None):
+    def __init__(self, name: Optional[str]):
         self.name = name
         if name is None:
             return
@@ -976,7 +894,7 @@ def __init__(self, path: SimplePath) -> None:
         """
         self._path = path
 
-    def read_text(self, filename: str | os.PathLike[str]) -> str | None:
+    def read_text(self, filename: str | os.PathLike[str]) -> Optional[str]:
         with suppress(
             FileNotFoundError,
             IsADirectoryError,
@@ -1040,7 +958,7 @@ def distributions(**kwargs) -> Iterable[Distribution]:
     return Distribution.discover(**kwargs)
 
 
-def metadata(distribution_name: str) -> _meta.PackageMetadata | None:
+def metadata(distribution_name: str) -> _meta.PackageMetadata:
     """Get the metadata for the named package.
 
     :param distribution_name: The name of the distribution package to query.
@@ -1083,7 +1001,7 @@ def entry_points(**params) -> EntryPoints:
     return EntryPoints(eps).select(**params)
 
 
-def files(distribution_name: str) -> list[PackagePath] | None:
+def files(distribution_name: str) -> Optional[List[PackagePath]]:
     """Return a list of files for the named package.
 
     :param distribution_name: The name of the distribution package to query.
@@ -1092,7 +1010,7 @@ def files(distribution_name: str) -> list[PackagePath] | None:
     return distribution(distribution_name).files
 
 
-def requires(distribution_name: str) -> list[str] | None:
+def requires(distribution_name: str) -> Optional[List[str]]:
     """
     Return a list of requirements for the named package.
 
@@ -1102,7 +1020,7 @@ def requires(distribution_name: str) -> list[str] | None:
     return distribution(distribution_name).requires
 
 
-def packages_distributions() -> Mapping[str, list[str]]:
+def packages_distributions() -> Mapping[str, List[str]]:
     """
     Return a mapping of top-level packages to their
     distributions.
@@ -1115,7 +1033,7 @@ def packages_distributions() -> Mapping[str, list[str]]:
     pkg_to_dist = collections.defaultdict(list)
     for dist in distributions():
         for pkg in _top_level_declared(dist) or _top_level_inferred(dist):
-            pkg_to_dist[pkg].append(md_none(dist.metadata)['Name'])
+            pkg_to_dist[pkg].append(dist.metadata['Name'])
     return dict(pkg_to_dist)
 
 
@@ -1123,7 +1041,7 @@ def _top_level_declared(dist):
     return (dist.read_text('top_level.txt') or '').split()
 
 
-def _topmost(name: PackagePath) -> str | None:
+def _topmost(name: PackagePath) -> Optional[str]:
     """
     Return the top-most parent as long as there is a parent.
     """
@@ -1149,10 +1067,11 @@ def _get_toplevel_name(name: PackagePath) -> str:
     >>> _get_toplevel_name(PackagePath('foo.dist-info'))
     'foo.dist-info'
     """
-    # Defer import of inspect for performance (python/cpython#118761)
-    import inspect
-
-    return _topmost(name) or inspect.getmodulename(name) or str(name)
+    return _topmost(name) or (
+        # python/typeshed#10328
+        inspect.getmodulename(name)  # type: ignore
+        or str(name)
+    )
 
 
 def _top_level_inferred(dist):
diff --git a/Lib/importlib/metadata/_adapters.py b/Lib/importlib/metadata/_adapters.py
index f5b30dd..6223263 100644
--- a/Lib/importlib/metadata/_adapters.py
+++ b/Lib/importlib/metadata/_adapters.py
@@ -1,58 +1,11 @@
-import email.message
-import email.policy
 import re
 import textwrap
+import email.message
 
 from ._text import FoldedCase
 
 
-class RawPolicy(email.policy.EmailPolicy):
-    def fold(self, name, value):
-        folded = self.linesep.join(
-            textwrap.indent(value, prefix=' ' * 8, predicate=lambda line: True)
-            .lstrip()
-            .splitlines()
-        )
-        return f'{name}: {folded}{self.linesep}'
-
-
 class Message(email.message.Message):
-    r"""
-    Specialized Message subclass to handle metadata naturally.
-
-    Reads values that may have newlines in them and converts the
-    payload to the Description.
-
-    >>> msg_text = textwrap.dedent('''
-    ...     Name: Foo
-    ...     Version: 3.0
-    ...     License: blah
-    ...             de-blah
-    ...     <BLANKLINE>
-    ...     First line of description.
-    ...     Second line of description.
-    ...     <BLANKLINE>
-    ...     Fourth line!
-    ...     ''').lstrip().replace('<BLANKLINE>', '')
-    >>> msg = Message(email.message_from_string(msg_text))
-    >>> msg['Description']
-    'First line of description.\nSecond line of description.\n\nFourth line!\n'
-
-    Message should render even if values contain newlines.
-
-    >>> print(msg)
-    Name: Foo
-    Version: 3.0
-    License: blah
-            de-blah
-    Description: First line of description.
-            Second line of description.
-    <BLANKLINE>
-            Fourth line!
-    <BLANKLINE>
-    <BLANKLINE>
-    """
-
     multiple_use_keys = set(
         map(
             FoldedCase,
@@ -104,20 +57,15 @@ def __getitem__(self, item):
     def _repair_headers(self):
         def redent(value):
             "Correct for RFC822 indentation"
-            indent = ' ' * 8
-            if not value or '\n' + indent not in value:
+            if not value or '\n' not in value:
                 return value
-            return textwrap.dedent(indent + value)
+            return textwrap.dedent(' ' * 8 + value)
 
         headers = [(key, redent(value)) for key, value in vars(self)['_headers']]
         if self._payload:
             headers.append(('Description', self.get_payload()))
-            self.set_payload('')
         return headers
 
-    def as_string(self):
-        return super().as_string(policy=RawPolicy())
-
     @property
     def json(self):
         """
diff --git a/Lib/importlib/metadata/_collections.py b/Lib/importlib/metadata/_collections.py
index fc5045d..cf0954e 100644
--- a/Lib/importlib/metadata/_collections.py
+++ b/Lib/importlib/metadata/_collections.py
@@ -1,5 +1,4 @@
 import collections
-import typing
 
 
 # from jaraco.collections 3.3
@@ -25,10 +24,7 @@ def freeze(self):
         self._frozen = lambda key: self.default_factory()
 
 
-class Pair(typing.NamedTuple):
-    name: str
-    value: str
-
+class Pair(collections.namedtuple('Pair', 'name value')):
     @classmethod
     def parse(cls, text):
         return cls(*map(str.strip, text.split("=", 1)))
diff --git a/Lib/importlib/metadata/_functools.py b/Lib/importlib/metadata/_functools.py
index 5dda6a2..71f66bd 100644
--- a/Lib/importlib/metadata/_functools.py
+++ b/Lib/importlib/metadata/_functools.py
@@ -1,5 +1,5 @@
-import functools
 import types
+import functools
 
 
 # from jaraco.functools 3.3
diff --git a/Lib/importlib/metadata/_meta.py b/Lib/importlib/metadata/_meta.py
index 0c20eff..1927d0f 100644
--- a/Lib/importlib/metadata/_meta.py
+++ b/Lib/importlib/metadata/_meta.py
@@ -1,13 +1,9 @@
 from __future__ import annotations
 
 import os
-from collections.abc import Iterator
-from typing import (
-    Any,
-    Protocol,
-    TypeVar,
-    overload,
-)
+from typing import Protocol
+from typing import Any, Dict, Iterator, List, Optional, TypeVar, Union, overload
+
 
 _T = TypeVar("_T")
 
@@ -24,25 +20,25 @@ def __iter__(self) -> Iterator[str]: ...  # pragma: no cover
     @overload
     def get(
         self, name: str, failobj: None = None
-    ) -> str | None: ...  # pragma: no cover
+    ) -> Optional[str]: ...  # pragma: no cover
 
     @overload
-    def get(self, name: str, failobj: _T) -> str | _T: ...  # pragma: no cover
+    def get(self, name: str, failobj: _T) -> Union[str, _T]: ...  # pragma: no cover
 
     # overload per python/importlib_metadata#435
     @overload
     def get_all(
         self, name: str, failobj: None = None
-    ) -> list[Any] | None: ...  # pragma: no cover
+    ) -> Optional[List[Any]]: ...  # pragma: no cover
 
     @overload
-    def get_all(self, name: str, failobj: _T) -> list[Any] | _T:
+    def get_all(self, name: str, failobj: _T) -> Union[List[Any], _T]:
         """
         Return all values associated with a possibly multi-valued key.
         """
 
     @property
-    def json(self) -> dict[str, str | list[str]]:
+    def json(self) -> Dict[str, Union[str, List[str]]]:
         """
         A JSON-compatible form of the metadata.
         """
@@ -54,11 +50,11 @@ class SimplePath(Protocol):
     """
 
     def joinpath(
-        self, other: str | os.PathLike[str]
+        self, other: Union[str, os.PathLike[str]]
     ) -> SimplePath: ...  # pragma: no cover
 
     def __truediv__(
-        self, other: str | os.PathLike[str]
+        self, other: Union[str, os.PathLike[str]]
     ) -> SimplePath: ...  # pragma: no cover
 
     @property
diff --git a/Lib/importlib/metadata/_typing.py b/Lib/importlib/metadata/_typing.py
deleted file mode 100644
index 32b1d2b..0000000
--- a/Lib/importlib/metadata/_typing.py
+++ /dev/null
@@ -1,15 +0,0 @@
-import functools
-import typing
-
-from ._meta import PackageMetadata
-
-md_none = functools.partial(typing.cast, PackageMetadata)
-"""
-Suppress type errors for optional metadata.
-
-Although Distribution.metadata can return None when metadata is corrupt
-and thus None, allow callers to assume it's not None and crash if
-that's the case.
-
-# python/importlib_metadata#493
-"""
diff --git a/Lib/test/test_importlib/metadata/_path.py b/Lib/test/test_importlib/metadata/_path.py
index e63d889..b3cfb9c 100644
--- a/Lib/test/test_importlib/metadata/_path.py
+++ b/Lib/test/test_importlib/metadata/_path.py
@@ -1,14 +1,9 @@
-# from jaraco.path 3.7.2
-
-from __future__ import annotations
+# from jaraco.path 3.7
 
 import functools
 import pathlib
-from collections.abc import Mapping
-from typing import TYPE_CHECKING, Protocol, Union, runtime_checkable
-
-if TYPE_CHECKING:
-    from typing_extensions import Self
+from typing import Dict, Protocol, Union
+from typing import runtime_checkable
 
 
 class Symlink(str):
@@ -17,25 +12,29 @@ class Symlink(str):
     """
 
 
-FilesSpec = Mapping[str, Union[str, bytes, Symlink, 'FilesSpec']]
+FilesSpec = Dict[str, Union[str, bytes, Symlink, 'FilesSpec']]  # type: ignore
 
 
 @runtime_checkable
 class TreeMaker(Protocol):
-    def __truediv__(self, other, /) -> Self: ...
-    def mkdir(self, *, exist_ok) -> object: ...
-    def write_text(self, content, /, *, encoding) -> object: ...
-    def write_bytes(self, content, /) -> object: ...
-    def symlink_to(self, target, /) -> object: ...
+    def __truediv__(self, *args, **kwargs): ...  # pragma: no cover
+
+    def mkdir(self, **kwargs): ...  # pragma: no cover
+
+    def write_text(self, content, **kwargs): ...  # pragma: no cover
+
+    def write_bytes(self, content): ...  # pragma: no cover
+
+    def symlink_to(self, target): ...  # pragma: no cover
 
 
-def _ensure_tree_maker(obj: str | TreeMaker) -> TreeMaker:
-    return obj if isinstance(obj, TreeMaker) else pathlib.Path(obj)
+def _ensure_tree_maker(obj: Union[str, TreeMaker]) -> TreeMaker:
+    return obj if isinstance(obj, TreeMaker) else pathlib.Path(obj)  # type: ignore
 
 
 def build(
     spec: FilesSpec,
-    prefix: str | TreeMaker = pathlib.Path(),
+    prefix: Union[str, TreeMaker] = pathlib.Path(),  # type: ignore
 ):
     """
     Build a set of files/directories, as described by the spec.
@@ -67,24 +66,23 @@ def build(
 
 
 @functools.singledispatch
-def create(content: str | bytes | FilesSpec, path: TreeMaker) -> None:
+def create(content: Union[str, bytes, FilesSpec], path):
     path.mkdir(exist_ok=True)
-    # Mypy only looks at the signature of the main singledispatch method. So it must contain the complete Union
-    build(content, prefix=path)  # type: ignore[arg-type] # python/mypy#11727
+    build(content, prefix=path)  # type: ignore
 
 
 @create.register
-def _(content: bytes, path: TreeMaker) -> None:
+def _(content: bytes, path):
     path.write_bytes(content)
 
 
 @create.register
-def _(content: str, path: TreeMaker) -> None:
+def _(content: str, path):
     path.write_text(content, encoding='utf-8')
 
 
 @create.register
-def _(content: Symlink, path: TreeMaker) -> None:
+def _(content: Symlink, path):
     path.symlink_to(content)
 
 
diff --git a/Lib/test/test_importlib/metadata/fixtures.py b/Lib/test/test_importlib/metadata/fixtures.py
index 494047d..826b1b3 100644
--- a/Lib/test/test_importlib/metadata/fixtures.py
+++ b/Lib/test/test_importlib/metadata/fixtures.py
@@ -1,11 +1,11 @@
-import contextlib
-import copy
-import functools
-import json
-import pathlib
-import shutil
 import sys
+import copy
+import json
+import shutil
+import pathlib
 import textwrap
+import functools
+import contextlib
 
 from test.support import import_helper
 from test.support import os_helper
@@ -14,10 +14,14 @@
 from . import _path
 from ._path import FilesSpec
 
-if sys.version_info >= (3, 9):
-    from importlib import resources
-else:
-    import importlib_resources as resources
+
+try:
+    from importlib import resources  # type: ignore
+
+    getattr(resources, 'files')
+    getattr(resources, 'as_file')
+except (ImportError, AttributeError):
+    import importlib_resources as resources  # type: ignore
 
 
 @contextlib.contextmanager
diff --git a/Lib/test/test_importlib/metadata/test_api.py b/Lib/test/test_importlib/metadata/test_api.py
index 9f6e12c..813febf 100644
--- a/Lib/test/test_importlib/metadata/test_api.py
+++ b/Lib/test/test_importlib/metadata/test_api.py
@@ -1,8 +1,9 @@
-import importlib
 import re
 import textwrap
 import unittest
+import importlib
 
+from . import fixtures
 from importlib.metadata import (
     Distribution,
     PackageNotFoundError,
@@ -14,8 +15,6 @@
     version,
 )
 
-from . import fixtures
-
 
 class APITests(
     fixtures.EggInfoPkg,
diff --git a/Lib/test/test_importlib/metadata/test_main.py b/Lib/test/test_importlib/metadata/test_main.py
index 83b686b..a0bc822 100644
--- a/Lib/test/test_importlib/metadata/test_main.py
+++ b/Lib/test/test_importlib/metadata/test_main.py
@@ -1,7 +1,8 @@
-import importlib
-import pickle
 import re
+import pickle
 import unittest
+import importlib
+import importlib.metadata
 from test.support import os_helper
 
 try:
@@ -9,6 +10,8 @@
 except ImportError:
     from .stubs import fake_filesystem_unittest as ffs
 
+from . import fixtures
+from ._path import Symlink
 from importlib.metadata import (
     Distribution,
     EntryPoint,
@@ -21,9 +24,6 @@
     version,
 )
 
-from . import fixtures
-from ._path import Symlink
-
 
 class BasicTests(fixtures.DistInfoPkg, unittest.TestCase):
     version_pattern = r'\d+\.\d+(\.\d)?'
@@ -157,16 +157,6 @@ def test_valid_dists_preferred(self):
         dist = Distribution.from_name('foo')
         assert dist.version == "1.0"
 
-    def test_missing_metadata(self):
-        """
-        Dists with a missing metadata file should return None.
-
-        Ref python/importlib_metadata#493.
-        """
-        fixtures.build_files(self.make_pkg('foo-4.3', files={}), self.site_dir)
-        assert Distribution.from_name('foo').metadata is None
-        assert metadata('foo') is None
-
 
 class NonASCIITests(fixtures.OnSysPath, fixtures.SiteDir, unittest.TestCase):
     @staticmethod
diff --git a/Lib/test/test_importlib/metadata/test_zip.py b/Lib/test/test_importlib/metadata/test_zip.py
index fcb649f..276f628 100644
--- a/Lib/test/test_importlib/metadata/test_zip.py
+++ b/Lib/test/test_importlib/metadata/test_zip.py
@@ -1,6 +1,7 @@
 import sys
 import unittest
 
+from . import fixtures
 from importlib.metadata import (
     PackageNotFoundError,
     distribution,
@@ -10,8 +11,6 @@
     version,
 )
 
-from . import fixtures
-
 
 class TestZip(fixtures.ZipFixtures, unittest.TestCase):
     def setUp(self):
diff --git a/Misc/NEWS.d/next/Library/2025-08-17-10-22-31.gh-issue-132947.XR4MJ8.rst b/Misc/NEWS.d/next/Library/2025-08-17-10-22-31.gh-issue-132947.XR4MJ8.rst
deleted file mode 100644
index 8a2b0a4..0000000
--- a/Misc/NEWS.d/next/Library/2025-08-17-10-22-31.gh-issue-132947.XR4MJ8.rst
+++ /dev/null
@@ -1,6 +0,0 @@
-Applied changes to ``importlib.metadata`` from `importlib_metadata 8.7
-<https://importlib-metadata.readthedocs.io/en/latest/history.html#v8-7-0>`_,
-including ``dist`` now disallowed for ``EntryPoints.select``; deferred
-imports for faster import times; added support for metadata with newlines
-(python/cpython#119650); and ``metadata()`` function now returns ``None``
-when a metadata directory is present but no metadata is present.