Greg Ward | adc1172 | 2000-07-30 00:04:17 +0000 | [diff] [blame] | 1 | """distutils.filelist |
| 2 | |
| 3 | Provides the FileList class, used for poking about the filesystem |
| 4 | and building lists of files. |
| 5 | """ |
| 6 | |
Greg Ward | adc1172 | 2000-07-30 00:04:17 +0000 | [diff] [blame] | 7 | __revision__ = "$Id$" |
| 8 | |
Neal Norwitz | 9d72bb4 | 2007-04-17 08:48:32 +0000 | [diff] [blame] | 9 | import os, re |
Greg Ward | adc1172 | 2000-07-30 00:04:17 +0000 | [diff] [blame] | 10 | import fnmatch |
Greg Ward | adc1172 | 2000-07-30 00:04:17 +0000 | [diff] [blame] | 11 | from distutils.util import convert_path |
Greg Ward | 7b3d56c | 2000-07-30 00:21:36 +0000 | [diff] [blame] | 12 | from distutils.errors import DistutilsTemplateError, DistutilsInternalError |
Jeremy Hylton | 4f2f133 | 2002-06-04 21:04:03 +0000 | [diff] [blame] | 13 | from distutils import log |
Greg Ward | adc1172 | 2000-07-30 00:04:17 +0000 | [diff] [blame] | 14 | |
| 15 | class FileList: |
Greg Ward | c98927a | 2000-07-30 00:08:13 +0000 | [diff] [blame] | 16 | """A list of files built by on exploring the filesystem and filtered by |
| 17 | applying various patterns to what we find there. |
Greg Ward | adc1172 | 2000-07-30 00:04:17 +0000 | [diff] [blame] | 18 | |
Greg Ward | c98927a | 2000-07-30 00:08:13 +0000 | [diff] [blame] | 19 | Instance attributes: |
| 20 | dir |
| 21 | directory from which files will be taken -- only used if |
| 22 | 'allfiles' not supplied to constructor |
| 23 | files |
| 24 | list of filenames currently being built/filtered/manipulated |
| 25 | allfiles |
| 26 | complete list of files under consideration (ie. without any |
| 27 | filtering applied) |
| 28 | """ |
Greg Ward | adc1172 | 2000-07-30 00:04:17 +0000 | [diff] [blame] | 29 | |
Collin Winter | 5b7e9d7 | 2007-08-30 03:52:21 +0000 | [diff] [blame] | 30 | def __init__(self, warn=None, debug_print=None): |
Jeremy Hylton | cd8a114 | 2002-06-04 20:14:43 +0000 | [diff] [blame] | 31 | # ignore argument to FileList, but keep them for backwards |
| 32 | # compatibility |
Greg Ward | 979db97 | 2000-07-30 01:45:42 +0000 | [diff] [blame] | 33 | self.allfiles = None |
| 34 | self.files = [] |
Greg Ward | adc1172 | 2000-07-30 00:04:17 +0000 | [diff] [blame] | 35 | |
Collin Winter | 5b7e9d7 | 2007-08-30 03:52:21 +0000 | [diff] [blame] | 36 | def set_allfiles(self, allfiles): |
Greg Ward | 979db97 | 2000-07-30 01:45:42 +0000 | [diff] [blame] | 37 | self.allfiles = allfiles |
| 38 | |
Collin Winter | 5b7e9d7 | 2007-08-30 03:52:21 +0000 | [diff] [blame] | 39 | def findall(self, dir=os.curdir): |
Greg Ward | 979db97 | 2000-07-30 01:45:42 +0000 | [diff] [blame] | 40 | self.allfiles = findall(dir) |
| 41 | |
Collin Winter | 5b7e9d7 | 2007-08-30 03:52:21 +0000 | [diff] [blame] | 42 | def debug_print(self, msg): |
Greg Ward | adc1172 | 2000-07-30 00:04:17 +0000 | [diff] [blame] | 43 | """Print 'msg' to stdout if the global DEBUG (taken from the |
| 44 | DISTUTILS_DEBUG environment variable) flag is true. |
| 45 | """ |
Jeremy Hylton | fcd7353 | 2002-09-11 16:31:53 +0000 | [diff] [blame] | 46 | from distutils.debug import DEBUG |
Greg Ward | adc1172 | 2000-07-30 00:04:17 +0000 | [diff] [blame] | 47 | if DEBUG: |
Guido van Rossum | be19ed7 | 2007-02-09 05:37:30 +0000 | [diff] [blame] | 48 | print(msg) |
Greg Ward | adc1172 | 2000-07-30 00:04:17 +0000 | [diff] [blame] | 49 | |
Greg Ward | 979db97 | 2000-07-30 01:45:42 +0000 | [diff] [blame] | 50 | # -- List-like methods --------------------------------------------- |
| 51 | |
Collin Winter | 5b7e9d7 | 2007-08-30 03:52:21 +0000 | [diff] [blame] | 52 | def append(self, item): |
Greg Ward | 979db97 | 2000-07-30 01:45:42 +0000 | [diff] [blame] | 53 | self.files.append(item) |
| 54 | |
Collin Winter | 5b7e9d7 | 2007-08-30 03:52:21 +0000 | [diff] [blame] | 55 | def extend(self, items): |
Greg Ward | 979db97 | 2000-07-30 01:45:42 +0000 | [diff] [blame] | 56 | self.files.extend(items) |
| 57 | |
Collin Winter | 5b7e9d7 | 2007-08-30 03:52:21 +0000 | [diff] [blame] | 58 | def sort(self): |
Greg Ward | 979db97 | 2000-07-30 01:45:42 +0000 | [diff] [blame] | 59 | # Not a strict lexical sort! |
Collin Winter | dc40ae6 | 2007-07-17 00:39:32 +0000 | [diff] [blame] | 60 | sortable_files = sorted(map(os.path.split, self.files)) |
Greg Ward | 979db97 | 2000-07-30 01:45:42 +0000 | [diff] [blame] | 61 | self.files = [] |
| 62 | for sort_tuple in sortable_files: |
Neal Norwitz | d910855 | 2006-03-17 08:00:19 +0000 | [diff] [blame] | 63 | self.files.append(os.path.join(*sort_tuple)) |
Greg Ward | 979db97 | 2000-07-30 01:45:42 +0000 | [diff] [blame] | 64 | |
| 65 | |
| 66 | # -- Other miscellaneous utility methods --------------------------- |
| 67 | |
Collin Winter | 5b7e9d7 | 2007-08-30 03:52:21 +0000 | [diff] [blame] | 68 | def remove_duplicates(self): |
Greg Ward | 979db97 | 2000-07-30 01:45:42 +0000 | [diff] [blame] | 69 | # Assumes list has been sorted! |
Jeremy Hylton | cd8a114 | 2002-06-04 20:14:43 +0000 | [diff] [blame] | 70 | for i in range(len(self.files) - 1, 0, -1): |
| 71 | if self.files[i] == self.files[i - 1]: |
Greg Ward | 979db97 | 2000-07-30 01:45:42 +0000 | [diff] [blame] | 72 | del self.files[i] |
| 73 | |
| 74 | |
| 75 | # -- "File template" methods --------------------------------------- |
Fred Drake | b94b849 | 2001-12-06 20:51:35 +0000 | [diff] [blame] | 76 | |
Collin Winter | 5b7e9d7 | 2007-08-30 03:52:21 +0000 | [diff] [blame] | 77 | def _parse_template_line(self, line): |
Neal Norwitz | 9d72bb4 | 2007-04-17 08:48:32 +0000 | [diff] [blame] | 78 | words = line.split() |
Greg Ward | c98927a | 2000-07-30 00:08:13 +0000 | [diff] [blame] | 79 | action = words[0] |
Greg Ward | adc1172 | 2000-07-30 00:04:17 +0000 | [diff] [blame] | 80 | |
Greg Ward | 7b3d56c | 2000-07-30 00:21:36 +0000 | [diff] [blame] | 81 | patterns = dir = dir_pattern = None |
| 82 | |
| 83 | if action in ('include', 'exclude', |
| 84 | 'global-include', 'global-exclude'): |
Greg Ward | 071ed76 | 2000-09-26 02:12:31 +0000 | [diff] [blame] | 85 | if len(words) < 2: |
Collin Winter | 5b7e9d7 | 2007-08-30 03:52:21 +0000 | [diff] [blame] | 86 | raise DistutilsTemplateError( |
| 87 | "'%s' expects <pattern1> <pattern2> ..." % action) |
Amaury Forgeot d'Arc | 61cb087 | 2008-07-26 20:09:45 +0000 | [diff] [blame] | 88 | patterns = [convert_path(w) for w in words[1:]] |
Greg Ward | 7b3d56c | 2000-07-30 00:21:36 +0000 | [diff] [blame] | 89 | elif action in ('recursive-include', 'recursive-exclude'): |
Greg Ward | 071ed76 | 2000-09-26 02:12:31 +0000 | [diff] [blame] | 90 | if len(words) < 3: |
Collin Winter | 5b7e9d7 | 2007-08-30 03:52:21 +0000 | [diff] [blame] | 91 | raise DistutilsTemplateError( |
| 92 | "'%s' expects <dir> <pattern1> <pattern2> ..." % action) |
Greg Ward | c98927a | 2000-07-30 00:08:13 +0000 | [diff] [blame] | 93 | dir = convert_path(words[1]) |
Amaury Forgeot d'Arc | 61cb087 | 2008-07-26 20:09:45 +0000 | [diff] [blame] | 94 | patterns = [convert_path(w) for w in words[2:]] |
Greg Ward | 7b3d56c | 2000-07-30 00:21:36 +0000 | [diff] [blame] | 95 | elif action in ('graft', 'prune'): |
Greg Ward | 071ed76 | 2000-09-26 02:12:31 +0000 | [diff] [blame] | 96 | if len(words) != 2: |
Collin Winter | 5b7e9d7 | 2007-08-30 03:52:21 +0000 | [diff] [blame] | 97 | raise DistutilsTemplateError( |
| 98 | "'%s' expects a single <dir_pattern>" % action) |
Greg Ward | 7b3d56c | 2000-07-30 00:21:36 +0000 | [diff] [blame] | 99 | dir_pattern = convert_path(words[1]) |
Greg Ward | c98927a | 2000-07-30 00:08:13 +0000 | [diff] [blame] | 100 | else: |
Collin Winter | 5b7e9d7 | 2007-08-30 03:52:21 +0000 | [diff] [blame] | 101 | raise DistutilsTemplateError("unknown action '%s'" % action) |
Greg Ward | 7b3d56c | 2000-07-30 00:21:36 +0000 | [diff] [blame] | 102 | |
Greg Ward | d5dcc17 | 2000-07-30 01:04:22 +0000 | [diff] [blame] | 103 | return (action, patterns, dir, dir_pattern) |
Greg Ward | 7b3d56c | 2000-07-30 00:21:36 +0000 | [diff] [blame] | 104 | |
Collin Winter | 5b7e9d7 | 2007-08-30 03:52:21 +0000 | [diff] [blame] | 105 | def process_template_line(self, line): |
Greg Ward | 7b3d56c | 2000-07-30 00:21:36 +0000 | [diff] [blame] | 106 | # Parse the line: split it up, make sure the right number of words |
Greg Ward | 0f34185 | 2000-07-30 00:36:25 +0000 | [diff] [blame] | 107 | # is there, and return the relevant words. 'action' is always |
Greg Ward | 7b3d56c | 2000-07-30 00:21:36 +0000 | [diff] [blame] | 108 | # defined: it's the first word of the line. Which of the other |
| 109 | # three are defined depends on the action; it'll be either |
| 110 | # patterns, (dir and patterns), or (dir_pattern). |
Tarek Ziadé | 3679727 | 2010-07-22 12:50:05 +0000 | [diff] [blame] | 111 | (action, patterns, dir, dir_pattern) = self._parse_template_line(line) |
Greg Ward | adc1172 | 2000-07-30 00:04:17 +0000 | [diff] [blame] | 112 | |
Greg Ward | c98927a | 2000-07-30 00:08:13 +0000 | [diff] [blame] | 113 | # OK, now we know that the action is valid and we have the |
| 114 | # right number of words on the line for that action -- so we |
Greg Ward | 7b3d56c | 2000-07-30 00:21:36 +0000 | [diff] [blame] | 115 | # can proceed with minimal error-checking. |
Greg Ward | c98927a | 2000-07-30 00:08:13 +0000 | [diff] [blame] | 116 | if action == 'include': |
Neal Norwitz | 9d72bb4 | 2007-04-17 08:48:32 +0000 | [diff] [blame] | 117 | self.debug_print("include " + ' '.join(patterns)) |
Greg Ward | 7b3d56c | 2000-07-30 00:21:36 +0000 | [diff] [blame] | 118 | for pattern in patterns: |
Greg Ward | 071ed76 | 2000-09-26 02:12:31 +0000 | [diff] [blame] | 119 | if not self.include_pattern(pattern, anchor=1): |
Jeremy Hylton | cd8a114 | 2002-06-04 20:14:43 +0000 | [diff] [blame] | 120 | log.warn("warning: no files found matching '%s'", |
| 121 | pattern) |
Greg Ward | adc1172 | 2000-07-30 00:04:17 +0000 | [diff] [blame] | 122 | |
Greg Ward | c98927a | 2000-07-30 00:08:13 +0000 | [diff] [blame] | 123 | elif action == 'exclude': |
Neal Norwitz | 9d72bb4 | 2007-04-17 08:48:32 +0000 | [diff] [blame] | 124 | self.debug_print("exclude " + ' '.join(patterns)) |
Greg Ward | 7b3d56c | 2000-07-30 00:21:36 +0000 | [diff] [blame] | 125 | for pattern in patterns: |
Greg Ward | 071ed76 | 2000-09-26 02:12:31 +0000 | [diff] [blame] | 126 | if not self.exclude_pattern(pattern, anchor=1): |
Jeremy Hylton | cd8a114 | 2002-06-04 20:14:43 +0000 | [diff] [blame] | 127 | log.warn(("warning: no previously-included files " |
| 128 | "found matching '%s'"), pattern) |
Greg Ward | c98927a | 2000-07-30 00:08:13 +0000 | [diff] [blame] | 129 | |
| 130 | elif action == 'global-include': |
Neal Norwitz | 9d72bb4 | 2007-04-17 08:48:32 +0000 | [diff] [blame] | 131 | self.debug_print("global-include " + ' '.join(patterns)) |
Greg Ward | 7b3d56c | 2000-07-30 00:21:36 +0000 | [diff] [blame] | 132 | for pattern in patterns: |
Greg Ward | 071ed76 | 2000-09-26 02:12:31 +0000 | [diff] [blame] | 133 | if not self.include_pattern(pattern, anchor=0): |
Collin Winter | 5b7e9d7 | 2007-08-30 03:52:21 +0000 | [diff] [blame] | 134 | log.warn(("warning: no files found matching '%s' " |
Jeremy Hylton | cd8a114 | 2002-06-04 20:14:43 +0000 | [diff] [blame] | 135 | "anywhere in distribution"), pattern) |
Greg Ward | c98927a | 2000-07-30 00:08:13 +0000 | [diff] [blame] | 136 | |
| 137 | elif action == 'global-exclude': |
Neal Norwitz | 9d72bb4 | 2007-04-17 08:48:32 +0000 | [diff] [blame] | 138 | self.debug_print("global-exclude " + ' '.join(patterns)) |
Greg Ward | 7b3d56c | 2000-07-30 00:21:36 +0000 | [diff] [blame] | 139 | for pattern in patterns: |
Greg Ward | 071ed76 | 2000-09-26 02:12:31 +0000 | [diff] [blame] | 140 | if not self.exclude_pattern(pattern, anchor=0): |
Jeremy Hylton | cd8a114 | 2002-06-04 20:14:43 +0000 | [diff] [blame] | 141 | log.warn(("warning: no previously-included files matching " |
| 142 | "'%s' found anywhere in distribution"), |
| 143 | pattern) |
Greg Ward | c98927a | 2000-07-30 00:08:13 +0000 | [diff] [blame] | 144 | |
| 145 | elif action == 'recursive-include': |
| 146 | self.debug_print("recursive-include %s %s" % |
Neal Norwitz | 9d72bb4 | 2007-04-17 08:48:32 +0000 | [diff] [blame] | 147 | (dir, ' '.join(patterns))) |
Greg Ward | 7b3d56c | 2000-07-30 00:21:36 +0000 | [diff] [blame] | 148 | for pattern in patterns: |
Greg Ward | 071ed76 | 2000-09-26 02:12:31 +0000 | [diff] [blame] | 149 | if not self.include_pattern(pattern, prefix=dir): |
Collin Winter | 5b7e9d7 | 2007-08-30 03:52:21 +0000 | [diff] [blame] | 150 | log.warn(("warning: no files found matching '%s' " |
Tim Peters | 182b5ac | 2004-07-18 06:16:08 +0000 | [diff] [blame] | 151 | "under directory '%s'"), |
Jeremy Hylton | cd8a114 | 2002-06-04 20:14:43 +0000 | [diff] [blame] | 152 | pattern, dir) |
Greg Ward | c98927a | 2000-07-30 00:08:13 +0000 | [diff] [blame] | 153 | |
| 154 | elif action == 'recursive-exclude': |
| 155 | self.debug_print("recursive-exclude %s %s" % |
Neal Norwitz | 9d72bb4 | 2007-04-17 08:48:32 +0000 | [diff] [blame] | 156 | (dir, ' '.join(patterns))) |
Greg Ward | 7b3d56c | 2000-07-30 00:21:36 +0000 | [diff] [blame] | 157 | for pattern in patterns: |
Greg Ward | c98927a | 2000-07-30 00:08:13 +0000 | [diff] [blame] | 158 | if not self.exclude_pattern(pattern, prefix=dir): |
Jeremy Hylton | cd8a114 | 2002-06-04 20:14:43 +0000 | [diff] [blame] | 159 | log.warn(("warning: no previously-included files matching " |
| 160 | "'%s' found under directory '%s'"), |
| 161 | pattern, dir) |
Fred Drake | b94b849 | 2001-12-06 20:51:35 +0000 | [diff] [blame] | 162 | |
Greg Ward | c98927a | 2000-07-30 00:08:13 +0000 | [diff] [blame] | 163 | elif action == 'graft': |
| 164 | self.debug_print("graft " + dir_pattern) |
Greg Ward | 0f34185 | 2000-07-30 00:36:25 +0000 | [diff] [blame] | 165 | if not self.include_pattern(None, prefix=dir_pattern): |
Jeremy Hylton | cd8a114 | 2002-06-04 20:14:43 +0000 | [diff] [blame] | 166 | log.warn("warning: no directories found matching '%s'", |
| 167 | dir_pattern) |
Greg Ward | c98927a | 2000-07-30 00:08:13 +0000 | [diff] [blame] | 168 | |
| 169 | elif action == 'prune': |
| 170 | self.debug_print("prune " + dir_pattern) |
| 171 | if not self.exclude_pattern(None, prefix=dir_pattern): |
Collin Winter | 5b7e9d7 | 2007-08-30 03:52:21 +0000 | [diff] [blame] | 172 | log.warn(("no previously-included directories found " |
Jeremy Hylton | cd8a114 | 2002-06-04 20:14:43 +0000 | [diff] [blame] | 173 | "matching '%s'"), dir_pattern) |
Greg Ward | c98927a | 2000-07-30 00:08:13 +0000 | [diff] [blame] | 174 | else: |
Collin Winter | 5b7e9d7 | 2007-08-30 03:52:21 +0000 | [diff] [blame] | 175 | raise DistutilsInternalError( |
| 176 | "this cannot happen: invalid action '%s'" % action) |
Greg Ward | adc1172 | 2000-07-30 00:04:17 +0000 | [diff] [blame] | 177 | |
Tarek Ziadé | 3679727 | 2010-07-22 12:50:05 +0000 | [diff] [blame] | 178 | |
Greg Ward | 979db97 | 2000-07-30 01:45:42 +0000 | [diff] [blame] | 179 | # -- Filtering/selection methods ----------------------------------- |
| 180 | |
Collin Winter | 5b7e9d7 | 2007-08-30 03:52:21 +0000 | [diff] [blame] | 181 | def include_pattern(self, pattern, anchor=1, prefix=None, is_regex=0): |
Greg Ward | 0f34185 | 2000-07-30 00:36:25 +0000 | [diff] [blame] | 182 | """Select strings (presumably filenames) from 'self.files' that |
Tarek Ziadé | 3679727 | 2010-07-22 12:50:05 +0000 | [diff] [blame] | 183 | match 'pattern', a Unix-style wildcard (glob) pattern. Patterns |
| 184 | are not quite the same as implemented by the 'fnmatch' module: '*' |
| 185 | and '?' match non-special characters, where "special" is platform- |
| 186 | dependent: slash on Unix; colon, slash, and backslash on |
Greg Ward | 0f34185 | 2000-07-30 00:36:25 +0000 | [diff] [blame] | 187 | DOS/Windows; and colon on Mac OS. |
Greg Ward | adc1172 | 2000-07-30 00:04:17 +0000 | [diff] [blame] | 188 | |
| 189 | If 'anchor' is true (the default), then the pattern match is more |
| 190 | stringent: "*.py" will match "foo.py" but not "foo/bar.py". If |
| 191 | 'anchor' is false, both of these will match. |
| 192 | |
| 193 | If 'prefix' is supplied, then only filenames starting with 'prefix' |
| 194 | (itself a pattern) and ending with 'pattern', with anything in between |
| 195 | them, will match. 'anchor' is ignored in this case. |
| 196 | |
| 197 | If 'is_regex' is true, 'anchor' and 'prefix' are ignored, and |
| 198 | 'pattern' is assumed to be either a string containing a regex or a |
| 199 | regex object -- no translation is done, the regex is just compiled |
| 200 | and used as-is. |
| 201 | |
| 202 | Selected strings will be added to self.files. |
| 203 | |
Collin Winter | 5b7e9d7 | 2007-08-30 03:52:21 +0000 | [diff] [blame] | 204 | Return True if files are found, False otherwise. |
Greg Ward | adc1172 | 2000-07-30 00:04:17 +0000 | [diff] [blame] | 205 | """ |
Collin Winter | 5b7e9d7 | 2007-08-30 03:52:21 +0000 | [diff] [blame] | 206 | files_found = False |
Greg Ward | 071ed76 | 2000-09-26 02:12:31 +0000 | [diff] [blame] | 207 | pattern_re = translate_pattern(pattern, anchor, prefix, is_regex) |
Greg Ward | 0f34185 | 2000-07-30 00:36:25 +0000 | [diff] [blame] | 208 | self.debug_print("include_pattern: applying regex r'%s'" % |
Greg Ward | adc1172 | 2000-07-30 00:04:17 +0000 | [diff] [blame] | 209 | pattern_re.pattern) |
| 210 | |
| 211 | # delayed loading of allfiles list |
Greg Ward | 979db97 | 2000-07-30 01:45:42 +0000 | [diff] [blame] | 212 | if self.allfiles is None: |
| 213 | self.findall() |
Greg Ward | adc1172 | 2000-07-30 00:04:17 +0000 | [diff] [blame] | 214 | |
| 215 | for name in self.allfiles: |
Greg Ward | 071ed76 | 2000-09-26 02:12:31 +0000 | [diff] [blame] | 216 | if pattern_re.search(name): |
Greg Ward | adc1172 | 2000-07-30 00:04:17 +0000 | [diff] [blame] | 217 | self.debug_print(" adding " + name) |
Greg Ward | 071ed76 | 2000-09-26 02:12:31 +0000 | [diff] [blame] | 218 | self.files.append(name) |
Collin Winter | 5b7e9d7 | 2007-08-30 03:52:21 +0000 | [diff] [blame] | 219 | files_found = True |
Greg Ward | adc1172 | 2000-07-30 00:04:17 +0000 | [diff] [blame] | 220 | return files_found |
| 221 | |
Greg Ward | adc1172 | 2000-07-30 00:04:17 +0000 | [diff] [blame] | 222 | |
Tarek Ziadé | 3679727 | 2010-07-22 12:50:05 +0000 | [diff] [blame] | 223 | def exclude_pattern (self, pattern, |
| 224 | anchor=1, prefix=None, is_regex=0): |
Greg Ward | adc1172 | 2000-07-30 00:04:17 +0000 | [diff] [blame] | 225 | """Remove strings (presumably filenames) from 'files' that match |
Tarek Ziadé | 3679727 | 2010-07-22 12:50:05 +0000 | [diff] [blame] | 226 | 'pattern'. Other parameters are the same as for |
| 227 | 'include_pattern()', above. |
| 228 | The list 'self.files' is modified in place. |
| 229 | Return True if files are found, False otherwise. |
Greg Ward | adc1172 | 2000-07-30 00:04:17 +0000 | [diff] [blame] | 230 | """ |
Collin Winter | 5b7e9d7 | 2007-08-30 03:52:21 +0000 | [diff] [blame] | 231 | files_found = False |
Greg Ward | 071ed76 | 2000-09-26 02:12:31 +0000 | [diff] [blame] | 232 | pattern_re = translate_pattern(pattern, anchor, prefix, is_regex) |
Greg Ward | adc1172 | 2000-07-30 00:04:17 +0000 | [diff] [blame] | 233 | self.debug_print("exclude_pattern: applying regex r'%s'" % |
| 234 | pattern_re.pattern) |
Greg Ward | 071ed76 | 2000-09-26 02:12:31 +0000 | [diff] [blame] | 235 | for i in range(len(self.files)-1, -1, -1): |
| 236 | if pattern_re.search(self.files[i]): |
Greg Ward | adc1172 | 2000-07-30 00:04:17 +0000 | [diff] [blame] | 237 | self.debug_print(" removing " + self.files[i]) |
| 238 | del self.files[i] |
Collin Winter | 5b7e9d7 | 2007-08-30 03:52:21 +0000 | [diff] [blame] | 239 | files_found = True |
Greg Ward | adc1172 | 2000-07-30 00:04:17 +0000 | [diff] [blame] | 240 | return files_found |
| 241 | |
Greg Ward | adc1172 | 2000-07-30 00:04:17 +0000 | [diff] [blame] | 242 | |
| 243 | # ---------------------------------------------------------------------- |
| 244 | # Utility functions |
| 245 | |
Collin Winter | 5b7e9d7 | 2007-08-30 03:52:21 +0000 | [diff] [blame] | 246 | def findall(dir=os.curdir): |
Greg Ward | adc1172 | 2000-07-30 00:04:17 +0000 | [diff] [blame] | 247 | """Find all files under 'dir' and return the list of full filenames |
| 248 | (relative to 'dir'). |
| 249 | """ |
| 250 | from stat import ST_MODE, S_ISREG, S_ISDIR, S_ISLNK |
| 251 | |
| 252 | list = [] |
| 253 | stack = [dir] |
| 254 | pop = stack.pop |
| 255 | push = stack.append |
| 256 | |
| 257 | while stack: |
| 258 | dir = pop() |
Greg Ward | 071ed76 | 2000-09-26 02:12:31 +0000 | [diff] [blame] | 259 | names = os.listdir(dir) |
Greg Ward | adc1172 | 2000-07-30 00:04:17 +0000 | [diff] [blame] | 260 | |
| 261 | for name in names: |
| 262 | if dir != os.curdir: # avoid the dreaded "./" syndrome |
Greg Ward | 071ed76 | 2000-09-26 02:12:31 +0000 | [diff] [blame] | 263 | fullname = os.path.join(dir, name) |
Greg Ward | adc1172 | 2000-07-30 00:04:17 +0000 | [diff] [blame] | 264 | else: |
| 265 | fullname = name |
| 266 | |
| 267 | # Avoid excess stat calls -- just one will do, thank you! |
| 268 | stat = os.stat(fullname) |
| 269 | mode = stat[ST_MODE] |
| 270 | if S_ISREG(mode): |
Greg Ward | 071ed76 | 2000-09-26 02:12:31 +0000 | [diff] [blame] | 271 | list.append(fullname) |
Greg Ward | adc1172 | 2000-07-30 00:04:17 +0000 | [diff] [blame] | 272 | elif S_ISDIR(mode) and not S_ISLNK(mode): |
Greg Ward | 071ed76 | 2000-09-26 02:12:31 +0000 | [diff] [blame] | 273 | push(fullname) |
Greg Ward | adc1172 | 2000-07-30 00:04:17 +0000 | [diff] [blame] | 274 | return list |
| 275 | |
| 276 | |
Collin Winter | 5b7e9d7 | 2007-08-30 03:52:21 +0000 | [diff] [blame] | 277 | def glob_to_re(pattern): |
Tarek Ziadé | 3679727 | 2010-07-22 12:50:05 +0000 | [diff] [blame] | 278 | """Translate a shell-like glob pattern to a regular expression; return |
| 279 | a string containing the regex. Differs from 'fnmatch.translate()' in |
| 280 | that '*' does not match "special characters" (which are |
| 281 | platform-specific). |
Greg Ward | adc1172 | 2000-07-30 00:04:17 +0000 | [diff] [blame] | 282 | """ |
Greg Ward | 071ed76 | 2000-09-26 02:12:31 +0000 | [diff] [blame] | 283 | pattern_re = fnmatch.translate(pattern) |
Greg Ward | adc1172 | 2000-07-30 00:04:17 +0000 | [diff] [blame] | 284 | |
| 285 | # '?' and '*' in the glob pattern become '.' and '.*' in the RE, which |
| 286 | # IMHO is wrong -- '?' and '*' aren't supposed to match slash in Unix, |
| 287 | # and by extension they shouldn't match such "special characters" under |
| 288 | # any OS. So change all non-escaped dots in the RE to match any |
| 289 | # character except the special characters. |
| 290 | # XXX currently the "special characters" are just slash -- i.e. this is |
| 291 | # Unix-only. |
Tarek Ziadé | 889b0aa | 2009-04-05 21:49:36 +0000 | [diff] [blame] | 292 | pattern_re = re.sub(r'((?<!\\)(\\\\)*)\.', r'\1[^/]', pattern_re) |
| 293 | |
Greg Ward | adc1172 | 2000-07-30 00:04:17 +0000 | [diff] [blame] | 294 | return pattern_re |
| 295 | |
Greg Ward | adc1172 | 2000-07-30 00:04:17 +0000 | [diff] [blame] | 296 | |
Collin Winter | 5b7e9d7 | 2007-08-30 03:52:21 +0000 | [diff] [blame] | 297 | def translate_pattern(pattern, anchor=1, prefix=None, is_regex=0): |
Greg Ward | adc1172 | 2000-07-30 00:04:17 +0000 | [diff] [blame] | 298 | """Translate a shell-like wildcard pattern to a compiled regular |
Tarek Ziadé | 3679727 | 2010-07-22 12:50:05 +0000 | [diff] [blame] | 299 | expression. Return the compiled regex. If 'is_regex' true, |
Greg Ward | adc1172 | 2000-07-30 00:04:17 +0000 | [diff] [blame] | 300 | then 'pattern' is directly compiled to a regex (if it's a string) |
| 301 | or just returned as-is (assumes it's a regex object). |
| 302 | """ |
| 303 | if is_regex: |
Guido van Rossum | 3172c5d | 2007-10-16 18:12:55 +0000 | [diff] [blame] | 304 | if isinstance(pattern, str): |
Greg Ward | adc1172 | 2000-07-30 00:04:17 +0000 | [diff] [blame] | 305 | return re.compile(pattern) |
| 306 | else: |
| 307 | return pattern |
| 308 | |
| 309 | if pattern: |
Greg Ward | 071ed76 | 2000-09-26 02:12:31 +0000 | [diff] [blame] | 310 | pattern_re = glob_to_re(pattern) |
Greg Ward | adc1172 | 2000-07-30 00:04:17 +0000 | [diff] [blame] | 311 | else: |
| 312 | pattern_re = '' |
Fred Drake | b94b849 | 2001-12-06 20:51:35 +0000 | [diff] [blame] | 313 | |
Greg Ward | adc1172 | 2000-07-30 00:04:17 +0000 | [diff] [blame] | 314 | if prefix is not None: |
Tarek Ziadé | 74c23ac | 2009-08-17 21:35:46 +0000 | [diff] [blame] | 315 | # ditch end of pattern character |
| 316 | empty_pattern = glob_to_re('') |
Tarek Ziadé | 3679727 | 2010-07-22 12:50:05 +0000 | [diff] [blame] | 317 | prefix_re = (glob_to_re(prefix))[:-len(empty_pattern)] |
Greg Ward | 071ed76 | 2000-09-26 02:12:31 +0000 | [diff] [blame] | 318 | pattern_re = "^" + os.path.join(prefix_re, ".*" + pattern_re) |
Greg Ward | adc1172 | 2000-07-30 00:04:17 +0000 | [diff] [blame] | 319 | else: # no prefix -- respect anchor flag |
| 320 | if anchor: |
| 321 | pattern_re = "^" + pattern_re |
Fred Drake | b94b849 | 2001-12-06 20:51:35 +0000 | [diff] [blame] | 322 | |
Greg Ward | 071ed76 | 2000-09-26 02:12:31 +0000 | [diff] [blame] | 323 | return re.compile(pattern_re) |