예제 #1
0
	def setGlobalOption(self, key, value):
		""" Set a global value for an option

		Called internally from L{propertysupport.setGlobalOption} and does not 
		need to be called directly
		"""
		if not key in _definedOptions:
			raise BuildException("Cannot specify value for option that has not been defined \"%s\"" % key)
		if key in self._globalOptions:
			log.warn("Resetting global option %s to %s at %s", key, value, BuildFileLocation().getLineString())
		else:
			log.info("Setting global option %s to %s at %s", key, value, BuildFileLocation().getLineString())
		self._globalOptions[key] = value
예제 #2
0
def definePropertiesFromFile(propertiesFile,
                             prefix=None,
                             excludeLines=None,
                             conditions=None):
    """
	Defines a set of properties from a .properties file
	
	@param propertiesFile: The file to include properties from (can include ${...} variables)

	@param prefix: if specified, this prefix will be added to the start of all property names from this file

	@param excludeLines: a string of list of strings to search for, any KEY containing these strings will be ignored
	
	@param conditions: an optional list of string conditions that can appear in property 
	keys e.g. "FOO<condition>=bar" where lines with no condition in this list 
	are ignored. Conditions are typically lowercase. 
	"""
    if conditions:
        assert not isinstance(
            conditions, basestring), 'conditions parameter must be a list'
    __log.info('Defining properties from file: %s', propertiesFile)
    context = getBuildInitializationContext()

    propertiesFile = context.getFullPath(
        propertiesFile,
        BuildFileLocation(raiseOnError=True).buildDir)
    try:
        f = open(propertiesFile, 'r')
    except Exception, e:
        raise BuildException('Failed to open properties file "%s"' %
                             (propertiesFile),
                             causedBy=True)
예제 #3
0
    def __init__(self, dir, excludes=None, includes=None):
        """
		@param dir: 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. 

		@param includes: a list of glob patterns for the files to include (excluding all others)

		@param excludes: a list of glob patterns to exclude after processing any includes.
		"""
        self.__dir = dir
        self.includes = flatten(includes)
        self.excludes = flatten(excludes)

        bad = [
            x for x in (self.includes + self.excludes)
            if ('//' in x or x.startswith('/') or x.startswith('/')
                or '\\' in x or '${' in x)
        ]
        if bad:
            raise BuildException(
                'Invalid includes/excludes pattern in FindPaths - must not contain \\, begin or end with /, or contain substitution variables: "%s"'
                % bad[0])
        if isinstance(
                dir, basestring
        ) and '\\' in dir:  # avoid silly mistakes, and enforce consistency
            raise BuildException(
                'Invalid base directory for FindPaths - must not contain \\ (always use forward slashes)'
            )

        self.location = BuildFileLocation()
        self.__lock = threading.Lock()
        self.__cached = None
예제 #4
0
    def __init__(self, name, dependencies):
        """ Normal constructor, should only be called from sub-classes since this is a stub.

		@param name: a unique name for this target (may contain unexpanded ${...}
		variables). Should correspond to the file or directory which is created
		as a result of running this target.
		@param dependencies: a list of dependencies, which may need to be 
		flattened/expanded by the build system; may be any combination of 
		strings, PathSets and lists and may also contain unexpanded variables.
		"""

        self._optionsTargetOverridesUnresolved = {
        }  # for target-specific option overrides. for internal use (by buildcontext), do not use
        self.__optionsResolved = None  # gets assigned during end of initialization phase

        if isinstance(name, basestring):
            if '//' in name:
                raise BuildException(
                    'Invalid target name: double slashes are not permitted: %s'
                    % name)
            if '\\' in name:
                raise BuildException(
                    'Invalid target name: backslashes are not permitted: %s' %
                    name)
        self.__name = str(name)
        self.__path_src = name
        self.__tags = ['all']
        self.__priority = 0.0  # default so we can go bigger or smaller
        self.log = logging.getLogger(self.__class__.__name__)

        init = getBuildInitializationContext()
        if not init:  # doc-test mode
            self.location = BuildFileLocation(raiseOnError=False)
        else:
            self.location = BuildFileLocation(raiseOnError=True)
            init.registerTarget(self)

        # should ensure changes to the build file cause a rebuild? probs no need
        # PathSet will perform all necessary flattening etc
        self.__dependencies = PathSet(dependencies)

        self.__path = None  # set by _resolveTargetPath
        self.__workDir = None
