Mercurial > repos > shellac > guppy_basecaller
comparison env/lib/python3.7/site-packages/glob2/impl.py @ 2:6af9afd405e9 draft
"planemo upload commit 0a63dd5f4d38a1f6944587f52a8cd79874177fc1"
| author | shellac |
|---|---|
| date | Thu, 14 May 2020 14:56:58 -0400 |
| parents | 26e78fe6e8c4 |
| children |
comparison
equal
deleted
inserted
replaced
| 1:75ca89e9b81c | 2:6af9afd405e9 |
|---|---|
| 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 |
