LSSTApplications  10.0+286,10.0+36,10.0+46,10.0-2-g4f67435,10.1+152,10.1+37,11.0,11.0+1,11.0-1-g47edd16,11.0-1-g60db491,11.0-1-g7418c06,11.0-2-g04d2804,11.0-2-g68503cd,11.0-2-g818369d,11.0-2-gb8b8ce7
LSSTDataManagementBasePackage
Public Member Functions | Public Attributes | Static Public Attributes | Properties | Private Member Functions | Private Attributes | List of all members
lsst.sconsUtils.dependencies.PackageTree Class Reference

A class for loading and managing the dependency tree of a package, as defined by its configuration module (.cfg) file. More...

Inheritance diagram for lsst.sconsUtils.dependencies.PackageTree:

Public Member Functions

def __init__
 Recursively load *.cfg files for packageName and all its dependencies. More...
 
def configure
 Configure the entire dependency tree in order. More...
 
def __contains__
 
def __getitem__
 
def get
 
def keys
 

Public Attributes

 cfgPath
 
 packages
 
 customTests
 
 primary
 

Static Public Attributes

 has_key = __contains__
 

Properties

 name = property(lambda self: self.primary.config.name)
 

Private Member Functions

def _tryImport
 
def _recurse
 

Private Attributes

 _current
 

Detailed Description

A class for loading and managing the dependency tree of a package, as defined by its configuration module (.cfg) file.

This tree isn't actually stored as a tree; it's flattened into an ordered dictionary as it is recursively loaded.

The main SCons produced by configure() and available as sconsUtils.env will contain an instance of this class as env.dependencies.

Its can be used like a read-only dictionary to check whether an optional package has been configured; a package that was not found will have a value of None, while a configured package's value will be its imported .cfg module.

Definition at line 388 of file dependencies.py.

Constructor & Destructor Documentation

def lsst.sconsUtils.dependencies.PackageTree.__init__ (   self,
  primaryName,
  noCfgFile = False 
)

Recursively load *.cfg files for packageName and all its dependencies.

Parameters
primaryNameThe name of the primary package being built.
noCfgFileIf True, this package has no .cfg file

After init, self.primary will be set to the configuration module for the primary package, and self.packages will be an OrderedDict of dependencies (excluding self.primary), ordered such that configuration can proceed in iteration order.

Definition at line 400 of file dependencies.py.

401  def __init__(self, primaryName, noCfgFile=False):
402  self.cfgPath = state.env.cfgPath
403  self.packages = collections.OrderedDict()
404  self.customTests = {
405  "CustomCFlagCheck" : CustomCFlagCheck,
406  "CustomCppFlagCheck" : CustomCppFlagCheck,
407  "CustomCompileCheck" : CustomCompileCheck,
408  "CustomLinkCheck" : CustomLinkCheck,
409  }
410  self._current = set([primaryName])
411  if noCfgFile:
412  self.primary = None
413  return
414 
415  self.primary = self._tryImport(primaryName)
416  if self.primary is None:
417  state.log.fail("Failed to load primary package configuration for %s." % primaryName)
418 
419  missingDeps = []
420  for dependency in self.primary.dependencies.get("required", ()):
421  if not self._recurse(dependency):
422  missingDeps.append(dependency)
423  if missingDeps:
424  state.log.fail("Failed to load required dependencies: \"%s\"" % '", "'.join(missingDeps))
425 
426  missingDeps = []
427  for dependency in self.primary.dependencies.get("buildRequired", ()):
428  if not self._recurse(dependency):
429  missingDeps.append(dependency)
430  if missingDeps:
431  state.log.fail("Failed to load required build dependencies: \"%s\"" % '", "'.join(missingDeps))
432 
433  for dependency in self.primary.dependencies.get("optional", ()):
434  self._recurse(dependency)
435 
436  for dependency in self.primary.dependencies.get("buildOptional", ()):
437  self._recurse(dependency)
def __init__
Recursively load *.cfg files for packageName and all its dependencies.

Member Function Documentation

def lsst.sconsUtils.dependencies.PackageTree.__contains__ (   self,
  name 
)

Definition at line 461 of file dependencies.py.

462  def __contains__(self, name):
463  return name == self.name or name in self.packages
def lsst.sconsUtils.dependencies.PackageTree.__getitem__ (   self,
  name 
)

Definition at line 466 of file dependencies.py.

467  def __getitem__(self, name):
468  if name == self.name:
469  return self.primary
470  else:
471  return self.packages[name]
def lsst.sconsUtils.dependencies.PackageTree._recurse (   self,
  name 
)
private
Recursively load a dependency.

Definition at line 505 of file dependencies.py.