예제 #5
0
	def __init__(self, message, location=None, causedBy=False):
		""" 
		BuildExceptions thrown during loading of the build config files will include the build file location 
		(from their call stack) in the message. BuildExceptions thrown during operations on a target 
		(dep resolution, execution, cleaning) will have information about that target added by xpybuild 
		when it is logged, so there is usually no reason to explicitly add the target name into the message. 
		
		To avoid losing essential diagnostic information, do not catch arbitrary 
		non-BuildException classes and wrap in a BuildException. 
		
		The location can optionally be specified explicitly (e.g. for pathsets with delayed evaluation). 
	
		@param message: the error cause (does not need to include the target name)
		
		@param location: usually None, or else a BuildFileLocation object for the source line that caused the problem. 
		This is useful if the build file location associated with the exception is 
		something other than a target, e.g. a PathSet. 
		
		@param causedBy: if True, takes the exception currently on the stack as the caused of this exception, and 
		adds it to the build exception message. If the cause is not a BuildException, then its stack 
		trace will be captured if this is True. 
		"""
		assert message
		self.__msg = message.strip()
		
		if causedBy:
			causedBy = sys.exc_info()
			causedByExc = causedBy[1]
			
			if isinstance(causedByExc, BuildException):
				causedByMsg = causedByExc.__msg
				if not location: location = causedByExc.__location
				self.__causedByTraceback = None # tracebacks not needed for BuildException, by definition
			else:
				causedByMsg = '%s'%causedByExc
				self.__causedByTraceback = traceback.format_exc(causedBy)
				
			if (causedByMsg not in self.__msg): self.__msg += (': %s'%causedByMsg)
			
		else: 
			assert causedBy==False
			self.__causedByTraceback = None

		# keep things simple by using None instead of an empty BuildFileLocation object
		if (not location or not location.buildFile) and BuildFileLocation._currentBuildFile:
			# only do this if we're parsing build files at the moment, otherwise it's 
			# more reliable to keep it blank and let the scheduler use the target's location
			location = BuildFileLocation(raiseOnError=False)
			if not location.buildFile: location = None
		self.__location = location
		
		Exception.__init__(self, self.__msg)
예제 #6
0
    def __init__(self, dirTargetName):
        """
		@param dirTargetName: The directory that another target will generate.
		"""
        BasePathSet.__init__(self)
        assert isinstance(dirTargetName, basestring)
        assert dirTargetName.endswith('/')
        self.__target = dirTargetName
        self.__location = BuildFileLocation()

        if '\\' in dirTargetName:  # avoid silly mistakes, and enforce consistency
            raise BuildException(
                'Invalid directory target - must not contain \\ (always use forward slashes)'
            )
예제 #7
0
    def _coerceToValidValue(value):
        value = getBuildInitializationContext().expandPropertyValues(value)

        if not os.path.isabs(value):
            # must absolutize this, as otherwise it might be used from a build
            # file in a different location, resulting in the same property
            # resolving to different effective values in different places
            value = BuildFileLocation(raiseOnError=True).buildDir + '/' + value

        value = normpath(value).rstrip('/\\')
        if mustExist and not os.path.exists(value):
            raise BuildException(
                'Invalid path property value for "%s" - path "%s" does not exist'
                % (name, value))
        return value
예제 #8
0
    def __init__(self, dir, *children):
        """
		@param 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.

		@param 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. 
		"""
        self.__dir = dir

        self.__children = flatten(children)
        self.__location = BuildFileLocation()
예제 #9
0
    def __init__(self,
                 targetTag,
                 allowDirectories=False,
                 walkDirectories=False):
        """
		@param targetTag: the tag name
		
		@param 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)
		
		@param walkDirectories: implies allowDirectories. Recursively enumerate the 
		contents of the directory at build time.
		"""
        self.__targetTag = targetTag
        self.__location = BuildFileLocation()
        self.__allowDirectories = allowDirectories or walkDirectories
        self.__walkDirectories = walkDirectories
예제 #10
0
    def __init__(self, *inputs):
        """
		Construct a PathSet from the specified strings and other pathsets. 
		
		@param inputs: 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 '/'. 
			
		>>> 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(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({})) #doctest: +IGNORE_EXCEPTION_DETAIL
		Traceback (most recent call last):
		...
		BuildException:
		"""
        super(BasePathSet, self).__init__()
        self.contents = flatten(inputs)

        self.__location = None
        for x in self.contents:
            if not (isinstance(x, basestring) or isinstance(x, BasePathSet)
                    or hasattr(x, 'resolveToString')):
                raise BuildException(
                    'PathSet may contain only strings, PathSets, Composables, targets and lists - cannot accept %s (%s)'
                    % (x, x.__class__))

        self.__location = BuildFileLocation()
예제 #11
0
    def __init__(self,
                 archivePath,
                 includes=None,
                 excludes=None,
                 destMapper=None):
        """
		@param archivePath: The archive to unpack; either a string or a singleton PathSet

		@param destMapper: A functor that takes a (context, destPath) where destPath 
		is an archive-relative path (guaranteed to contain / not \\), and 
		returns the desired destination relative path string. 
		The functor should have a deterministic and 
		user-friendly __str__ implementation. 

		@param includes: a list of include patterns (if provided excludes all non-matching files)

		@param excludes: a list of exclude patterns (processed after includes)
		"""
        self.__path = PathSet(archivePath)
        self.__destMapper = destMapper
        self.__includes = flatten(includes)
        self.__excludes = flatten(excludes)
        self.__location = BuildFileLocation()
        self.__isResolved = False
예제 #12
0
 def __init__(self, replacementToken, filepath):
     self.replacementToken, self.filepath = replacementToken, filepath
     self.baseDir = BuildFileLocation().buildDir