1111
1212if sys .version_info >= (3 ,): # pragma: nocover
1313 from contextlib import suppress
14- from pathlib import Path
1514else : # pragma: nocover
1615 from contextlib2 import suppress # noqa
1716 from itertools import imap as map # type: ignore
18- from pathlib2 import Path
1917
2018 FileNotFoundError = IOError , OSError
2119 NotADirectoryError = IOError , OSError
2220 __metaclass__ = type
2321
2422
23+ if sys .version_info > (3 , 5 ): # pragma: nocover
24+ from pathlib import Path
25+ else : # pragma: nocover
26+ from pathlib2 import Path
27+
28+
2529def install (cls ):
2630 """Class decorator for installation on sys.meta_path."""
2731 sys .meta_path .append (cls ())
@@ -46,12 +50,14 @@ def find_spec(*args, **kwargs):
4650 find_module = find_spec
4751
4852
49- class MetadataPathBaseFinder (NullFinder ):
53+ @install
54+ class MetadataPathFinder (NullFinder ):
5055 """A degenerate finder for distribution packages on the file system.
5156
5257 This finder supplies only a find_distributions() method for versions
5358 of Python that do not have a PathFinder find_distributions().
5459 """
60+ search_template = r'{pattern}(-.*)?\.(dist|egg)-info'
5561
5662 def find_distributions (self , name = None , path = None ):
5763 """Return an iterable of all Distribution instances capable of
@@ -72,9 +78,15 @@ def _search_paths(cls, pattern, paths):
7278 """
7379 return itertools .chain .from_iterable (
7480 cls ._search_path (path , pattern )
75- for path in map (Path , paths )
81+ for path in map (cls . _switch_path , paths )
7682 )
7783
84+ @staticmethod
85+ def _switch_path (path ):
86+ with suppress (Exception ):
87+ return zipp .Path (path )
88+ return Path (path )
89+
7890 @classmethod
7991 def _predicate (cls , pattern , root , item ):
8092 return re .match (pattern , str (item .name ), flags = re .IGNORECASE )
@@ -89,82 +101,15 @@ def _search_path(cls, root, pattern):
89101 if cls ._predicate (matcher , root , item ))
90102
91103
92- @install
93- class MetadataPathFinder (MetadataPathBaseFinder ):
94- search_template = r'{pattern}(-.*)?\.(dist|egg)-info'
95-
96-
97- @install
98- class MetadataPathEggInfoFileFinder (MetadataPathBaseFinder ):
99- search_template = r'{pattern}(-.*)?\.egg-info'
100-
101- @classmethod
102- def _predicate (cls , pattern , root , item ):
103- return (
104- (root / item ).is_file () and
105- re .match (pattern , str (item .name ), flags = re .IGNORECASE ))
106-
107-
108104class PathDistribution (Distribution ):
109105 def __init__ (self , path ):
110106 """Construct a distribution from a path to the metadata directory."""
111107 self ._path = path
112108
113109 def read_text (self , filename ):
114- with suppress (FileNotFoundError , NotADirectoryError ):
115- with self ._path .joinpath (filename ).open (encoding = 'utf-8' ) as fp :
116- return fp .read ()
117- return None
110+ with suppress (FileNotFoundError , NotADirectoryError , KeyError ):
111+ return self ._path .joinpath (filename ).read_text (encoding = 'utf-8' )
118112 read_text .__doc__ = Distribution .read_text .__doc__
119113
120114 def locate_file (self , path ):
121115 return self ._path .parent / path
122-
123-
124- @install
125- class WheelMetadataFinder (NullFinder ):
126- """A degenerate finder for distribution packages in wheels.
127-
128- This finder supplies only a find_distributions() method for versions
129- of Python that do not have a PathFinder find_distributions().
130- """
131- search_template = r'{pattern}(-.*)?\.whl'
132-
133- def find_distributions (self , name = None , path = None ):
134- """Return an iterable of all Distribution instances capable of
135- loading the metadata for packages matching the name
136- (or all names if not supplied) along the paths in the list
137- of directories ``path`` (defaults to sys.path).
138- """
139- if path is None :
140- path = sys .path
141- pattern = '.*' if name is None else re .escape (name )
142- found = self ._search_paths (pattern , path )
143- return map (WheelDistribution , found )
144-
145- @classmethod
146- def _search_paths (cls , pattern , paths ):
147- return (
148- path
149- for path in map (Path , paths )
150- if re .match (
151- cls .search_template .format (pattern = pattern ),
152- str (path .name ),
153- flags = re .IGNORECASE ,
154- )
155- )
156-
157-
158- class WheelDistribution (Distribution ):
159- def __init__ (self , archive ):
160- self ._archive = zipp .Path (archive )
161- name , version = archive .name .split ('-' )[0 :2 ]
162- self ._dist_info = '{}-{}.dist-info' .format (name , version )
163-
164- def read_text (self , filename ):
165- target = self ._archive / self ._dist_info / filename
166- return target .read_text () if target .exists () else None
167- read_text .__doc__ = Distribution .read_text .__doc__
168-
169- def locate_file (self , path ):
170- return self ._archive / path
0 commit comments