xpybuild.targets.copy

Contains the xpybuild.targets.copy.Copy target for binary file and directory copies, and the xpybuild.targets.copy.FilteredCopy target for copying text file(s) while filtering their contents through a set of mappers.

FilteredCopy uses one or more instances of xpybuild.targets.copy.FileContentsMapper to map from source to destination file contents. Several pre-defined mappers are provided:

StringReplaceLineMapper(old, new[, …])

Performs a simple string replacement for a single key/value.

createReplaceDictLineMappers(replaceDict[, …])

Create a list of line mappers based on the contents of the specified replaceDict, where values containing ${…} properties will be expanded out.

RegexLineMapper(regex, repl[, …])

Performs a regex substitution ; any ${…} xpybuild properties in the replacement string will be expanded, but not in the regex string.

OmitLines(match)

Omits lines from the input which contain the specified regular expression.

InsertFileContentsLineMapper(…)

Replace instances of the specified token with the entire contents of the specified file.

AddFileHeader(string[, disablePropertyExpansion])

Add the specified string as a header at the start of the file.

AddFileFooter(string[, disablePropertyExpansion])

Add the specified string as a footer at the end of the file.

Copy

class xpybuild.targets.copy.Copy(dest, src, implicitDependencies=None)[source]

Bases: xpybuild.basetarget.BaseTarget

Target that copies input file(s) to an output file or directory.

The parent directory will be created if it doesn’t exist already.

The ‘Copy.symlinks’ option can be set to True if symbolic links in the source should result in the creation of symbolic links in the destination.

Parameters
  • dest – the output directory (ending with a “/”) or file. Never specify a dest directory that is also written to by another target (e.g. do not specify an output directory here). If you need to write multiple files to a directory, use separate Copy targets for each, with file (rather than directory) target dest names.

  • src – the input, which may be any combination of strings, PathSets and lists of these. If these PathSets include mapping information, this will be used to define where (under the dest directory) each file is copied.

Note that only src files will be copied, any directory in the src list will be created but its contents will not be copied across - the only way to copy a directory is to use a FindPaths (or FindPaths(DirGeneratedByTarget(‘…’))) for the src, which has the ability to find its contents on disk (this is necessary to prevent complex race conditions and build errors arising from implicit directory walking during the execution phase - if all dir walking happens during dependency resolution then such errors can be easily detected before they cause a problem).

To create new empty directories that are not present in the source (mkdir), you can use this simple trick which utilizes the fact that the current directory . definitely exists. It doesn’t copy anything from inside (just copies only its ‘existence’) and uses a SingletonDestRenameMapper PathSet to provide the destination:

SingletonDestRenameMapper('my-new-dest-directory/', './'),
Parameters

implicitDependencies – provides a way to add additional implicit dependencies that will not be part of src but may affect the copy process (e.g. filtering in); this is intended for use by subclasses, do not set this explicitly.

FilteredCopy

class xpybuild.targets.copy.FilteredCopy(dest, src, *mappers, **kwargs)[source]

Bases: xpybuild.targets.copy.Copy

Target that copies one or more input text file(s) to an output file or directory, filtering each line through the specified line mappers.

The parent directory will be created if it doesn’t exist already.

Any source files determines to be binary/non-text by ExtensionBasedFileEncodingDecider.BINARY are copied without any mappers being invoked.

Parameters
  • dest – the output directory (ending with a /) or file. Never specify a dest directory that is also written to by another target (e.g. do not specify an output directory here). If you need to write multiple files to the output directory, use separate Copy targets for each.

  • src – the input, which may be any combination of strings, PathSets and lists of these.

  • mappers

    a list of objects subclassing FileContentsMapper

    that will be used to transform the file, line by line. Can be empty in which case this behaves the same as a normal Copy target. Any items in this list with the value None are ignored.

    For simple @TOKEN@ replacement see createReplaceDictLineMappers. In addition to per-line changes, it is also possible to specify mappers that add header/footer content to the file.

    Note that files are read and written in binary mode, so mappers will be dealing directly with platform-specific \n and \r characters; python’s os.linesep should be used where a platform-neutral newline is required.

  • allowUnusedMappers

    To avoid build files that accumulate unused cruft or are hard to understand, by default it is an error to include a mapper in this list that is not used, i.e. that does not in any way change the output for any file. We recommend using conditionalization to avoid passing in such mappers e.g.

    FilteredCopy(target, src, [StringReplaceLineMapper(os.linesep,'\n') if IS_WINDOWS else None]). 
    

    If this is not practical, set allowUnusedMappers=True to prevent this check.

getHashableImplicitInputs(context)[source]

Include the mapper descriptions in the implicit dependencies.

FileContentsMapper

class xpybuild.targets.copy.FileContentsMapper[source]

Bases: object

A base class for mappers that take part in text file transformation for use with FilteredCopy

Note that files are read and written in binary mode, so mappers will be dealing directly with platform-specific n and r characters; python’s os.linesep should be used where a platform-netural new line character is required.

