LSSTApplications  8.0.0.0+107,8.0.0.1+13,9.1+18,9.2,master-g084aeec0a4,master-g0aced2eed8+6,master-g15627eb03c,master-g28afc54ef9,master-g3391ba5ea0,master-g3d0fb8ae5f,master-g4432ae2e89+36,master-g5c3c32f3ec+17,master-g60f1e072bb+1,master-g6a3ac32d1b,master-g76a88a4307+1,master-g7bce1f4e06+57,master-g8ff4092549+31,master-g98e65bf68e,master-ga6b77976b1+53,master-gae20e2b580+3,master-gb584cd3397+53,master-gc5448b162b+1,master-gc54cf9771d,master-gc69578ece6+1,master-gcbf758c456+22,master-gcec1da163f+63,master-gcf15f11bcc,master-gd167108223,master-gf44c96c709
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 387 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 399 of file dependencies.py.

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

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

Definition at line 465 of file dependencies.py.

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

Definition at line 508 of file dependencies.py.

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

Definition at line 482 of file dependencies.py.

483  def _tryImport(self, name):
484  """Search for and import an individual configuration module from file."""
485  filenames = []
486  envVars = ("%s_DIR_EXTRA" % name.upper(), "%s_DIR" % name.upper())
487  paths = [os.path.join(os.environ[v], "ups") for v in envVars if v in os.environ]
488  paths.extend(self.cfgPath)
489  for path in paths:
490  filename = os.path.join(path, name + ".cfg")
491  if os.path.exists(filename):
492  try:
493  module = imp.load_source(name + "_cfg", filename)
494  except Exception, e:
495  state.log.warn("Error loading configuration %s (%s)" % (filename, e))
496  continue
497  state.log.info("Using configuration for package '%s' at '%s'." % (name, filename))
498  if not hasattr(module, "dependencies") or not isinstance(module.dependencies, dict):
499  state.log.warn("Configuration module for package '%s' lacks a dependencies dict." % name)
500  return None
501  if not hasattr(module, "config") or not isinstance(module.config, Configuration):
502  state.log.warn("Configuration module for package '%s' lacks a config object." % name)
503  return None
504  else:
505  module.config.addCustomTests(self.customTests)
506  return module
507  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 440 of file dependencies.py.

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

Definition at line 471 of file dependencies.py.

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

Definition at line 477 of file dependencies.py.

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

Member Data Documentation

lsst.sconsUtils.dependencies.PackageTree._current
private

Definition at line 408 of file dependencies.py.

lsst.sconsUtils.dependencies.PackageTree.cfgPath

Definition at line 400 of file dependencies.py.

lsst.sconsUtils.dependencies.PackageTree.customTests

Definition at line 402 of file dependencies.py.

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

Definition at line 463 of file dependencies.py.

lsst.sconsUtils.dependencies.PackageTree.packages

Definition at line 401 of file dependencies.py.

lsst.sconsUtils.dependencies.PackageTree.primary

Definition at line 410 of file dependencies.py.

Property Documentation

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

Definition at line 437 of file dependencies.py.


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