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