getInstance()[source]

Called when a target begins to use a (potentially shared) line mapper. Returns the thread-safe (or stateless) FileContentsMapper instance that will be used; since most instances are inherently stateless, by default just returns self.

If you need to keep any state that changes after the prepare method is called (for example based on tracking the current filename or previously encountered lines), you need to override this and return a new instance either by calling your constructor or use Python’s copy.deepcopy() method.

prepare(context, **kwargs)[source]

Called once the build process has started and before any other method on this mapper (other than getInstance) to allow the mapper to initialize its internal variables using the build context, for example by expanding build properties.

startFile(context, src, dest)[source]

Called when the mapper starts to process a new file.

Can be used to prevent the mapper handling certain files. For stateful mappers (with an implementation of L(getInstance), this can be used to enable file-specific behaviour during mapping.

Parameters
  • context – The context.

  • src – The absolute normalized long-path-safe source file path.

  • dest – The absolute normalized long-path-safe destination file path.

Returns

True if this file can be handled by this mapper, or False if it should be ignored for this file.

mapLine(context, line)[source]

Called for every line in the file, returning the original line, a changed line, or None if the line should be deleted.

Parameters

line – The input line as a byte string.

Returns

The line to write to output as a byte string, or None if it should be omitted.

getHeader(context)[source]

Called at the start of every file. By default returns None but can return a string that will be written to the target file before anything else. Use os.linesep for new lines.

getFooter(context)[source]

Called at the end of every file. By default returns None but can return a string that will be written to the target file after everything else. Use os.linesep for new lines.

getDescription(context)[source]

Returns a string description of the transformation, to be used for up-to-date rebuild checking

getDependencies()[source]

Advanced option for specifying paths that are required to be read by this line mapper, which therefore should be dependencies of the target that uses it. Returns a list of unresolved paths.

OmitLines

class xpybuild.targets.copy.OmitLines(match)[source]

Bases: xpybuild.targets.copy.FileContentsMapper

Omits lines from the input which contain the specified regular expression. Use re.escape() on the input if a simple substring match is required.

StringReplaceLineMapper

class xpybuild.targets.copy.StringReplaceLineMapper(old, new, disablePropertyExpansion=False)[source]

Bases: xpybuild.targets.copy.FileContentsMapper

Performs a simple string replacement for a single key/value. Any ${…} xpybuild properties in the old and new strings will be expanded.

Usually will be created from a dictionary of tokens and replacements by createReplaceDictLineMappers

Parameters

disablePropertyExpansion – set to True to disable expansion of ${…} properties in the old and new strings.

RegexLineMapper

class xpybuild.targets.copy.RegexLineMapper(regex, repl, disablePropertyExpansion=False)[source]

Bases: xpybuild.targets.copy.FileContentsMapper

Performs a regex substitution ; any ${…} xpybuild properties in the replacement string will be expanded, but not in the regex string.

Note that files are written in binary mode, so rather than hardcoding the newline character “n”, python’s os.linesep should be used where a platform-neutral newline is required.

InsertFileContentsLineMapper

class xpybuild.targets.copy.InsertFileContentsLineMapper(replacementToken, filepath)[source]

Bases: xpybuild.targets.copy.FileContentsMapper

Replace instances of the specified token with the entire contents of the specified file.

filepath must be an absolute path, not a build dir relative path.

AddFileHeader

class xpybuild.targets.copy.AddFileHeader(string, disablePropertyExpansion=False)[source]

Bases: xpybuild.targets.copy.FileContentsMapper

Add the specified string as a header at the start of the file. Note that if a trailing newline is required before the rest of the file’s contents it should be included as part of the header.

Property substitution will be performed on the specified string.

Note that files are written in binary mode, so rather than hardcoding the newline character “n”, python’s os.linesep should be used where a platform-neutral newline is required.

Parameters

disablePropertyExpansion – set to True to disable expansion of ${…} properties in the old and new strings.

AddFileFooter

class xpybuild.targets.copy.AddFileFooter(string, disablePropertyExpansion=False)[source]

Bases: xpybuild.targets.copy.FileContentsMapper

Add the specified string as a footer at the end of the file. Note that if a trailing newline is required at the end of the file it should be included as part of the footer.

Property substitution will be performed on the specified string.

Note that files are written in binary mode, so rather than hardcoding the newline character “n”, python’s os.linesep should be used where a platform-neutral newline is required.

Parameters

disablePropertyExpansion – set to True to disable expansion of ${…} properties in the old and new strings.

createReplaceDictLineMappers

xpybuild.targets.copy.createReplaceDictLineMappers(replaceDict, replaceMarker='@')[source]

Create a list of line mappers based on the contents of the specified replaceDict, where values containing ${…} properties will be expanded out.

Parameters
  • replaceDict – The dictionary of keys and values

  • replaceMarker – the delimiter for keys (default=@), e.g. @KEY@ will be replaced with VALUE