@@ -128,12 +128,21 @@ class EntryPoint(
128128 See `the packaging docs on entry points
129129 <https://packaging.python.org/specifications/entry-points/>`_
130130 for more information.
131+
132+ >>> ep = EntryPoint(
133+ ... name=None, group=None, value='package.module:attr [extra1, extra2]')
134+ >>> ep.module
135+ 'package.module'
136+ >>> ep.attr
137+ 'attr'
138+ >>> ep.extras
139+ ['extra1', 'extra2']
131140 """
132141
133142 pattern = re .compile (
134143 r'(?P<module>[\w.]+)\s*'
135- r'(:\s*(?P<attr>[\w.]+))? \s*'
136- r'(?P<extras>\[.*\])? \s*$'
144+ r'(:\s*(?P<attr>[\w.]+)\s*)? '
145+ r'(( ?P<extras>\[.*\])\s*)? $'
137146 )
138147 """
139148 A regular expression describing the syntax for an entry point,
@@ -176,7 +185,7 @@ def attr(self):
176185 @property
177186 def extras (self ):
178187 match = self .pattern .match (self .value )
179- return list ( re .finditer (r'\w+' , match .group ('extras' ) or '' ) )
188+ return re .findall (r'\w+' , match .group ('extras' ) or '' )
180189
181190 def _for (self , dist ):
182191 self .dist = dist
@@ -200,6 +209,25 @@ def __reduce__(self):
200209 )
201210
202211 def matches (self , ** params ):
212+ """
213+ EntryPoint matches the given parameters.
214+
215+ >>> ep = EntryPoint(group='foo', name='bar', value='bing:bong [extra1, extra2]')
216+ >>> ep.matches(group='foo')
217+ True
218+ >>> ep.matches(name='bar', value='bing:bong [extra1, extra2]')
219+ True
220+ >>> ep.matches(group='foo', name='other')
221+ False
222+ >>> ep.matches()
223+ True
224+ >>> ep.matches(extras=['extra1', 'extra2'])
225+ True
226+ >>> ep.matches(module='bing')
227+ True
228+ >>> ep.matches(attr='bong')
229+ True
230+ """
203231 attrs = (getattr (self , param ) for param in params )
204232 return all (map (operator .eq , params .values (), attrs ))
205233
@@ -236,6 +264,8 @@ class DeprecatedList(list):
236264 1
237265 """
238266
267+ __slots__ = ()
268+
239269 _warn = functools .partial (
240270 warnings .warn ,
241271 "EntryPoints list interface is deprecated. Cast to list if needed." ,
@@ -648,7 +678,7 @@ def _read_dist_info_reqs(self):
648678
649679 def _read_egg_info_reqs (self ):
650680 source = self .read_text ('requires.txt' )
651- return source and self ._deps_from_requires_text (source )
681+ return None if source is None else self ._deps_from_requires_text (source )
652682
653683 @classmethod
654684 def _deps_from_requires_text (cls , source ):
@@ -669,16 +699,25 @@ def _convert_egg_info_reqs_to_simple_reqs(sections):
669699 def make_condition (name ):
670700 return name and f'extra == "{ name } "'
671701
672- def parse_condition (section ):
702+ def quoted_marker (section ):
673703 section = section or ''
674704 extra , sep , markers = section .partition (':' )
675705 if extra and markers :
676706 markers = f'({ markers } )'
677707 conditions = list (filter (None , [markers , make_condition (extra )]))
678708 return '; ' + ' and ' .join (conditions ) if conditions else ''
679709
710+ def url_req_space (req ):
711+ """
712+ PEP 508 requires a space between the url_spec and the quoted_marker.
713+ Ref python/importlib_metadata#357.
714+ """
715+ # '@' is uniquely indicative of a url_req.
716+ return ' ' * ('@' in req )
717+
680718 for section in sections :
681- yield section .value + parse_condition (section .name )
719+ space = url_req_space (section .value )
720+ yield section .value + space + quoted_marker (section .name )
682721
683722
684723class DistributionFinder (MetaPathFinder ):
@@ -741,14 +780,13 @@ def __new__(cls, root):
741780
742781 def __init__ (self , root ):
743782 self .root = root
744- self .base = os .path .basename (self .root ).lower ()
745783
746784 def joinpath (self , child ):
747785 return pathlib .Path (self .root , child )
748786
749787 def children (self ):
750788 with suppress (Exception ):
751- return os .listdir (self .root or '' )
789+ return os .listdir (self .root or '. ' )
752790 with suppress (Exception ):
753791 return self .zip_children ()
754792 return []
0 commit comments