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]) |