506  def _recurse(self, name):
507  """Recursively load a dependency."""
508  if name in self._current:
509  state.log.fail("Detected recursive dependency involving package '%s'" % name)
510  else:
511  self._current.add(name)
512  if name in self.packages:
513  self._current.remove(name)
514  return self.packages[name] is not None
515  module = self._tryImport(name)
516  if module is None:
517  self.packages[name] = None
518  self._current.remove(name)
519  return False
520  for dependency in module.dependencies.get("required", ()):
521  if not self._recurse(dependency):
522  # We can't configure this package because a required dependency wasn't found.
523  # But this package might itself be optional, so we don't die yet.
524  self.packages[name] = None
525  self._current.remove(name)
526  state.log.warn("Could not load all dependencies for package '%s' (missing %s)." %
527  (name, dependency))
528  return False
529  for dependency in module.dependencies.get("optional", ()):
530  self._recurse(dependency)
531  # This comes last to ensure the ordering puts all dependencies first.
532  self.packages[name] = module
533  self._current.remove(name)
534  return True
535 
536 #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
def lsst.sconsUtils.dependencies.PackageTree._tryImport (   self,
  name 
)
private
Search for and import an individual configuration module from file.

Definition at line 483 of file dependencies.py.

484  def _tryImport(self, name):
485  """Search for and import an individual configuration module from file."""
486  for path in self.cfgPath:
487  filename = os.path.join(path, name + ".cfg")
488  if os.path.exists(filename):
489  try:
490  module = imp.load_source(name + "_cfg", filename)
491  except Exception as e:
492  state.log.warn("Error loading configuration %s (%s)" % (filename, e))
493  continue
494  state.log.info("Using configuration for package '%s' at '%s'." % (name, filename))
495  if not hasattr(module, "dependencies") or not isinstance(module.dependencies, dict):
496  state.log.warn("Configuration module for package '%s' lacks a dependencies dict." % name)
497  return None
498  if not hasattr(module, "config") or not isinstance(module.config, Configuration):
499  state.log.warn("Configuration module for package '%s' lacks a config object." % name)
500  return None
501  else:
502  module.config.addCustomTests(self.customTests)
503  return module
504  state.log.info("Failed to import configuration for optional package '%s'." % name)
def lsst.sconsUtils.dependencies.PackageTree.configure (   self,
  env,
  check = False 
)

Configure the entire dependency tree in order.

and return an updated environment."""

Definition at line 441 of file dependencies.py.

442  def configure(self, env, check=False):
443  conf = env.Configure(custom_tests=self.customTests)
444  for name, module in self.packages.items():
445  if module is None:
446  state.log.info("Skipping missing optional package %s." % name)
447  continue
448  if not module.config.configure(conf, packages=self.packages, check=check, build=False):
449  state.log.fail("%s was found but did not pass configuration checks." % name)
450  if self.primary:
451  self.primary.config.configure(conf, packages=self.packages, check=False, build=True)
452  env.AppendUnique(SWIGPATH=env["CPPPATH"])
453  env.AppendUnique(XSWIGPATH=env["XCPPPATH"])
454  # reverse the order of libraries in env.libs, so libraries that fulfill a dependency
455  # of another appear after it. required by the linker to successfully resolve symbols
456  # in static libraries.
457  for target in env.libs:
458  env.libs[target].reverse()
459  env = conf.Finish()
460  return env
def configure
Configure the entire dependency tree in order.
def lsst.sconsUtils.dependencies.PackageTree.get (   self,
  name,
  default = None 
)

Definition at line 472 of file dependencies.py.

473  def get(self, name, default=None):
474  if name == self.name:
475  return self.primary
476  else:
477  return self.packages.get(name)
def lsst.sconsUtils.dependencies.PackageTree.keys (   self)

Definition at line 478 of file dependencies.py.

479  def keys(self):
480  k = self.packages.keys()
481  k.append(self.name)
482  return k

Member Data Documentation

lsst.sconsUtils.dependencies.PackageTree._current
private

Definition at line 409 of file dependencies.py.

lsst.sconsUtils.dependencies.PackageTree.cfgPath

Definition at line 401 of file dependencies.py.

lsst.sconsUtils.dependencies.PackageTree.customTests

Definition at line 403 of file dependencies.py.

lsst.sconsUtils.dependencies.PackageTree.has_key = __contains__
static

Definition at line 464 of file dependencies.py.

lsst.sconsUtils.dependencies.PackageTree.packages

Definition at line 402 of file dependencies.py.

lsst.sconsUtils.dependencies.PackageTree.primary

Definition at line 411 of file dependencies.py.

Property Documentation

lsst.sconsUtils.dependencies.PackageTree.name = property(lambda self: self.primary.config.name)
static

Definition at line 438 of file dependencies.py.


The documentation for this class was generated from the following file: