xpybuild.pathsets¶
PathSets are used throughout xpybuild to specify the source files and directories to build, how they are to be checked for up-to-dateness, and (for targets where it’s relevant) the destination for each source file.
Here’s an example showing some of the most common PathSets and how to use them:
Copy('${OUTPUT_DIR}/docs/', PathSet(
'./README.txt',
'./dev/CHANGELOG.txt',
DirBasedPathSet('legal/', [
'LICENSE.txt',
'EULA.txt',
]),
FindPaths('samples/', includes=['**'], excludes=['**/*.pyc']),
FindPaths(DirGeneratedByTarget('${OUTPUT_DIR}/api-docs/')+'/html'),
AddDestPrefix('community/', FindPaths('samples-community/')),
))
The main PathSet classes
For simple cases where you just need to specify a few files statically, use PathSet
which accepts any number of
strings (which can be nested inside lists). Like all PathSet classes, relative paths are automatically resolved
relative to the directory of the .xpybuild.py
build file where the PathSet appears. If you want to add several
paths from the same directory, DirBasedPathSet
is usually the most convenient way to to that.
Sometimes it’s not practical to specify the sources statically, and for those cases FindPaths
can be used.
FindPaths
dynamically walks a directory tree, and can be configured with Ant-style glob **/*
expressions to indicate
what files (and/or empty sub-directories) to include and exclude. Importantly, FindPaths
delays walking the
directory until actually needed, to avoid slowing down the initial parsing of the build files and determining
inter-target dependencies. However since somewhat expensive to walk the file system, never use FindPaths
when
a more efficient static DirBasedPathSet
would be sufficient.
If you need to use the output of another target in a PathSet, it is very important to make sure xpybuild knows the
name of the underlying target so that it can calculate the dependencies correctly. Failure to do this can result in
unreliable builds. For targets that generate a file this happens automatically, but it’s not possible to
(efficiently!) auto-detect when the build file specifies a subdirectory or file from a target that generates a
directory - so you need to do that explicitly using DirGeneratedByTarget
.
Important
Always use DirGeneratedByTarget()
for any path that was generated by a directory target.
This is shown in the above example.
There are also other classes such as TargetsWithTag
that can use the output of some targets as the input to another.
The main PathSet classes are therefore:
|
Factory method that creates a single BasePathSet instance containing the specified strings and/or other PathSets. |
|
Constructs a pathset using a basedir and a list of (statically defined, non-globbed) basedir-relative paths within it. |
|
A lazily-evaluated PathSet that uses |
|
This special PathSet must be used for the base dir when specifying a PathSet for any paths located under a directory that is generated as part of the build process. |
|
A special PathSet that resolves to all build target output paths marked with the specified tag. |
|
A special PathSet that resolves to all build target output paths that are descendents of the specified parent dir (which is not a target itself, but somewhere under a build output directory). |
PathSet destinations and filtering
PathSets have a built-in concept of a destination
for each source path. This isn’t relevant for every target
(e.g. Java source compilation) but is very useful for others such as xpybuild.targets.copy.Copy
or
xpybuild.targets.archive.Zip
where
there’s a natural concept of a destination for each file/directory. The destination for each path is always a relative
(not absolute) path, so that the same PathSet can be used in different places. The default destination for each source
path is either the basename (without any directory prefix), or for PathSets like DirBasedPathSet
and FindPaths
that have a base directory, it’s the path relative to that directory.
There are a variety of derived PathSets that wrap around another PathSet and add logic to change the the destination
paths - for example AddDestPrefix
- or filter the results:
|
Adds a specified prefix on to the destinations of the specified PathSet. |
|
Removes all prefixes from the destinations of the specified PathSet. |
|
Strips one or more parent directory elements from the start of the destinations of the specified PathSet. |
|
Uses the specified hardcoded destination name for the specific file (and checks only a single input is supplied). |
|
Applies a functor to the destination paths of the enclosed PathSet (the PathSet’s source paths are unaffected) |
|
Applies a functor to the src paths of the enclosed PathSet to get new destinations (the PathSet’s source paths are unaffected) |
|
Filters the contents of another PathSet using a lambda includeDecider function. |
MapSrc¶
-
xpybuild.pathsets.
MapSrc
= <class 'xpybuild.pathsets.MapDestFromSrc'>¶ - Deprecated
Legacy name for
MapDestFromSrc
.
BasePathSet¶
-
class
xpybuild.pathsets.
BasePathSet
[source]¶ Bases:
object
Base class for PathSet implementations.
This is a stub class and should not be used directly.
-
resolve
(context)[source]¶ Use the specified context to resolve the contents of this pathset to a list of normalized absolute paths (using OS-dependent slashes).
Note that unless you actually need a list it is usually more efficient to iterate over resolveWithDestinations which avoids taking a copy of the data structure.
All directory paths must end with “/” or “”.
Some PathSet implementations will cache the results of resolve, if expensive (e.g. file system globbing); in such case it is essential to ensure that the implementation is thread-safe.
PathSets can contain duplicate entries (with same source and/or destination).
-
resolveWithDestinations
(context)[source]¶ Use the specified context to resolve the contents of this pathset to a list of (srcabs, destrel) pairs specifying the absolute and normalized path of each source path, and a relative normalized delimited path indicating the destination of that path (interpreted in a target-specific way by certain targets such as copy and zip).
All paths use OS-dependent slash characters (os.path.sep), and all directory paths must end with a slash to avoid confusion with file paths.
Some PathSet implementations will cache the results of resolve, if expensive (e.g. file system globbing); in such case it is essential to ensure that the implementation is thread-safe.
May raise BuildException if the resolution fails.
PathSets can contain duplicate entries (with same source and/or destination).
-
DirBasedPathSet¶
-
class
xpybuild.pathsets.
DirBasedPathSet
(dir, *children)[source]¶ Bases:
xpybuild.pathsets.BasePathSet
Constructs a pathset using a basedir and a list of (statically defined, non-globbed) basedir-relative paths within it.
If it is not possible to statically specify the files to be included and globbing is required, use
FindPaths
instead to perform a dynamic search; but since FindPaths is a lot slower due to the additional file system operations it is better to use DirBasedPathSet where possible.e.g. DirBasedPathSet(‘${MY_DIR}/’, ‘a’, ‘b/’, ‘${MY_JARS[]}’, ‘x, y, ${Z[]}’)
>>> str(DirBasedPathSet('${MY_DIR}', 'a', 'b/c/', '${MY_JARS[]}', 'd').resolveWithDestinations(BaseContext({'MY_DIR':'MY_DIR/', 'MY_JARS[]':' 1 , 2/3, 4/5/'}))).replace('\\\\','/') "[('BUILD_DIR/MY_DIR/a', 'a'), ('BUILD_DIR/MY_DIR/b/c/', 'b/c/'), ('BUILD_DIR/MY_DIR/1', '1'), ('BUILD_DIR/MY_DIR/2/3', '2/3'), ('BUILD_DIR/MY_DIR/4/5/', '4/5/'), ('BUILD_DIR/MY_DIR/d', 'd')]"
>>> DirBasedPathSet('mydir', 'a*b').resolve(BaseContext({})) Traceback (most recent call last): ... xpybuild.utils.buildexceptions.BuildException:
>>> str(PathSet('a', DirBasedPathSet(DirGeneratedByTarget('4/5/6/'), '7/8'))) 'PathSet("a", DirBasedPathSet(DirGeneratedByTarget("4/5/6/"), [\'7/8\']))'
>>> str([path for (path,pathset) in PathSet('a', DirBasedPathSet(DirGeneratedByTarget('4/5/6/'), '7/8'))._resolveUnderlyingDependencies(BaseContext({}))]).replace('\\\\','/') "['BUILD_DIR/a', 'BUILD_DIR/4/5/6/']"
- Parameters
dir – the base directory, which may include substitution variables. When fully expanded, it is essential that dir ends with a ‘/’. May be a string or a DirGeneratedByTarget.
children – strings defining the child files or dirs, which may include ${…} variables but not ‘*’ expansions. Can be specified nested inside tuples or lists if desired. If any of the child strings contains a ${…[]} variable, it will be expanded early and split around the ‘,’ character.
FindPaths¶
-
class
xpybuild.pathsets.
FindPaths
(dir, excludes=None, includes=None)[source]¶ Bases:
xpybuild.pathsets.BasePathSet
A lazily-evaluated PathSet that uses
*
and**
(ant-style) globbing to dynamically discover files (and optionally directories) under a common parent directory.As FindPaths performs a dynamic search of the file system during the dependency checking phase of each build it is considerably slower than other PathSets, so should only be used for specifying the contents of a directory with lots of entries or a file or directory where it is not possible to statically specify the filenames in the build script - for which cases always use
PathSet
orDirBasedPathSet
instead.FindPaths matching is always case-sensitive, will give an error if the dir does not exist or any of the includes fail to match anything. Sorts its output to ensure determinism.
Includes/excludes are specified using
*
and**
wildcards (similar to ant), where*
represents any path element and**
represents zero or more path elements. Path elements may not begin with a slash, or contain any backslash characters. They match paths underneath the base dir.Each include/exclude applies either to files OR directories, depending on whether it ends with a
/
. File include/excludes (e.g.foo/**
) are the most common (and the file**
pattern is the default include if none is specified). But if used for a target such as a Copy, note that empty directories will NOT be returned by file patterns, so if you wish to copy all empty directories as well as all files, use:FindPaths(..., includes=['**', '**/']).
In addition, global (non-overridable) excludes may be specified by setting the
FindPaths.Options.globalExcludesFunction
option.Destination paths (where needed) are generated from the path underneath the base dir.
FindPaths will return file or directory symlinks (with
/
suffix if directory), but will not recurse into directory symlinks.- Parameters
dir – The base directory to search (relative or absolute, may contain ${…} variables). May be a simple string, or a
DirGeneratedByTarget
to glob under a directory generated as part of the build. To find paths from a set of targets useTargetsWithinDir
(though only use this when that dynamism is truly required, as this will be slower than statically listing the targets individually or using TargetsWithTag).includes – a list of glob patterns for the files to include (excluding all others)
excludes – a list of glob patterns to exclude after processing any includes.
>>> str(FindPaths('a/b/c', includes=['*.x', 'y/**/z/foo.*'], excludes=['xx', '**/y'])) 'FindPaths("a/b/c", includes=["*.x", "y/**/z/foo.*"], excludes=["xx", "**/y"])'
>>> str(PathSet('a', FindPaths(DirGeneratedByTarget('4/5/6/'), includes='*.xml'))) 'PathSet("a", FindPaths(DirGeneratedByTarget("4/5/6/"), includes=["*.xml"], excludes=[]))'
>>> FindPaths('x', includes=['*.x', 'c:\d'], excludes=[]) Traceback (most recent call last): ... xpybuild.utils.buildexceptions.BuildException:
>>> FindPaths('x', includes=['*.x', '${foo}'], excludes=[]) Traceback (most recent call last): ... xpybuild.utils.buildexceptions.BuildException:
-
class
Options
[source]¶ Bases:
object
Options for customizing the behaviour of this type of PathSet. Can be configured with
xpybuild.propertysupport.setGlobalOption
.-
static
defaultGlobalExcludesFunction
(name)[source]¶ The default function used for the
FindPaths.Options.globalExcludesFunction
option.The current implementation excludes temporary NFS (Network File System) files matching the pattern “.nfs[0-9]”.
This function must be very fast to execute as it’s highly performance-critical for the dependency checking and build process, so simple string operations should be used instead of regular expressions.
- Parameters
name (str) – A base file/directory name (without path).
- Returns
True if this file or directory should be excluded.
-
globalExcludesFunction
= Option "FindPaths.globalExcludesFunction" (default: <function FindPaths.Options.defaultGlobalExcludesFunction>)¶ Global (non-overridable) excludes may be specified by setting this option to a function that accepts a full path and returns True if it should be ignored.
Needs to be as fast as possible.
-
static
-
resolveWithDestinations
(context)[source]¶ Uses the file system to returns a list of relative paths for files matching the specified include/exclude patterns, throwing a BuildException if none can be found.
This method will cache its result after being called the first time.
Note that it is possible the destinations may contain “../” elements - targets for which that could be a problem should check for and disallow such destinations (e.g. for copy we would not want to allow copying to destinations outside the specified root directory).
TargetsWithTag¶
-
class
xpybuild.pathsets.
TargetsWithTag
(targetTag, allowDirectories=False, walkDirectories=False)[source]¶ Bases:
xpybuild.pathsets.BasePathSet
A special PathSet that resolves to all build target output paths marked with the specified tag.
Note that this is intended mostly for files; it can be used for directories, but only to return the target directory name itself (there is no implicit FindPaths directory searching, as would be required to copy the contents of the directory).
See also
TargetsWithinDir
.- Parameters
targetTag – the tag name
allowDirectories – set this to True to allow directories to be specified (by default this is False to avoid errors where a directory is used in a Copy without FindPaths, and therefore ends up empty)
walkDirectories – implies allowDirectories. Recursively enumerate the contents of the directory at build time.
TargetsWithinDir¶
-
class
xpybuild.pathsets.
TargetsWithinDir
(parentDir)[source]¶ Bases:
xpybuild.pathsets.BasePathSet
A special PathSet that resolves to all build target output paths that are descendents of the specified parent dir (which is not a target itself, but somewhere under a build output directory). When resolved, this pathset returns a single source and destination path which is the parent directory itself.
This PathSet can be wrapped in FindPaths if the contained files and directories are needed.
See also
TargetsWithTag
.- Parameters
parentDir – a string identifying the parent dir. When resolved, must end in a slash.
FilteredPathSet¶
-
class
xpybuild.pathsets.
FilteredPathSet
(includeDecider, pathSet, delayFiltration=False)[source]¶ Bases:
xpybuild.pathsets._DerivedPathSet
Filters the contents of another PathSet using a lambda includeDecider function.
>>> str(FilteredPathSet(isDirPath, PathSet('a', 'b/', 'd/e', 'e/f/', 'g${x}')).resolveWithDestinations(BaseContext({'x':'/x/'}))).replace('\\\\','/') "[('BUILD_DIR/b/', 'b/'), ('BUILD_DIR/e/f/', 'f/'), ('BUILD_DIR/g/x/', 'x/')]"
>>> str(FilteredPathSet(isDirPath, PathSet('a', 'b/', 'd/e', 'e/f/', 'g${x}'))) 'FilteredPathSet(isDirPath, PathSet("a", "b/", "d/e", "e/f/", "g${x}"))'
>>> str(PathSet('a', FilteredPathSet(lambda x: True, DirGeneratedByTarget('4/5/6/')))) 'PathSet("a", FilteredPathSet(<lambda>, DirGeneratedByTarget("4/5/6/")))'
>>> str([path for (path,pathset) in PathSet('a', FilteredPathSet(isDirPath, DirGeneratedByTarget('4/5/6/')))._resolveUnderlyingDependencies(BaseContext({}))]).replace('\\\\','/') "['BUILD_DIR/a', 'BUILD_DIR/4/5/6/']"
>>> str([path for (path,pathset) in PathSet('a', FilteredPathSet(lambda p:p.endswith('.java'), FindPaths(DirGeneratedByTarget('4/5/6/'))))._resolveUnderlyingDependencies(BaseContext({}))]).replace('\\\\','/') "['BUILD_DIR/a', 'BUILD_DIR/4/5/6/']"
Construct a PathSet that filters its input, e.g. allows only directories or only files.
- Parameters
includeDecider – a function that takes an absolute resolved path and returns True if it should be included
delayFiltration – don’t filter for dependencies, only for the set used at build time
AddDestPrefix¶
-
class
xpybuild.pathsets.
AddDestPrefix
(prefix, pathSet)[source]¶ Bases:
xpybuild.pathsets._DerivedPathSet
Adds a specified prefix on to the destinations of the specified PathSet. (the PathSet’s source paths are unaffected)
See also RemoveDestParents which does the inverse.
e.g. AddDestPrefix(‘META-INF/’, mypathset)
>>> str(AddDestPrefix('lib/bar/', DirBasedPathSet('mydir/', 'b/', 'd/e', 'e/f/')).resolveWithDestinations(BaseContext({}) )).replace('\\\\','/') "[('BUILD_DIR/mydir/b/', 'lib/bar/b/'), ('BUILD_DIR/mydir/d/e', 'lib/bar/d/e'), ('BUILD_DIR/mydir/e/f/', 'lib/bar/e/f/')]"
>>> str(AddDestPrefix('lib', DirBasedPathSet('mydir/', 'b/', 'd/e', 'e/f/')).resolveWithDestinations(BaseContext({}) )).replace('\\\\','/') "[('BUILD_DIR/mydir/b/', 'libb/'), ('BUILD_DIR/mydir/d/e', 'libd/e'), ('BUILD_DIR/mydir/e/f/', 'libe/f/')]"
>>> str(AddDestPrefix('/lib', DirBasedPathSet('mydir/', 'b/', 'd/e', 'e/f/')).resolveWithDestinations(BaseContext({}) )).replace('\\\\','/') "[('BUILD_DIR/mydir/b/', 'libb/'), ('BUILD_DIR/mydir/d/e', 'libd/e'), ('BUILD_DIR/mydir/e/f/', 'libe/f/')]"
>>> str(AddDestPrefix('lib/bar/', PathSet('a', 'b/', 'd/e', 'e/f/'))) 'AddDestPrefix(prefix="lib/bar/", PathSet("a", "b/", "d/e", "e/f/"))'
Construct an AddDestPrefix from a PathSet, path or list of paths/path sets.
- Parameters
prefix – a string that should be added to the beginning of each dest path. Usually this will end with a slash ‘/’.
pathSet – either a PathSet object of some type or something from which a path set can be constructed.
MapDest¶
-
class
xpybuild.pathsets.
MapDest
(fn, pathSet)[source]¶ Bases:
xpybuild.pathsets._DerivedPathSet
Applies a functor to the destination paths of the enclosed PathSet (the PathSet’s source paths are unaffected)
Do not use this pathset for adding a prefix to the destinations - for that
AddDestPrefix
is a better solution.Note that paths passed to the functor will always have forward slashes.
e.g. MapDest(lambda x:x.lower(), mypathset)
>>> str(MapDest(lambda x: x.rstrip('/')+'_foo', PathSet('a', 'b/', 'c${c}')).resolveWithDestinations(BaseContext({'c':'C/'}))).replace('\\\\','/') "[('BUILD_DIR/a', 'a_foo'), ('BUILD_DIR/b/', 'b_foo/'), ('BUILD_DIR/cC/', 'cC_foo/')]"
>>> str(MapDest(lambda x: x+'_foo', PathSet('a', 'b/', 'c${c}'))) 'MapDest(<lambda>, PathSet("a", "b/", "c${c}"))'
- Parameters
fn – a function that takes a resolved dest path (using forward slashes not backslashes) as input, and returns a potentially different dest path. If possible, use a named function rather than a lamba.
MapDestFromSrc¶
-
class
xpybuild.pathsets.
MapDestFromSrc
(fn, pathSet)[source]¶ Bases:
xpybuild.pathsets._DerivedPathSet
Applies a functor to the src paths of the enclosed PathSet to get new destinations (the PathSet’s source paths are unaffected)
Note that paths passed to the functor will always have forward slashes.
e.g. MapDestFromSrc(lambda x:x.lower(), mypathset)
- Parameters
fn – a function that takes a resolved dest path (using forward slashes not backslashes) as input, and returns a potentially different dest path
FlattenDest¶
-
class
xpybuild.pathsets.
FlattenDest
(pathSet)[source]¶ Bases:
xpybuild.pathsets._DerivedPathSet
Removes all prefixes from the destinations of the specified PathSet.
e.g. FlattenDest(mypathset)
>>> str(FlattenDest(PathSet('a', 'b/', 'd/e', 'e/f/'))) 'FlattenDest(PathSet("a", "b/", "d/e", "e/f/"))'
- Parameters
pathSet – The input PathSet, path or list of path/PathSets.
RemoveDestParents¶
-
class
xpybuild.pathsets.
RemoveDestParents
(dirsToRemove, pathSet)[source]¶ Bases:
xpybuild.pathsets._DerivedPathSet
Strips one or more parent directory elements from the start of the destinations of the specified PathSet. (the PathSet’s source paths are unaffected)
e.g. RemoveDestParents(2, mypathset) # strips the leading 2 parent dirs
See also AddDestPrefix which does the inverse.
>>> str(RemoveDestParents(1, DirBasedPathSet('mydir/', ['d/e', 'e/f/g/'])).resolveWithDestinations(BaseContext({}) )).replace('\\\\','/') "[('BUILD_DIR/mydir/d/e', 'e'), ('BUILD_DIR/mydir/e/f/g/', 'f/g/')]"
>>> str(RemoveDestParents(2, DirBasedPathSet('mydir/', ['a/b/c', 'a/b/c/d', 'd/e/f/', 'd/e/f/g/'])).resolveWithDestinations(BaseContext({}) )).replace('\\\\','/') "[('BUILD_DIR/mydir/a/b/c', 'c'), ('BUILD_DIR/mydir/a/b/c/d', 'c/d'), ('BUILD_DIR/mydir/d/e/f/', 'f/'), ('BUILD_DIR/mydir/d/e/f/g/', 'f/g/')]"
>>> str(RemoveDestParents(1, DirBasedPathSet('mydir/', 'a')).resolveWithDestinations(BaseContext({}) )).replace('\\\\','/') Traceback (most recent call last): ... xpybuild.utils.buildexceptions.BuildException: Cannot strip 1 parent dir(s) from "a" as it does not have that many parent directories
>>> str(RemoveDestParents(1, DirBasedPathSet('mydir/', 'b/')).resolveWithDestinations(BaseContext({}) )).replace('\\\\','/') Traceback (most recent call last): ... xpybuild.utils.buildexceptions.BuildException: Cannot strip 1 parent dir(s) from "b/" as it does not have that many parent directories
Construct an RemoveDestParents from a PathSet, path or list of paths/path sets.
- Parameters
dirsToRemove – the number of parent directory elements to remove
pathSet – either a PathSet object of some type or something from which a path set can be constructed.
SingletonDestRenameMapper¶
-
class
xpybuild.pathsets.
SingletonDestRenameMapper
(newDestRelPath, pathSet)[source]¶ Bases:
xpybuild.pathsets._DerivedPathSet
Uses the specified hardcoded destination name for the specific file (and checks only a single input is supplied). Properties in the specified dest prefix string will be expanded
e.g. (SingletonDestRenameMapper(‘meta-inf/manifest.mf’, ‘foo/mymanifest’).
>>> str(SingletonDestRenameMapper('meta-inf/manifest.mf', 'foo/bar')) 'SingletonDestRenameMapper(meta-inf/manifest.mf, PathSet("foo/bar"))'
>>> str(SingletonDestRenameMapper('meta-inf/manifest.mf', 'foo/mymanifest').resolveWithDestinations(BaseContext({}))).replace('\\\\','/') "[('BUILD_DIR/foo/mymanifest', 'meta-inf/manifest.mf')]"
- Parameters
newDestRelPath – Replacement destination path (including file name)
pathSet – The input path or PathSet, which must contain a single file.
DirGeneratedByTarget¶
-
class
xpybuild.pathsets.
DirGeneratedByTarget
(dirTargetName)[source]¶ Bases:
xpybuild.pathsets.BasePathSet
This special PathSet must be used for the base dir when specifying a PathSet for any paths located under a directory that is generated as part of the build process.
This forces the evaluation of any parent PathSet to be delayed until the target dependency has actually been built.
Often used as the first argument of a DirBasedPathSet or FindPaths.
As a convenience, the “+” operator can be used to add a string representing a relative path to a DirGeneratedByTarget (which will be converted to the equivalent DirBasedPathSet expression).
>>> str(DirGeneratedByTarget('4/5/6/')) 'DirGeneratedByTarget("4/5/6/")'
>>> str(DirGeneratedByTarget('4/5/6/')+'foo/${MY_VAR}/bar') 'DirBasedPathSet(DirGeneratedByTarget("4/5/6/"), [\'foo/${MY_VAR}/bar\'])'
- Parameters
dirTargetName – The directory that another target will generate.
PathSet¶
-
xpybuild.pathsets.
PathSet
(*items)[source]¶ Factory method that creates a single BasePathSet instance containing the specified strings and/or other PathSets.
An additional composite pathset instance will be constructed to hold them if needed.
- Parameters
items – contains strings, targets and PathSet objects, nested as deeply as you like within lists and tuples. The strings must be absolute paths, or paths relative to the build file where this PathSet is defined, in which case the PathSet must be instantiated during the build file parsing phase (relative paths cannot be used in a PathSet that is instantiated while building or resolving dependencies for a target). Paths may not contain the ‘*’ character, and directory paths must end with an explicit ‘/’.
- Returns
A BasePathSet instance.
>>> str(PathSet('a', [('b/', PathSet('1/2/3/', '4/5/6/'), ['d/e'])], 'e/f/${x}').resolveWithDestinations(BaseContext({'x':'X/'}))).replace('\\\\','/') "[('BUILD_DIR/a', 'a'), ('BUILD_DIR/b/', 'b/'), ('BUILD_DIR/1/2/3/', '3/'), ('BUILD_DIR/4/5/6/', '6/'), ('BUILD_DIR/d/e', 'e'), ('BUILD_DIR/e/f/X/', 'X/')]"
>>> str(PathSet('a', [('b/', PathSet('1/2/3/', '4/5/6/'), ['d/e'])], 'e/f/${x}').resolve(BaseContext({'x':'X/'}))).replace('\\\\','/') "['BUILD_DIR/a', 'BUILD_DIR/b/', 'BUILD_DIR/1/2/3/', 'BUILD_DIR/4/5/6/', 'BUILD_DIR/d/e', 'BUILD_DIR/e/f/X/']"
>>> str(PathSet('a', [('b/', PathSet('1/2/3/', '4/5/6/'), ['d/e'])], 'e/f/${x}')) 'PathSet("a", "b/", PathSet("1/2/3/", "4/5/6/"), "d/e", "e/f/${x}")'
>>> str([path for (path,pathset) in PathSet('a', [[PathSet('1/2/3/', DirGeneratedByTarget('4/5/6/'), '7/8/')]], DirGeneratedByTarget('9/'))._resolveUnderlyingDependencies(BaseContext({}))]).replace('\\\\','/') "['BUILD_DIR/a', 'BUILD_DIR/1/2/3/', 'BUILD_DIR/4/5/6/', 'BUILD_DIR/7/8/', 'BUILD_DIR/9/']"
>>> PathSet('a/*').resolve(BaseContext({})) Traceback (most recent call last): ... xpybuild.utils.buildexceptions.BuildException: