Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 # Copyright 2013 The LUCI Authors. All rights reserved. | 1 # Copyright 2013 The LUCI Authors. All rights reserved. |
| 2 # Use of this source code is governed under the Apache License, Version 2.0 | 2 # Use of this source code is governed under the Apache License, Version 2.0 |
| 3 # that can be found in the LICENSE file. | 3 # that can be found in the LICENSE file. |
| 4 | 4 |
| 5 import functools | 5 import functools |
| 6 import itertools | 6 import itertools |
| 7 import os | 7 import os |
| 8 import re | 8 import re |
| 9 import tempfile | 9 import tempfile |
| 10 | 10 |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 28 def string_filter(func): | 28 def string_filter(func): |
| 29 @functools.wraps(func) | 29 @functools.wraps(func) |
| 30 def inner(*args, **kwargs): | 30 def inner(*args, **kwargs): |
| 31 return func(*map(str, args), **kwargs) | 31 return func(*map(str, args), **kwargs) |
| 32 return inner | 32 return inner |
| 33 | 33 |
| 34 | 34 |
| 35 class path_set(object): | 35 class path_set(object): |
| 36 """ implements a set which contains all the parents folders of added folders. | 36 """ implements a set which contains all the parents folders of added folders. |
| 37 """ | 37 """ |
| 38 # TODO(iannucci): Expand this to be a full fakey filesystem, including file | |
| 39 # contents and file types. Coordinate with the `file` module. | |
| 38 def __init__(self, path_mod, initial_paths): | 40 def __init__(self, path_mod, initial_paths): |
| 39 self._path_mod = path_mod | 41 self._path_mod = path_mod |
| 40 self._initial_paths = set(initial_paths) | 42 self._initial_paths = set(initial_paths) |
| 41 self._paths = set() | 43 self._paths = set() |
| 42 | 44 |
| 43 def _initialize(self): | 45 def _initialize(self): |
| 44 self._initialize = lambda: None | 46 self._initialize = lambda: None |
| 45 for path in self._initial_paths: | 47 for path in self._initial_paths: |
| 46 self.add(path) | 48 self.add(path) |
| 47 self._initial_paths = None | 49 self._initial_paths = None |
| 48 self.contains = lambda path: path in self._paths | 50 self.contains = lambda path: path in self._paths |
| 49 | 51 |
| 50 def add(self, path): | 52 def add(self, path): |
| 51 path = str(path) | 53 path = str(path) |
| 52 self._initialize() | 54 self._initialize() |
| 53 while path: | 55 while path: |
| 54 self._paths.add(path) | 56 self._paths.add(path) |
| 55 path = self._path_mod.dirname(path) | 57 path = self._path_mod.dirname(path) |
| 56 | 58 |
| 59 def copy(self, source, dest): | |
| 60 source, dest = str(source), str(dest) | |
|
dnj
2017/05/31 16:50:40
Needs initialize?
iannucci
2017/05/31 22:59:26
Done.
| |
| 61 to_add = set() | |
| 62 for p in self._paths: | |
| 63 if p.startswith(source): | |
| 64 to_add.add(p.replace(source, dest)) | |
| 65 self._paths |= to_add | |
| 66 | |
| 67 def remove(self, path, filt): | |
| 68 path = str(path) | |
| 69 self._initialize() | |
| 70 kill_set = set(p for p in self._paths if p.startswith(path) and filt(p)) | |
| 71 self._paths -= kill_set | |
| 72 | |
| 57 def contains(self, path): | 73 def contains(self, path): |
| 58 self._initialize() | 74 self._initialize() |
| 59 return self.contains(path) | 75 return self.contains(path) |
| 60 | 76 |
| 61 | 77 |
| 62 class fake_path(object): | 78 class fake_path(object): |
| 63 """Standin for os.path when we're in test mode. | 79 """Standin for os.path when we're in test mode. |
| 64 | 80 |
| 65 This class simulates the os.path interface exposed by PathApi, respecting the | 81 This class simulates the os.path interface exposed by PathApi, respecting the |
| 66 current platform according to the `platform` module. This allows us to | 82 current platform according to the `platform` module. This allows us to |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 84 def __getattr__(self, name): | 100 def __getattr__(self, name): |
| 85 self._init_pth() | 101 self._init_pth() |
| 86 return getattr(self._pth, name) | 102 return getattr(self._pth, name) |
| 87 | 103 |
| 88 def mock_add_paths(self, path): | 104 def mock_add_paths(self, path): |
| 89 """ | 105 """ |
| 90 Adds a path and all of its parents to the set of existing paths. | 106 Adds a path and all of its parents to the set of existing paths. |
| 91 """ | 107 """ |
| 92 self._mock_path_exists.add(path) | 108 self._mock_path_exists.add(path) |
| 93 | 109 |
| 110 def mock_copy_paths(self, source, dest): | |
| 111 """ | |
| 112 Duplicates a path and all of its children to another path. | |
| 113 """ | |
| 114 self._mock_path_exists.copy(source, dest) | |
| 115 | |
| 116 def mock_remove_paths(self, path, filt): | |
| 117 """ | |
| 118 Removes a path and all of its children from the set of existing paths. | |
| 119 """ | |
| 120 self._mock_path_exists.remove(path, filt) | |
| 121 | |
| 94 def exists(self, path): # pylint: disable=E0202 | 122 def exists(self, path): # pylint: disable=E0202 |
| 95 """Return True if path refers to an existing path.""" | 123 """Return True if path refers to an existing path.""" |
| 96 return self._mock_path_exists.contains(path) | 124 return self._mock_path_exists.contains(path) |
| 97 | 125 |
| 98 # This matches: | 126 # This matches: |
| 99 # [START_DIR] | 127 # [START_DIR] |
| 100 # RECIPE[some_pkg::some_module:recipe_name] | 128 # RECIPE[some_pkg::some_module:recipe_name] |
| 101 # | 129 # |
| 102 # and friends at the beginning of a string. | 130 # and friends at the beginning of a string. |
| 103 ROOT_MATCHER = re.compile('^[A-Z_]*\[[^]]*\]') | 131 ROOT_MATCHER = re.compile('^[A-Z_]*\[[^]]*\]') |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 233 self._temp_dir = ['/'] | 261 self._temp_dir = ['/'] |
| 234 self._cache_dir = ['/', 'b', 'c'] | 262 self._cache_dir = ['/', 'b', 'c'] |
| 235 | 263 |
| 236 self.set_config('BASE') | 264 self.set_config('BASE') |
| 237 | 265 |
| 238 def mock_add_paths(self, path): | 266 def mock_add_paths(self, path): |
| 239 """For testing purposes, assert that |path| exists.""" | 267 """For testing purposes, assert that |path| exists.""" |
| 240 if self._test_data.enabled: | 268 if self._test_data.enabled: |
| 241 self._path_mod.mock_add_paths(path) | 269 self._path_mod.mock_add_paths(path) |
| 242 | 270 |
| 271 def mock_copy_paths(self, source, dest): | |
| 272 """For testing purposes, copy |source| to |dest|.""" | |
| 273 if self._test_data.enabled: | |
| 274 self._path_mod.mock_copy_paths(source, dest) | |
| 275 | |
| 276 def mock_remove_paths(self, path, filt=lambda p: True): | |
| 277 """For testing purposes, assert that |path| doesn't exist. | |
| 278 | |
| 279 Args: | |
| 280 path (str|Path) - The path to remove. | |
| 281 filt (func[str] bool) - Called for every candidate path. Return | |
| 282 True to remove this path. | |
| 283 """ | |
| 284 if self._test_data.enabled: | |
| 285 self._path_mod.mock_remove_paths(path, filt) | |
| 286 | |
| 243 def assert_absolute(self, path): | 287 def assert_absolute(self, path): |
| 244 assert self.abspath(path) == str(path), '%s is not absolute' % path | 288 assert self.abspath(path) == str(path), '%s is not absolute' % path |
| 245 | 289 |
| 246 def mkdtemp(self, prefix): | 290 def mkdtemp(self, prefix): |
| 247 """Makes a new temp directory, returns path to it.""" | 291 """Makes a new temp directory, returns path to it.""" |
| 248 if not self._test_data.enabled: # pragma: no cover | 292 if not self._test_data.enabled: # pragma: no cover |
| 249 # New path as str. | 293 # New path as str. |
| 250 new_path = tempfile.mkdtemp(prefix=prefix, dir=str(self['tmp_base'])) | 294 new_path = tempfile.mkdtemp(prefix=prefix, dir=str(self['tmp_base'])) |
| 251 # Ensure it's under self._temp_dir, convert to Path. | 295 # Ensure it's under self._temp_dir, convert to Path. |
| 252 new_path = _split_path(new_path) | 296 new_path = _split_path(new_path) |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 332 if name in self.OK_ATTRS: | 376 if name in self.OK_ATTRS: |
| 333 return getattr(self._path_mod, name) | 377 return getattr(self._path_mod, name) |
| 334 if name in self.FILTER_METHODS: | 378 if name in self.FILTER_METHODS: |
| 335 return string_filter(getattr(self._path_mod, name)) | 379 return string_filter(getattr(self._path_mod, name)) |
| 336 raise AttributeError("'%s' object has no attribute '%s'" % | 380 raise AttributeError("'%s' object has no attribute '%s'" % |
| 337 (self._path_mod, name)) # pragma: no cover | 381 (self._path_mod, name)) # pragma: no cover |
| 338 | 382 |
| 339 def __dir__(self): # pragma: no cover | 383 def __dir__(self): # pragma: no cover |
| 340 # Used for helping out show_me_the_modules.py | 384 # Used for helping out show_me_the_modules.py |
| 341 return self.__dict__.keys() + list(self.OK_ATTRS + self.FILTER_METHODS) | 385 return self.__dict__.keys() + list(self.OK_ATTRS + self.FILTER_METHODS) |
| OLD | NEW |