diff --git a/CHANGES.rst b/CHANGES.rst index 9e0e7c44..74517bad 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -1,3 +1,10 @@ +v4.3.0 +======= + +* #317: De-duplication of distributions no longer requires + loading the full metadata for ``PathDistribution`` objects, + entry point loading performance by ~10x. + v4.2.0 ======= diff --git a/importlib_metadata/__init__.py b/importlib_metadata/__init__.py index 0da20fc8..3693a01d 100644 --- a/importlib_metadata/__init__.py +++ b/importlib_metadata/__init__.py @@ -498,6 +498,11 @@ def name(self): """Return the 'Name' metadata for the distribution package.""" return self.metadata['Name'] + @property + def _normalized_name(self): + """Return a normalized version of the name.""" + return Prepared.normalize(self.name) + @property def version(self): """Return the 'Version' metadata for the distribution package.""" @@ -805,6 +810,12 @@ def read_text(self, filename): def locate_file(self, path): return self._path.parent / path + @property + def _normalized_name(self): + stem = os.path.basename(str(self._path)) + name, sep, rest = stem.partition('-') + return name + def distribution(distribution_name): """Get the ``Distribution`` instance for the named package. @@ -859,7 +870,8 @@ def entry_points(**params) -> Union[EntryPoints, SelectableGroups]: :return: EntryPoints or SelectableGroups for all installed packages. """ - unique = functools.partial(unique_everseen, key=operator.attrgetter('name')) + norm_name = operator.attrgetter('_normalized_name') + unique = functools.partial(unique_everseen, key=norm_name) eps = itertools.chain.from_iterable( dist.entry_points for dist in unique(distributions()) )