Mercurial > repos > shellac > guppy_basecaller
comparison env/lib/python3.7/site-packages/glob2/impl.py @ 5:9b1c78e6ba9c draft default tip
"planemo upload commit 6c0a8142489327ece472c84e558c47da711a9142"
author | shellac |
---|---|
date | Mon, 01 Jun 2020 08:59:25 -0400 |
parents | 79f47841a781 |
children |
comparison
equal
deleted
inserted
replaced
4:79f47841a781 | 5:9b1c78e6ba9c |
---|---|
1 """Filename globbing utility.""" | |
2 | |
3 from __future__ import absolute_import | |
4 | |
5 import sys | |
6 import os | |
7 import re | |
8 from os.path import join | |
9 from . import fnmatch | |
10 | |
11 try: | |
12 from itertools import imap | |
13 except ImportError: | |
14 imap = map | |
15 | |
16 | |
17 class Globber(object): | |
18 | |
19 listdir = staticmethod(os.listdir) | |
20 isdir = staticmethod(os.path.isdir) | |
21 islink = staticmethod(os.path.islink) | |
22 exists = staticmethod(os.path.lexists) | |
23 | |
24 def walk(self, top, followlinks=False, sep=None): | |
25 """A simplified version of os.walk (code copied) that uses | |
26 ``self.listdir``, and the other local filesystem methods. | |
27 | |
28 Because we don't care about file/directory distinctions, only | |
29 a single list is returned. | |
30 """ | |
31 try: | |
32 names = self.listdir(top) | |
33 except os.error as err: | |
34 return | |
35 | |
36 items = [] | |
37 for name in names: | |
38 items.append(name) | |
39 | |
40 yield top, items | |
41 | |
42 for name in items: | |
43 new_path = _join_paths([top, name], sep=sep) | |
44 if followlinks or not self.islink(new_path): | |
45 for x in self.walk(new_path, followlinks): | |
46 yield x | |
47 | |
48 def glob(self, pathname, with_matches=False, include_hidden=False, recursive=True, | |
49 norm_paths=True, case_sensitive=True, sep=None): | |
50 """Return a list of paths matching a pathname pattern. | |
51 | |
52 The pattern may contain simple shell-style wildcards a la | |
53 fnmatch. However, unlike fnmatch, filenames starting with a | |
54 dot are special cases that are not matched by '*' and '?' | |
55 patterns. | |
56 | |
57 If ``include_hidden`` is True, then files and folders starting with | |
58 a dot are also returned. | |
59 """ | |
60 return list(self.iglob(pathname, with_matches, include_hidden, | |
61 norm_paths, case_sensitive, sep)) | |
62 | |
63 def iglob(self, pathname, with_matches=False, include_hidden=False, recursive=True, | |
64 norm_paths=True, case_sensitive=True, sep=None): | |
65 """Return an iterator which yields the paths matching a pathname | |
66 pattern. | |
67 | |
68 The pattern may contain simple shell-style wildcards a la | |
69 fnmatch. However, unlike fnmatch, filenames starting with a | |
70 dot are special cases that are not matched by '*' and '?' | |
71 patterns. | |
72 | |
73 If ``with_matches`` is True, then for each matching path | |
74 a 2-tuple will be returned; the second element if the tuple | |
75 will be a list of the parts of the path that matched the individual | |
76 wildcards. | |
77 | |
78 If ``include_hidden`` is True, then files and folders starting with | |
79 a dot are also returned. | |
80 """ | |
81 result = self._iglob(pathname, True, include_hidden, | |
82 norm_paths, case_sensitive, sep) | |
83 if with_matches: | |
84 return result | |
85 return imap(lambda s: s[0], result) | |
86 | |
87 def _iglob(self, pathname, rootcall, include_hidden, | |
88 norm_paths, case_sensitive, sep): | |
89 """Internal implementation that backs :meth:`iglob`. | |
90 | |
91 ``rootcall`` is required to differentiate between the user's call to | |
92 iglob(), and subsequent recursive calls, for the purposes of resolving | |
93 certain special cases of ** wildcards. Specifically, "**" is supposed | |
94 to include the current directory for purposes of globbing, but the | |
95 directory itself should never be returned. So if ** is the lastmost | |
96 part of the ``pathname`` given the user to the root call, we want to | |
97 ignore the current directory. For this, we need to know which the root | |
98 call is. | |
99 """ | |
100 | |
101 # Short-circuit if no glob magic | |
102 if not has_magic(pathname): | |
103 if self.exists(pathname): | |
104 yield pathname, () | |
105 return | |
106 | |
107 # If no directory part is left, assume the working directory | |
108 dirname, basename = os.path.split(pathname) | |
109 | |
110 # If the directory is globbed, recurse to resolve. | |
111 # If at this point there is no directory part left, we simply | |
112 # continue with dirname="", which will search the current dir. | |
113 # `os.path.split()` returns the argument itself as a dirname if it is a | |
114 # drive or UNC path. Prevent an infinite recursion if a drive or UNC path | |
115 # contains magic characters (i.e. r'\\?\C:'). | |
116 if dirname != pathname and has_magic(dirname): | |
117 # Note that this may return files, which will be ignored | |
118 # later when we try to use them as directories. | |
119 # Prefiltering them here would only require more IO ops. | |
120 dirs = self._iglob(dirname, False, include_hidden, | |
121 norm_paths, case_sensitive, sep) | |
122 else: | |
123 dirs = [(dirname, ())] | |
124 | |
125 # Resolve ``basename`` expr for every directory found | |
126 for dirname, dir_groups in dirs: | |
127 for name, groups in self.resolve_pattern(dirname, basename, | |
128 not rootcall, include_hidden, | |
129 norm_paths, case_sensitive, sep): | |
130 yield _join_paths([dirname, name], sep=sep), dir_groups + groups | |
131 | |
132 def resolve_pattern(self, dirname, pattern, globstar_with_root, include_hidden, | |
133 norm_paths, case_sensitive, sep): | |
134 """Apply ``pattern`` (contains no path elements) to the | |
135 literal directory in ``dirname``. | |
136 | |
137 If pattern=='', this will filter for directories. This is | |
138 a special case that happens when the user's glob expression ends | |
139 with a slash (in which case we only want directories). It simpler | |
140 and faster to filter here than in :meth:`_iglob`. | |
141 """ | |
142 | |
143 if sys.version_info[0] == 3: | |
144 if isinstance(pattern, bytes): | |
145 dirname = bytes(os.curdir, 'ASCII') | |
146 else: | |
147 if isinstance(pattern, unicode) and not isinstance(dirname, unicode): | |
148 dirname = unicode(dirname, sys.getfilesystemencoding() or | |
149 sys.getdefaultencoding()) | |
150 | |
151 # If no magic, short-circuit, only check for existence | |
152 if not has_magic(pattern): | |
153 if pattern == '': | |
154 if self.isdir(dirname): | |
155 return [(pattern, ())] | |
156 else: | |
157 if self.exists(_join_paths([dirname, pattern], sep=sep)): | |
158 return [(pattern, ())] | |
159 return [] | |
160 | |
161 if not dirname: | |
162 dirname = os.curdir | |
163 | |
164 try: | |
165 if pattern == '**': | |
166 # Include the current directory in **, if asked; by adding | |
167 # an empty string as opposed to '.', we spare ourselves | |
168 # having to deal with os.path.normpath() later. | |
169 names = [''] if globstar_with_root else [] | |
170 for top, entries in self.walk(dirname, sep=sep): | |
171 _mkabs = lambda s: _join_paths([top[len(dirname) + 1:], s], sep=sep) | |
172 names.extend(map(_mkabs, entries)) | |
173 # Reset pattern so that fnmatch(), which does not understand | |
174 # ** specifically, will only return a single group match. | |
175 pattern = '*' | |
176 else: | |
177 names = self.listdir(dirname) | |
178 except os.error: | |
179 return [] | |
180 | |
181 if not include_hidden and not _ishidden(pattern): | |
182 # Remove hidden files, but take care to ensure | |
183 # that the empty string we may have added earlier remains. | |
184 # Do not filter out the '' that we might have added earlier | |
185 names = filter(lambda x: not x or not _ishidden(x), names) | |
186 return fnmatch.filter(names, pattern, norm_paths, case_sensitive, sep) | |
187 | |
188 | |
189 default_globber = Globber() | |
190 glob = default_globber.glob | |
191 iglob = default_globber.iglob | |
192 del default_globber | |
193 | |
194 | |
195 magic_check = re.compile('[*?[]') | |
196 magic_check_bytes = re.compile(b'[*?[]') | |
197 | |
198 | |
199 def has_magic(s): | |
200 if isinstance(s, bytes): | |
201 match = magic_check_bytes.search(s) | |
202 else: | |
203 match = magic_check.search(s) | |
204 return match is not None | |
205 | |
206 | |
207 def _ishidden(path): | |
208 return path[0] in ('.', b'.'[0]) | |
209 | |
210 | |
211 def _join_paths(paths, sep=None): | |
212 path = join(*paths) | |
213 if sep: | |
214 path = re.sub(r'\/', sep, path) # cached internally | |
215 return path | |
216 |