[path] Remove a lot of magic from the path module.
This makes all the available methods show up in the documentation and
removes some magic double-underscore methods.
This also removes refines expanduser a bit; We've only use the "~"
formulation to get the current user's homedir, not any other users'
homedir.
Will remove `expanduser` in favor of api.path['home'] in downstream
repos as a followup.
R=yiwzhang@google.com
Change-Id: I6edd0ae056ce1ee5c90de25f65c7af07e1a98f26
Reviewed-on: https://chromium-review.googlesource.com/c/infra/luci/recipes-py/+/2406432
Commit-Queue: Robbie Iannucci <iannucci@chromium.org>
Auto-Submit: Robbie Iannucci <iannucci@chromium.org>
Reviewed-by: Yiwei Zhang <yiwzhang@google.com>
diff --git a/README.recipes.md b/README.recipes.md
index 31837da..5ec0e3e 100644
--- a/README.recipes.md
+++ b/README.recipes.md
@@ -2027,14 +2027,14 @@
`depot_tools/infra_paths` module). Refer to those modules for additional
documentation.
-#### **class [PathApi](/recipe_modules/path/api.py#218)([RecipeApi](/recipe_engine/recipe_api.py#878)):**
+#### **class [PathApi](/recipe_modules/path/api.py#206)([RecipeApi](/recipe_engine/recipe_api.py#878)):**
-— **def [\_\_getitem\_\_](/recipe_modules/path/api.py#475)(self, name):**
+— **def [\_\_getitem\_\_](/recipe_modules/path/api.py#438)(self, name):**
Gets the base path named `name`. See module docstring for more
information.
-— **def [abs\_to\_path](/recipe_modules/path/api.py#405)(self, abs_string_path):**
+— **def [abs\_to\_path](/recipe_modules/path/api.py#368)(self, abs_string_path):**
Converts an absolute path string `string_path` to a real Path object,
using the most appropriate known base path.
@@ -2060,27 +2060,66 @@
Raises an ValueError if the preconditions are not met, otherwise returns the
Path object.
-— **def [assert\_absolute](/recipe_modules/path/api.py#345)(self, path):**
+— **def [abspath](/recipe_modules/path/api.py#461)(self, path):**
+
+Equivalent to os.path.abspath.
+
+— **def [assert\_absolute](/recipe_modules/path/api.py#307)(self, path):**
Raises AssertionError if the given path is not an absolute path.
Args:
* path (Path|str) - The path to check.
-— **def [get](/recipe_modules/path/api.py#468)(self, name, default=None):**
+— **def [basename](/recipe_modules/path/api.py#465)(self, path):**
+
+Equivalent to os.path.basename.
+
+— **def [dirname](/recipe_modules/path/api.py#469)(self, path):**
+
+Equivalent to os.path.dirname.
+
+— **def [exists](/recipe_modules/path/api.py#517)(self, path):**
+
+Equivalent to os.path.exists.
+
+The presence or absence of paths can be mocked during the execution of the
+recipe by using the mock_* methods.
+
+— **def [expanduser](/recipe_modules/path/api.py#508)(self, path):**
+
+Do not use this, use `api.path['home']` instead.
+
+This ONLY handles `path` == "~", and returns `str(api.path['home'])`.
+
+— **def [get](/recipe_modules/path/api.py#431)(self, name, default=None):**
Gets the base path named `name`. See module docstring for more
information.
-— **def [get\_config\_defaults](/recipe_modules/path/api.py#230)(self):**
+— **def [get\_config\_defaults](/recipe_modules/path/api.py#209)(self):**
Internal recipe implementation function.
-— **def [initialize](/recipe_modules/path/api.py#290)(self):**
+— **def [initialize](/recipe_modules/path/api.py#271)(self):**
Internal recipe implementation function.
-— **def [mkdtemp](/recipe_modules/path/api.py#353)(self, prefix=tempfile.template):**
+— **def [join](/recipe_modules/path/api.py#473)(self, path, \*paths):**
+
+Equivalent to os.path.join.
+
+Note that Path objects returned from this module (e.g.
+api.path['start_dir']) have a built-in join method (e.g.
+new_path = p.join('some', 'name')). Many recipe modules expect Path objects
+rather than strings. Using this `join` method gives you raw path joining
+functionality and returns a string.
+
+If your path is rooted in one of the path module's root paths (i.e. those
+retrieved with api.path[something]), then you can convert from a string path
+back to a Path with the `abs_to_path` method.
+
+— **def [mkdtemp](/recipe_modules/path/api.py#316)(self, prefix=tempfile.template):**
Makes a new temporary directory, returns Path to it.
@@ -2090,7 +2129,7 @@
Returns a Path to the new directory.
-— **def [mkstemp](/recipe_modules/path/api.py#378)(self, prefix=tempfile.template):**
+— **def [mkstemp](/recipe_modules/path/api.py#341)(self, prefix=tempfile.template):**
Makes a new temporary file, returns Path to it.
@@ -2101,15 +2140,15 @@
Returns a Path to the new file. Unlike tempfile.mkstemp, the file's file
descriptor is closed.
-— **def [mock\_add\_paths](/recipe_modules/path/api.py#324)(self, path):**
+— **def [mock\_add\_paths](/recipe_modules/path/api.py#525)(self, path):**
For testing purposes, mark that |path| exists.
-— **def [mock\_copy\_paths](/recipe_modules/path/api.py#329)(self, source, dest):**
+— **def [mock\_copy\_paths](/recipe_modules/path/api.py#530)(self, source, dest):**
For testing purposes, copy |source| to |dest|.
-— **def [mock\_remove\_paths](/recipe_modules/path/api.py#334)(self, path, filt=(lambda p: True)):**
+— **def [mock\_remove\_paths](/recipe_modules/path/api.py#535)(self, path, filt=(lambda p: True)):**
For testing purposes, assert that |path| doesn't exist.
@@ -2117,6 +2156,37 @@
* path (str|Path) - The path to remove.
* filt (func[str] bool) - Called for every candidate path. Return
True to remove this path.
+
+  **@property**<br>— **def [pardir](/recipe_modules/path/api.py#446)(self):**
+
+Equivalent to os.path.pardir.
+
+  **@property**<br>— **def [pathsep](/recipe_modules/path/api.py#456)(self):**
+
+Equivalent to os.path.pathsep.
+
+— **def [realpath](/recipe_modules/path/api.py#496)(self, path):**
+
+Equivalent to os.path.realpath.
+
+— **def [relpath](/recipe_modules/path/api.py#500)(self, path, start):**
+
+Roughly equivalent to os.path.relpath.
+
+Unlike os.path.relpath, `start` is _required_. If you want the 'current
+directory', use the `recipe_engine/context` module's `cwd` property.
+
+  **@property**<br>— **def [sep](/recipe_modules/path/api.py#451)(self):**
+
+Equivalent to os.path.sep.
+
+— **def [split](/recipe_modules/path/api.py#488)(self, path):**
+
+Equivalent to os.path.split.
+
+— **def [splitext](/recipe_modules/path/api.py#492)(self, path):**
+
+Equivalent to os.path.splitext.
### *recipe_modules* / [platform](/recipe_modules/platform)
[DEPS](/recipe_modules/platform/__init__.py#5): [version](#recipe_modules-version)
diff --git a/recipe_modules/path/api.py b/recipe_modules/path/api.py
index 5204a1a..8001d59 100644
--- a/recipe_modules/path/api.py
+++ b/recipe_modules/path/api.py
@@ -58,15 +58,6 @@
return PathToString_inner
-def string_filter(func):
-
- @functools.wraps(func)
- def inner(*args, **kwargs):
- return func(*map(str, args), **{k: str(v) for k, v in kwargs.iteritems()})
-
- return inner
-
-
class path_set(object):
""" implements a set which contains all the parents folders of added folders.
"""
@@ -78,7 +69,7 @@
self._initial_paths = set(initial_paths)
self._paths = set()
- def _initialize(self):
+ def _initialize(self): # pylint: disable=method-hidden
self._initialize = lambda: None
for path in self._initial_paths:
self.add(path)
@@ -125,7 +116,7 @@
if self._is_contained_in(p, path, match_root) and filt(p))
self._paths -= kill_set
- def contains(self, path):
+ def contains(self, path): # pylint: disable=method-hidden
self._initialize()
return self.contains(path)
@@ -211,22 +202,10 @@
"""Returns the canonical version of the path."""
return self.normpath(path)
- def expanduser(self, path):
- return path.replace('~', '[HOME]')
-
class PathApi(recipe_api.RecipeApi):
_paths_client = recipe_api.RequireClient('paths')
- # Attribute accesses that we pass through to our "_path_mod" module.
- OK_ATTRS = ('pardir', 'sep', 'pathsep')
-
- # Because the native 'path' type in python is a str, we filter the *args
- # of these methods to stringify them first (otherwise they would be getting
- # recipe_util_types.Path instances).
- FILTER_METHODS = ('abspath', 'basename', 'dirname', 'exists', 'expanduser',
- 'join', 'split', 'splitext', 'realpath', 'relpath')
-
def get_config_defaults(self):
"""Internal recipe implementation function."""
return {
@@ -236,6 +215,7 @@
'TEMP_DIR': self._temp_dir,
'CACHE_DIR': self._cache_dir,
'CLEANUP_DIR': self._cleanup_dir,
+ 'HOME_DIR': self._home_dir,
}
def __init__(self, path_properties, **kwargs):
@@ -247,10 +227,11 @@
# Assigned at "initialize".
self._path_mod = None # NT or POSIX path module, or "os.path" in prod.
- self._start_dir = None
+ self._startup_cwd = None
self._temp_dir = None
self._cache_dir = None
self._cleanup_dir = None
+ self._home_dir = None
# Used in mkdtemp when generating and checking expectations.
self._test_counter = 0
@@ -293,6 +274,7 @@
self._path_mod = os.path
start_dir = self._paths_client.start_dir
self._startup_cwd = self._split_path(start_dir)
+ self._home_dir = self._split_path(self._path_mod.expanduser('~'))
tmp_dir = self._read_path('temp_dir', tempfile.gettempdir())
self._ensure_dir(tmp_dir)
@@ -318,37 +300,18 @@
self._temp_dir = [root]
self._cache_dir = [root, 'b', 'c']
self._cleanup_dir = [root, 'b', 'cleanup']
+ self._home_dir = [root, 'home', 'fake_user']
self.set_config('BASE')
- def mock_add_paths(self, path):
- """For testing purposes, mark that |path| exists."""
- if self._test_data.enabled:
- self._path_mod.mock_add_paths(path)
-
- def mock_copy_paths(self, source, dest):
- """For testing purposes, copy |source| to |dest|."""
- if self._test_data.enabled:
- self._path_mod.mock_copy_paths(source, dest)
-
- def mock_remove_paths(self, path, filt=lambda p: True):
- """For testing purposes, assert that |path| doesn't exist.
-
- Args:
- * path (str|Path) - The path to remove.
- * filt (func[str] bool) - Called for every candidate path. Return
- True to remove this path.
- """
- if self._test_data.enabled:
- self._path_mod.mock_remove_paths(path, filt)
-
def assert_absolute(self, path):
"""Raises AssertionError if the given path is not an absolute path.
Args:
* path (Path|str) - The path to check.
"""
- assert self.abspath(path) == str(path), '%s is not absolute' % path
+ if self.abspath(path) != str(path):
+ raise AssertionError('%s is not absolute' % path)
def mkdtemp(self, prefix=tempfile.template):
"""Makes a new temporary directory, returns Path to it.
@@ -480,15 +443,102 @@
raise KeyError('Unknown path: %s' % name)
return result
- def __getattr__(self, name):
- # retrieve os.path attributes
- if name in self.OK_ATTRS:
- return getattr(self._path_mod, name)
- if name in self.FILTER_METHODS:
- return string_filter(getattr(self._path_mod, name))
- raise AttributeError("'%s' object has no attribute '%s'" %
- (self._path_mod, name)) # pragma: no cover
+ @property
+ def pardir(self):
+ """Equivalent to os.path.pardir."""
+ return self._path_mod.pardir
- def __dir__(self): # pragma: no cover
- # Used for helping out show_me_the_modules.py
- return self.__dict__.keys() + list(self.OK_ATTRS + self.FILTER_METHODS)
+ @property
+ def sep(self):
+ """Equivalent to os.path.sep."""
+ return self._path_mod.sep
+
+ @property
+ def pathsep(self):
+ """Equivalent to os.path.pathsep."""
+ return self._path_mod.pathsep
+
+ def abspath(self, path):
+ """Equivalent to os.path.abspath."""
+ return self._path_mod.abspath(str(path))
+
+ def basename(self, path):
+ """Equivalent to os.path.basename."""
+ return self._path_mod.basename(str(path))
+
+ def dirname(self, path):
+ """Equivalent to os.path.dirname."""
+ return self._path_mod.dirname(str(path))
+
+ def join(self, path, *paths):
+ """Equivalent to os.path.join.
+
+ Note that Path objects returned from this module (e.g.
+ api.path['start_dir']) have a built-in join method (e.g.
+ new_path = p.join('some', 'name')). Many recipe modules expect Path objects
+ rather than strings. Using this `join` method gives you raw path joining
+ functionality and returns a string.
+
+ If your path is rooted in one of the path module's root paths (i.e. those
+ retrieved with api.path[something]), then you can convert from a string path
+ back to a Path with the `abs_to_path` method.
+ """
+ return self._path_mod.join(str(path), *map(str, paths))
+
+ def split(self, path):
+ """Equivalent to os.path.split."""
+ return self._path_mod.split(str(path))
+
+ def splitext(self, path):
+ """Equivalent to os.path.splitext."""
+ return self._path_mod.splitext(str(path))
+
+ def realpath(self, path):
+ """Equivalent to os.path.realpath."""
+ return self._path_mod.realpath(str(path))
+
+ def relpath(self, path, start):
+ """Roughly equivalent to os.path.relpath.
+
+ Unlike os.path.relpath, `start` is _required_. If you want the 'current
+ directory', use the `recipe_engine/context` module's `cwd` property.
+ """
+ return self._path_mod.relpath(str(path), str(start))
+
+ def expanduser(self, path): # pragma: no cover
+ """Do not use this, use `api.path['home']` instead.
+
+ This ONLY handles `path` == "~", and returns `str(api.path['home'])`.
+ """
+ if path == "~":
+ return str(self['home'])
+ raise ValueError("expanduser only supports `~`.")
+
+ def exists(self, path):
+ """Equivalent to os.path.exists.
+
+ The presence or absence of paths can be mocked during the execution of the
+ recipe by using the mock_* methods.
+ """
+ return self._path_mod.exists(str(path))
+
+ def mock_add_paths(self, path):
+ """For testing purposes, mark that |path| exists."""
+ if self._test_data.enabled:
+ self._path_mod.mock_add_paths(path)
+
+ def mock_copy_paths(self, source, dest):
+ """For testing purposes, copy |source| to |dest|."""
+ if self._test_data.enabled:
+ self._path_mod.mock_copy_paths(source, dest)
+
+ def mock_remove_paths(self, path, filt=lambda p: True):
+ """For testing purposes, assert that |path| doesn't exist.
+
+ Args:
+ * path (str|Path) - The path to remove.
+ * filt (func[str] bool) - Called for every candidate path. Return
+ True to remove this path.
+ """
+ if self._test_data.enabled:
+ self._path_mod.mock_remove_paths(path, filt)
diff --git a/recipe_modules/path/config.py b/recipe_modules/path/config.py
index ec8c43c..1122789 100644
--- a/recipe_modules/path/config.py
+++ b/recipe_modules/path/config.py
@@ -6,12 +6,13 @@
from recipe_engine.config_types import Path
-def BaseConfig(PLATFORM, START_DIR, TEMP_DIR, CACHE_DIR, CLEANUP_DIR,
+def BaseConfig(PLATFORM, START_DIR, TEMP_DIR, CACHE_DIR, CLEANUP_DIR, HOME_DIR,
**_kwargs):
assert START_DIR[0].endswith(('\\', '/')), START_DIR
assert TEMP_DIR[0].endswith(('\\', '/')), TEMP_DIR
assert CACHE_DIR[0].endswith(('\\', '/')), CACHE_DIR
assert CLEANUP_DIR[0].endswith(('\\', '/')), CLEANUP_DIR
+ assert HOME_DIR[0].endswith(('\\', '/')), HOME_DIR
return ConfigGroup(
# base path name -> [tokenized absolute path]
base_paths=Dict(value_type=tuple),
@@ -23,6 +24,7 @@
TEMP_DIR=Static(tuple(TEMP_DIR)),
CACHE_DIR=Static(tuple(CACHE_DIR)),
CLEANUP_DIR=Static(tuple(CLEANUP_DIR)),
+ HOME_DIR=Static(tuple(HOME_DIR)),
)
@@ -35,4 +37,5 @@
c.base_paths['tmp_base'] = c.TEMP_DIR
c.base_paths['cache'] = c.CACHE_DIR
c.base_paths['cleanup'] = c.CLEANUP_DIR
+ c.base_paths['home'] = c.HOME_DIR
c.dynamic_paths['checkout'] = None
diff --git a/recipe_modules/path/examples/full.expected/linux.json b/recipe_modules/path/examples/full.expected/linux.json
index b13f069..41fafeb 100644
--- a/recipe_modules/path/examples/full.expected/linux.json
+++ b/recipe_modules/path/examples/full.expected/linux.json
@@ -36,13 +36,6 @@
},
{
"cmd": [
- "touch",
- "[HOME]/file"
- ],
- "name": "touch my home"
- },
- {
- "cmd": [
"rm",
"-rf",
"[START_DIR]/copy2"
@@ -109,12 +102,13 @@
"echo",
"[CACHE]",
"[CLEANUP]",
+ "[HOME]",
"[START_DIR]",
"[TMP_BASE]"
],
"name": "base paths",
"~followup_annotations": [
- "@@@STEP_LOG_LINE@result@base_paths: {'start_dir': ('/', 'b', 'FakeTestingCWD'), 'cleanup': ('/', 'b', 'cleanup'), 'cache': ('/', 'b', 'c'), 'tmp_base': ('/',)}@@@",
+ "@@@STEP_LOG_LINE@result@base_paths: {'start_dir': ('/', 'b', 'FakeTestingCWD'), 'cleanup': ('/', 'b', 'cleanup'), 'cache': ('/', 'b', 'c'), 'tmp_base': ('/',), 'home': ('/', 'home', 'fake_user')}@@@",
"@@@STEP_LOG_END@result@@@"
]
},
diff --git a/recipe_modules/path/examples/full.expected/linux_kitchen.json b/recipe_modules/path/examples/full.expected/linux_kitchen.json
index b13f069..41fafeb 100644
--- a/recipe_modules/path/examples/full.expected/linux_kitchen.json
+++ b/recipe_modules/path/examples/full.expected/linux_kitchen.json
@@ -36,13 +36,6 @@
},
{
"cmd": [
- "touch",
- "[HOME]/file"
- ],
- "name": "touch my home"
- },
- {
- "cmd": [
"rm",
"-rf",
"[START_DIR]/copy2"
@@ -109,12 +102,13 @@
"echo",
"[CACHE]",
"[CLEANUP]",
+ "[HOME]",
"[START_DIR]",
"[TMP_BASE]"
],
"name": "base paths",
"~followup_annotations": [
- "@@@STEP_LOG_LINE@result@base_paths: {'start_dir': ('/', 'b', 'FakeTestingCWD'), 'cleanup': ('/', 'b', 'cleanup'), 'cache': ('/', 'b', 'c'), 'tmp_base': ('/',)}@@@",
+ "@@@STEP_LOG_LINE@result@base_paths: {'start_dir': ('/', 'b', 'FakeTestingCWD'), 'cleanup': ('/', 'b', 'cleanup'), 'cache': ('/', 'b', 'c'), 'tmp_base': ('/',), 'home': ('/', 'home', 'fake_user')}@@@",
"@@@STEP_LOG_END@result@@@"
]
},
diff --git a/recipe_modules/path/examples/full.expected/linux_luci.json b/recipe_modules/path/examples/full.expected/linux_luci.json
index b13f069..41fafeb 100644
--- a/recipe_modules/path/examples/full.expected/linux_luci.json
+++ b/recipe_modules/path/examples/full.expected/linux_luci.json
@@ -36,13 +36,6 @@
},
{
"cmd": [
- "touch",
- "[HOME]/file"
- ],
- "name": "touch my home"
- },
- {
- "cmd": [
"rm",
"-rf",
"[START_DIR]/copy2"
@@ -109,12 +102,13 @@
"echo",
"[CACHE]",
"[CLEANUP]",
+ "[HOME]",
"[START_DIR]",
"[TMP_BASE]"
],
"name": "base paths",
"~followup_annotations": [
- "@@@STEP_LOG_LINE@result@base_paths: {'start_dir': ('/', 'b', 'FakeTestingCWD'), 'cleanup': ('/', 'b', 'cleanup'), 'cache': ('/', 'b', 'c'), 'tmp_base': ('/',)}@@@",
+ "@@@STEP_LOG_LINE@result@base_paths: {'start_dir': ('/', 'b', 'FakeTestingCWD'), 'cleanup': ('/', 'b', 'cleanup'), 'cache': ('/', 'b', 'c'), 'tmp_base': ('/',), 'home': ('/', 'home', 'fake_user')}@@@",
"@@@STEP_LOG_END@result@@@"
]
},
diff --git a/recipe_modules/path/examples/full.expected/linux_swarming.json b/recipe_modules/path/examples/full.expected/linux_swarming.json
index b13f069..41fafeb 100644
--- a/recipe_modules/path/examples/full.expected/linux_swarming.json
+++ b/recipe_modules/path/examples/full.expected/linux_swarming.json
@@ -36,13 +36,6 @@
},
{
"cmd": [
- "touch",
- "[HOME]/file"
- ],
- "name": "touch my home"
- },
- {
- "cmd": [
"rm",
"-rf",
"[START_DIR]/copy2"
@@ -109,12 +102,13 @@
"echo",
"[CACHE]",
"[CLEANUP]",
+ "[HOME]",
"[START_DIR]",
"[TMP_BASE]"
],
"name": "base paths",
"~followup_annotations": [
- "@@@STEP_LOG_LINE@result@base_paths: {'start_dir': ('/', 'b', 'FakeTestingCWD'), 'cleanup': ('/', 'b', 'cleanup'), 'cache': ('/', 'b', 'c'), 'tmp_base': ('/',)}@@@",
+ "@@@STEP_LOG_LINE@result@base_paths: {'start_dir': ('/', 'b', 'FakeTestingCWD'), 'cleanup': ('/', 'b', 'cleanup'), 'cache': ('/', 'b', 'c'), 'tmp_base': ('/',), 'home': ('/', 'home', 'fake_user')}@@@",
"@@@STEP_LOG_END@result@@@"
]
},
diff --git a/recipe_modules/path/examples/full.expected/mac.json b/recipe_modules/path/examples/full.expected/mac.json
index b13f069..41fafeb 100644
--- a/recipe_modules/path/examples/full.expected/mac.json
+++ b/recipe_modules/path/examples/full.expected/mac.json
@@ -36,13 +36,6 @@
},
{
"cmd": [
- "touch",
- "[HOME]/file"
- ],
- "name": "touch my home"
- },
- {
- "cmd": [
"rm",
"-rf",
"[START_DIR]/copy2"
@@ -109,12 +102,13 @@
"echo",
"[CACHE]",
"[CLEANUP]",
+ "[HOME]",
"[START_DIR]",
"[TMP_BASE]"
],
"name": "base paths",
"~followup_annotations": [
- "@@@STEP_LOG_LINE@result@base_paths: {'start_dir': ('/', 'b', 'FakeTestingCWD'), 'cleanup': ('/', 'b', 'cleanup'), 'cache': ('/', 'b', 'c'), 'tmp_base': ('/',)}@@@",
+ "@@@STEP_LOG_LINE@result@base_paths: {'start_dir': ('/', 'b', 'FakeTestingCWD'), 'cleanup': ('/', 'b', 'cleanup'), 'cache': ('/', 'b', 'c'), 'tmp_base': ('/',), 'home': ('/', 'home', 'fake_user')}@@@",
"@@@STEP_LOG_END@result@@@"
]
},
diff --git a/recipe_modules/path/examples/full.expected/mac_kitchen.json b/recipe_modules/path/examples/full.expected/mac_kitchen.json
index b13f069..41fafeb 100644
--- a/recipe_modules/path/examples/full.expected/mac_kitchen.json
+++ b/recipe_modules/path/examples/full.expected/mac_kitchen.json
@@ -36,13 +36,6 @@
},
{
"cmd": [
- "touch",
- "[HOME]/file"
- ],
- "name": "touch my home"
- },
- {
- "cmd": [
"rm",
"-rf",
"[START_DIR]/copy2"
@@ -109,12 +102,13 @@
"echo",
"[CACHE]",
"[CLEANUP]",
+ "[HOME]",
"[START_DIR]",
"[TMP_BASE]"
],
"name": "base paths",
"~followup_annotations": [
- "@@@STEP_LOG_LINE@result@base_paths: {'start_dir': ('/', 'b', 'FakeTestingCWD'), 'cleanup': ('/', 'b', 'cleanup'), 'cache': ('/', 'b', 'c'), 'tmp_base': ('/',)}@@@",
+ "@@@STEP_LOG_LINE@result@base_paths: {'start_dir': ('/', 'b', 'FakeTestingCWD'), 'cleanup': ('/', 'b', 'cleanup'), 'cache': ('/', 'b', 'c'), 'tmp_base': ('/',), 'home': ('/', 'home', 'fake_user')}@@@",
"@@@STEP_LOG_END@result@@@"
]
},
diff --git a/recipe_modules/path/examples/full.expected/mac_luci.json b/recipe_modules/path/examples/full.expected/mac_luci.json
index b13f069..41fafeb 100644
--- a/recipe_modules/path/examples/full.expected/mac_luci.json
+++ b/recipe_modules/path/examples/full.expected/mac_luci.json
@@ -36,13 +36,6 @@
},
{
"cmd": [
- "touch",
- "[HOME]/file"
- ],
- "name": "touch my home"
- },
- {
- "cmd": [
"rm",
"-rf",
"[START_DIR]/copy2"
@@ -109,12 +102,13 @@
"echo",
"[CACHE]",
"[CLEANUP]",
+ "[HOME]",
"[START_DIR]",
"[TMP_BASE]"
],
"name": "base paths",
"~followup_annotations": [
- "@@@STEP_LOG_LINE@result@base_paths: {'start_dir': ('/', 'b', 'FakeTestingCWD'), 'cleanup': ('/', 'b', 'cleanup'), 'cache': ('/', 'b', 'c'), 'tmp_base': ('/',)}@@@",
+ "@@@STEP_LOG_LINE@result@base_paths: {'start_dir': ('/', 'b', 'FakeTestingCWD'), 'cleanup': ('/', 'b', 'cleanup'), 'cache': ('/', 'b', 'c'), 'tmp_base': ('/',), 'home': ('/', 'home', 'fake_user')}@@@",
"@@@STEP_LOG_END@result@@@"
]
},
diff --git a/recipe_modules/path/examples/full.expected/mac_swarming.json b/recipe_modules/path/examples/full.expected/mac_swarming.json
index b13f069..41fafeb 100644
--- a/recipe_modules/path/examples/full.expected/mac_swarming.json
+++ b/recipe_modules/path/examples/full.expected/mac_swarming.json
@@ -36,13 +36,6 @@
},
{
"cmd": [
- "touch",
- "[HOME]/file"
- ],
- "name": "touch my home"
- },
- {
- "cmd": [
"rm",
"-rf",
"[START_DIR]/copy2"
@@ -109,12 +102,13 @@
"echo",
"[CACHE]",
"[CLEANUP]",
+ "[HOME]",
"[START_DIR]",
"[TMP_BASE]"
],
"name": "base paths",
"~followup_annotations": [
- "@@@STEP_LOG_LINE@result@base_paths: {'start_dir': ('/', 'b', 'FakeTestingCWD'), 'cleanup': ('/', 'b', 'cleanup'), 'cache': ('/', 'b', 'c'), 'tmp_base': ('/',)}@@@",
+ "@@@STEP_LOG_LINE@result@base_paths: {'start_dir': ('/', 'b', 'FakeTestingCWD'), 'cleanup': ('/', 'b', 'cleanup'), 'cache': ('/', 'b', 'c'), 'tmp_base': ('/',), 'home': ('/', 'home', 'fake_user')}@@@",
"@@@STEP_LOG_END@result@@@"
]
},
diff --git a/recipe_modules/path/examples/full.expected/win.json b/recipe_modules/path/examples/full.expected/win.json
index 2b304bf..b9fdb3b 100644
--- a/recipe_modules/path/examples/full.expected/win.json
+++ b/recipe_modules/path/examples/full.expected/win.json
@@ -36,13 +36,6 @@
},
{
"cmd": [
- "touch",
- "[HOME]\\file"
- ],
- "name": "touch my home"
- },
- {
- "cmd": [
"rm",
"-rf",
"[START_DIR]\\copy2"
@@ -109,12 +102,13 @@
"echo",
"[CACHE]",
"[CLEANUP]",
+ "[HOME]",
"[START_DIR]",
"[TMP_BASE]"
],
"name": "base paths",
"~followup_annotations": [
- "@@@STEP_LOG_LINE@result@base_paths: {'start_dir': ('C:\\\\', 'b', 'FakeTestingCWD'), 'cleanup': ('C:\\\\', 'b', 'cleanup'), 'cache': ('C:\\\\', 'b', 'c'), 'tmp_base': ('C:\\\\',)}@@@",
+ "@@@STEP_LOG_LINE@result@base_paths: {'start_dir': ('C:\\\\', 'b', 'FakeTestingCWD'), 'cleanup': ('C:\\\\', 'b', 'cleanup'), 'cache': ('C:\\\\', 'b', 'c'), 'tmp_base': ('C:\\\\',), 'home': ('C:\\\\', 'home', 'fake_user')}@@@",
"@@@STEP_LOG_END@result@@@"
]
},
diff --git a/recipe_modules/path/examples/full.expected/win_kitchen.json b/recipe_modules/path/examples/full.expected/win_kitchen.json
index 2b304bf..b9fdb3b 100644
--- a/recipe_modules/path/examples/full.expected/win_kitchen.json
+++ b/recipe_modules/path/examples/full.expected/win_kitchen.json
@@ -36,13 +36,6 @@
},
{
"cmd": [
- "touch",
- "[HOME]\\file"
- ],
- "name": "touch my home"
- },
- {
- "cmd": [
"rm",
"-rf",
"[START_DIR]\\copy2"
@@ -109,12 +102,13 @@
"echo",
"[CACHE]",
"[CLEANUP]",
+ "[HOME]",
"[START_DIR]",
"[TMP_BASE]"
],
"name": "base paths",
"~followup_annotations": [
- "@@@STEP_LOG_LINE@result@base_paths: {'start_dir': ('C:\\\\', 'b', 'FakeTestingCWD'), 'cleanup': ('C:\\\\', 'b', 'cleanup'), 'cache': ('C:\\\\', 'b', 'c'), 'tmp_base': ('C:\\\\',)}@@@",
+ "@@@STEP_LOG_LINE@result@base_paths: {'start_dir': ('C:\\\\', 'b', 'FakeTestingCWD'), 'cleanup': ('C:\\\\', 'b', 'cleanup'), 'cache': ('C:\\\\', 'b', 'c'), 'tmp_base': ('C:\\\\',), 'home': ('C:\\\\', 'home', 'fake_user')}@@@",
"@@@STEP_LOG_END@result@@@"
]
},
diff --git a/recipe_modules/path/examples/full.expected/win_luci.json b/recipe_modules/path/examples/full.expected/win_luci.json
index 2b304bf..b9fdb3b 100644
--- a/recipe_modules/path/examples/full.expected/win_luci.json
+++ b/recipe_modules/path/examples/full.expected/win_luci.json
@@ -36,13 +36,6 @@
},
{
"cmd": [
- "touch",
- "[HOME]\\file"
- ],
- "name": "touch my home"
- },
- {
- "cmd": [
"rm",
"-rf",
"[START_DIR]\\copy2"
@@ -109,12 +102,13 @@
"echo",
"[CACHE]",
"[CLEANUP]",
+ "[HOME]",
"[START_DIR]",
"[TMP_BASE]"
],
"name": "base paths",
"~followup_annotations": [
- "@@@STEP_LOG_LINE@result@base_paths: {'start_dir': ('C:\\\\', 'b', 'FakeTestingCWD'), 'cleanup': ('C:\\\\', 'b', 'cleanup'), 'cache': ('C:\\\\', 'b', 'c'), 'tmp_base': ('C:\\\\',)}@@@",
+ "@@@STEP_LOG_LINE@result@base_paths: {'start_dir': ('C:\\\\', 'b', 'FakeTestingCWD'), 'cleanup': ('C:\\\\', 'b', 'cleanup'), 'cache': ('C:\\\\', 'b', 'c'), 'tmp_base': ('C:\\\\',), 'home': ('C:\\\\', 'home', 'fake_user')}@@@",
"@@@STEP_LOG_END@result@@@"
]
},
diff --git a/recipe_modules/path/examples/full.expected/win_swarming.json b/recipe_modules/path/examples/full.expected/win_swarming.json
index 2b304bf..b9fdb3b 100644
--- a/recipe_modules/path/examples/full.expected/win_swarming.json
+++ b/recipe_modules/path/examples/full.expected/win_swarming.json
@@ -36,13 +36,6 @@
},
{
"cmd": [
- "touch",
- "[HOME]\\file"
- ],
- "name": "touch my home"
- },
- {
- "cmd": [
"rm",
"-rf",
"[START_DIR]\\copy2"
@@ -109,12 +102,13 @@
"echo",
"[CACHE]",
"[CLEANUP]",
+ "[HOME]",
"[START_DIR]",
"[TMP_BASE]"
],
"name": "base paths",
"~followup_annotations": [
- "@@@STEP_LOG_LINE@result@base_paths: {'start_dir': ('C:\\\\', 'b', 'FakeTestingCWD'), 'cleanup': ('C:\\\\', 'b', 'cleanup'), 'cache': ('C:\\\\', 'b', 'c'), 'tmp_base': ('C:\\\\',)}@@@",
+ "@@@STEP_LOG_LINE@result@base_paths: {'start_dir': ('C:\\\\', 'b', 'FakeTestingCWD'), 'cleanup': ('C:\\\\', 'b', 'cleanup'), 'cache': ('C:\\\\', 'b', 'c'), 'tmp_base': ('C:\\\\',), 'home': ('C:\\\\', 'home', 'fake_user')}@@@",
"@@@STEP_LOG_END@result@@@"
]
},
diff --git a/recipe_modules/path/examples/full.py b/recipe_modules/path/examples/full.py
index c01b120..3f663c5 100644
--- a/recipe_modules/path/examples/full.py
+++ b/recipe_modules/path/examples/full.py
@@ -53,6 +53,27 @@
file_path = api.path['tmp_base'].join('new_file')
abspath = api.path.abspath(file_path)
api.path.assert_absolute(abspath)
+ try:
+ api.path.assert_absolute("not/abs")
+ assert False, "assert_absolute failed to catch relative path"
+ except AssertionError:
+ pass
+
+ assert api.path.pardir == '..'
+ if api.platform.is_win:
+ assert api.path.sep == '\\'
+ assert api.path.pathsep == ';'
+ else:
+ assert api.path.sep == '/'
+ assert api.path.pathsep == ':'
+
+ assert api.path.basename(file_path) == 'new_file'
+ assert api.path.dirname(file_path) == str(api.path['tmp_base'])
+ assert api.path.split(file_path) == (str(api.path['tmp_base']), 'new_file')
+ assert api.path.splitext('thing.bat.mkv') == ('thing.bat', '.mkv')
+
+ assert api.path.relpath(file_path, api.path['tmp_base']) == 'new_file'
+
api.step('touch me', ['touch', api.path.abspath(file_path)])
# Assert for testing that a file exists.
@@ -67,11 +88,6 @@
realpath = api.path.realpath(file_path)
assert api.path.exists(realpath)
- home_path = api.path.join(api.path.expanduser('~'), 'file')
- api.step('touch my home', ['touch', home_path])
- api.path.mock_add_paths(home_path)
- assert api.path.exists(home_path)
-
# can mock copy paths. See the file module to do this for real.
copy1 = api.path['start_dir'].join('copy1')
copy10 = api.path['start_dir'].join('copy10')