File tree Expand file tree Collapse file tree 6 files changed +64
-1
lines changed
Expand file tree Collapse file tree 6 files changed +64
-1
lines changed Original file line number Diff line number Diff line change 33 */.tox/*
44 tests/*
55 prepare/*
6+ */_itertools.py
67
78[report]
89show_missing = True
Original file line number Diff line number Diff line change 1+ v3.5.0
2+ ======
3+
4+ * #280: ``entry_points `` now only returns entry points for
5+ unique distributions (by name).
6+
17v3.4.0
28======
39
Original file line number Diff line number Diff line change 1919 Protocol ,
2020)
2121
22+ from ._itertools import unique_everseen
23+
2224from configparser import ConfigParser
2325from contextlib import suppress
2426from importlib import import_module
@@ -646,7 +648,10 @@ def entry_points():
646648
647649 :return: EntryPoint objects for all installed packages.
648650 """
649- eps = itertools .chain .from_iterable (dist .entry_points for dist in distributions ())
651+ unique = functools .partial (unique_everseen , key = operator .attrgetter ('name' ))
652+ eps = itertools .chain .from_iterable (
653+ dist .entry_points for dist in unique (distributions ())
654+ )
650655 by_group = operator .attrgetter ('group' )
651656 ordered = sorted (eps , key = by_group )
652657 grouped = itertools .groupby (ordered , by_group )
Original file line number Diff line number Diff line change 1+ from itertools import filterfalse
2+
3+
4+ def unique_everseen (iterable , key = None ):
5+ "List unique elements, preserving order. Remember all elements ever seen."
6+ # unique_everseen('AAAABBBCCDAABBB') --> A B C D
7+ # unique_everseen('ABBCcAD', str.lower) --> A B C D
8+ seen = set ()
9+ seen_add = seen .add
10+ if key is None :
11+ for element in filterfalse (seen .__contains__ , iterable ):
12+ seen_add (element )
13+ yield element
14+ else :
15+ for element in iterable :
16+ k = key (element )
17+ if k not in seen :
18+ seen_add (k )
19+ yield element
Original file line number Diff line number Diff line change @@ -76,6 +76,34 @@ def test_entry_points_distribution(self):
7676 self .assertIn (ep .dist .name , ('distinfo-pkg' , 'egginfo-pkg' ))
7777 self .assertEqual (ep .dist .version , "1.0.0" )
7878
79+ def test_entry_points_unique_packages (self ):
80+ """
81+ Entry points should only be exposed for the first package
82+ on sys.path with a given name.
83+ """
84+ alt_site_dir = self .fixtures .enter_context (fixtures .tempdir ())
85+ self .fixtures .enter_context (self .add_sys_path (alt_site_dir ))
86+ alt_pkg = {
87+ "distinfo_pkg-1.1.0.dist-info" : {
88+ "METADATA" : """
89+ Name: distinfo-pkg
90+ Version: 1.1.0
91+ """ ,
92+ "entry_points.txt" : """
93+ [entries]
94+ main = mod:altmain
95+ """ ,
96+ },
97+ }
98+ fixtures .build_files (alt_pkg , alt_site_dir )
99+ entries = dict (entry_points ()['entries' ])
100+ assert not any (
101+ ep .dist .name == 'distinfo-pkg' and ep .dist .version == '1.0.0'
102+ for ep in entries .values ()
103+ )
104+ # ns:sub doesn't exist in alt_pkg
105+ assert 'ns:sub' not in entries
106+
79107 def test_metadata_for_this_package (self ):
80108 md = metadata ('egginfo-pkg' )
81109 assert md ['author' ] == 'Steven Ma'
Original file line number Diff line number Diff line change @@ -38,6 +38,10 @@ use_develop = False
3838deps =
3939 ipython
4040commands =
41+ python -m ' print("Simple discovery performance")'
42+ python -m timeit -s ' import importlib_metadata' -- ' importlib_metadata.distribution("ipython")'
43+ python -m ' print("Entry point discovery performance")'
44+ python -m timeit -s ' import importlib_metadata' -- ' importlib_metadata.entry_points()'
4145 python -c ' print("Cached lookup performance")'
4246 python -m timeit -s ' import importlib_metadata; importlib_metadata.distribution("ipython")' -- ' importlib_metadata.distribution("ipython")'
4347 python -c ' print("Uncached lookup performance")'
You can’t perform that action at this time.
0 commit comments