Skip to content

Commit

Permalink
Merge branch 'main' into cacheduncached
Browse files Browse the repository at this point in the history
  • Loading branch information
jaraco committed Feb 21, 2021
2 parents 4e2603f + 67041f7 commit f49df03
Show file tree
Hide file tree
Showing 6 changed files with 64 additions and 1 deletion.
1 change: 1 addition & 0 deletions .coveragerc
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ omit =
*/.tox/*
tests/*
prepare/*
*/_itertools.py

[report]
show_missing = True
6 changes: 6 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
v3.5.0
======

* #280: ``entry_points`` now only returns entry points for
unique distributions (by name).

v3.4.0
======

Expand Down
7 changes: 6 additions & 1 deletion importlib_metadata/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
Protocol,
)

from ._itertools import unique_everseen

from configparser import ConfigParser
from contextlib import suppress
from importlib import import_module
Expand Down Expand Up @@ -646,7 +648,10 @@ def entry_points():
:return: EntryPoint objects for all installed packages.
"""
eps = itertools.chain.from_iterable(dist.entry_points for dist in distributions())
unique = functools.partial(unique_everseen, key=operator.attrgetter('name'))
eps = itertools.chain.from_iterable(
dist.entry_points for dist in unique(distributions())
)
by_group = operator.attrgetter('group')
ordered = sorted(eps, key=by_group)
grouped = itertools.groupby(ordered, by_group)
Expand Down
19 changes: 19 additions & 0 deletions importlib_metadata/_itertools.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
from itertools import filterfalse


def unique_everseen(iterable, key=None):
"List unique elements, preserving order. Remember all elements ever seen."
# unique_everseen('AAAABBBCCDAABBB') --> A B C D
# unique_everseen('ABBCcAD', str.lower) --> A B C D
seen = set()
seen_add = seen.add
if key is None:
for element in filterfalse(seen.__contains__, iterable):
seen_add(element)
yield element
else:
for element in iterable:
k = key(element)
if k not in seen:
seen_add(k)
yield element
28 changes: 28 additions & 0 deletions tests/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,34 @@ def test_entry_points_distribution(self):
self.assertIn(ep.dist.name, ('distinfo-pkg', 'egginfo-pkg'))
self.assertEqual(ep.dist.version, "1.0.0")

def test_entry_points_unique_packages(self):
"""
Entry points should only be exposed for the first package
on sys.path with a given name.
"""
alt_site_dir = self.fixtures.enter_context(fixtures.tempdir())
self.fixtures.enter_context(self.add_sys_path(alt_site_dir))
alt_pkg = {
"distinfo_pkg-1.1.0.dist-info": {
"METADATA": """
Name: distinfo-pkg
Version: 1.1.0
""",
"entry_points.txt": """
[entries]
main = mod:altmain
""",
},
}
fixtures.build_files(alt_pkg, alt_site_dir)
entries = dict(entry_points()['entries'])
assert not any(
ep.dist.name == 'distinfo-pkg' and ep.dist.version == '1.0.0'
for ep in entries.values()
)
# ns:sub doesn't exist in alt_pkg
assert 'ns:sub' not in entries

def test_metadata_for_this_package(self):
md = metadata('egginfo-pkg')
assert md['author'] == 'Steven Ma'
Expand Down
4 changes: 4 additions & 0 deletions tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ use_develop = False
deps =
ipython
commands =
python -m 'print("Simple discovery performance")'
python -m timeit -s 'import importlib_metadata' -- 'importlib_metadata.distribution("ipython")'
python -m 'print("Entry point discovery performance")'
python -m timeit -s 'import importlib_metadata' -- 'importlib_metadata.entry_points()'
python -c 'print("Cached lookup performance")'
python -m timeit -s 'import importlib_metadata; importlib_metadata.distribution("ipython")' -- 'importlib_metadata.distribution("ipython")'
python -c 'print("Uncached lookup performance")'
Expand Down

0 comments on commit f49df03

Please sign in to comment.