LSSTApplications  10.0-2-g4f67435,11.0.rc2+1,11.0.rc2+12,11.0.rc2+3,11.0.rc2+4,11.0.rc2+5,11.0.rc2+6,11.0.rc2+7,11.0.rc2+8
LSSTDataManagementBasePackage
config.py
Go to the documentation of this file.
1 #
2 # LSST Data Management System
3 # Copyright 2008, 2009, 2010 LSST Corporation.
4 #
5 # This product includes software developed by the
6 # LSST Project (http://www.lsst.org/).
7 #
8 # This program is free software: you can redistribute it and/or modify
9 # it under the terms of the GNU General Public License as published by
10 # the Free Software Foundation, either version 3 of the License, or
11 # (at your option) any later version.
12 #
13 # This program is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 # GNU General Public License for more details.
17 #
18 # You should have received a copy of the LSST License Statement and
19 # the GNU General Public License along with this program. If not,
20 # see <http://www.lsstcorp.org/LegalNotices/>.
21 #
22 
23 import io
24 import traceback
25 import sys
26 import math
27 import copy
28 
29 from .comparison import getComparisonName, compareScalars, compareConfigs
30 
31 __all__ = ("Config", "Field", "FieldValidationError")
32 
33 def _joinNamePath(prefix=None, name=None, index=None):
34  """
35  Utility function for generating nested configuration names
36  """
37  if not prefix and not name:
38  raise ValueError("Invalid name: cannot be None")
39  elif not name:
40  name = prefix
41  elif prefix and name:
42  name = prefix + "." + name
43 
44  if index is not None:
45  return "%s[%r]"%(name, index)
46  else:
47  return name
48 
49 def _autocast(x, dtype):
50  """
51  If appropriate perform type casting of value x to type dtype,
52  otherwise return the original value x
53  """
54  if dtype==float and type(x)==int:
55  return float(x)
56  if dtype==int and type(x)==long:
57  return int(x)
58  return x
59 
60 def _typeStr(x):
61  """
62  Utility function to generate a fully qualified type name.
63 
64  This is used primarily in writing config files to be
65  executed later upon 'load'.
66  """
67  if hasattr(x, '__module__') and hasattr(x, '__name__'):
68  xtype = x
69  else:
70  xtype = type(x)
71  if xtype.__module__ == '__builtin__':
72  return xtype.__name__
73  else:
74  return "%s.%s"%(xtype.__module__, xtype.__name__)
75 
76 class ConfigMeta(type):
77  """A metaclass for Config
78 
79  Adds a dictionary containing all Field class attributes
80  as a class attribute called '_fields', and adds the name of each field as
81  an instance variable of the field itself (so you don't have to pass the
82  name of the field to the field constructor).
83  """
84  def __init__(self, name, bases, dict_):
85  type.__init__(self, name, bases, dict_)
86  self._fields = {}
87  self._source = traceback.extract_stack(limit=2)[0]
88  def getFields(classtype):
89  fields = {}
90  bases=list(classtype.__bases__)
91  bases.reverse()
92  for b in bases:
93  fields.update(getFields(b))
94 
95  for k, v in classtype.__dict__.iteritems():
96  if isinstance(v, Field):
97  fields[k] = v
98  return fields
99 
100  fields = getFields(self)
101  for k, v in fields.iteritems():
102  setattr(self, k, copy.deepcopy(v))
103 
104  def __setattr__(self, name, value):
105  if isinstance(value, Field):
106  value.name = name
107  self._fields[name] = value
108  type.__setattr__(self, name, value)
109 
110 class FieldValidationError(ValueError):
111  """
112  Custom exception class which holds additional information useful to
113  debuggin Config errors:
114  - fieldType: type of the Field which incurred the error
115  - fieldName: name of the Field which incurred the error
116  - fullname: fully qualified name of the Field instance
117  - history: full history of all changes to the Field instance
118  - fieldSource: file and line number of the Field definition
119  """
120  def __init__(self, field, config, msg):
121  self.fieldType = type(field)
122  self.fieldName = field.name
123  self.fullname = _joinNamePath(config._name, field.name)
124  self.history = config.history.setdefault(field.name, [])
125  self.fieldSource = field.source
126  self.configSource = config._source
127  error="%s '%s' failed validation: %s\n"\
128  "For more information read the Field definition at:\n%s"\
129  "And the Config definition at:\n%s"%\
130  (self.fieldType.__name__, self.fullname, msg,
131  traceback.format_list([self.fieldSource])[0],
132  traceback.format_list([self.configSource])[0])
133  ValueError.__init__(self, error)
134 
135 
136 class Field(object):
137  """A field in a a Config.
138 
139  Instances of Field should be class attributes of Config subclasses:
140  Field only supports basic data types (int, float, complex, bool, str)
141 
142  class Example(Config):
143  myInt = Field(int, "an integer field!", default=0)
144  """
145  supportedTypes=(str, bool, float, int, complex)
146 
147  def __init__(self, doc, dtype, default=None, check=None, optional=False):
148  """Initialize a Field.
149 
150  dtype ------ Data type for the field.
151  doc -------- Documentation for the field.
152  default ---- A default value for the field.
153  check ------ A callable to be called with the field value that returns
154  False if the value is invalid. More complex inter-field
155  validation can be written as part of Config validate()
156  method; this will be ignored if set to None.
157  optional --- When False, Config validate() will fail if value is None
158  """
159  if dtype not in self.supportedTypes:
160  raise ValueError("Unsupported Field dtype %s"%_typeStr(dtype))
161  source = traceback.extract_stack(limit=2)[0]
162  self._setup(doc=doc, dtype=dtype, default=default, check=check, optional=optional, source=source)
163 
164 
165  def _setup(self, doc, dtype, default, check, optional, source):
166  """
167  Convenience function provided to simplify initialization of derived
168  Field types
169  """
170  self.dtype = dtype
171  self.doc = doc
172  self.__doc__ = doc
173  self.default = default
174  self.check = check
175  self.optional = optional
176  self.source = source
177 
178  def rename(self, instance):
179  """
180  Rename an instance of this field, not the field itself.
181  This is invoked by the owning config object and should not be called
182  directly
183 
184  Only useful for fields which hold sub-configs.
185  Fields which hold subconfigs should rename each sub-config with
186  the full field name as generated by _joinNamePath
187  """
188  pass
189 
190  def validate(self, instance):
191  """
192  Base validation for any field.
193  Ensures that non-optional fields are not None.
194  Ensures type correctness
195  Ensures that user-provided check function is valid
196  Most derived Field types should call Field.validate if they choose
197  to re-implement validate
198  """
199  value = self.__get__(instance)
200  if not self.optional and value is None:
201  raise FieldValidationError(self, instance, "Required value cannot be None")
202 
203  def freeze(self, instance):
204  """
205  Make this field read-only.
206  Only important for fields which hold sub-configs.
207  Fields which hold subconfigs should freeze each sub-config.
208  """
209  pass
210 
211  def _validateValue(self, value):
212  """
213  Validate a value that is not None
214 
215  This is called from __set__
216  This is not part of the Field API. However, simple derived field types
217  may benifit from implementing _validateValue
218  """
219  if value is None:
220  return
221 
222  if not isinstance(value, self.dtype):
223  msg = "Value %s is of incorrect type %s. Expected type %s"%\
224  (value, _typeStr(value), _typeStr(self.dtype))
225  raise TypeError(msg)
226  if self.check is not None and not self.check(value):
227  msg = "Value %s is not a valid value"%str(value)
228  raise ValueError(msg)
229 
230  def save(self, outfile, instance):
231  """
232  Saves an instance of this field to file.
233  This is invoked by the owning config object, and should not be called
234  directly
235 
236  outfile ---- an open output stream.
237  """
238  value = self.__get__(instance)
239  fullname = _joinNamePath(instance._name, self.name)
240  if isinstance(value, float) and (math.isinf(value) or math.isnan(value)):
241  # non-finite numbers need special care
242  print >> outfile, "%s=float('%r')"%(fullname, value)
243  else:
244  print >> outfile, "%s=%r"%(fullname, value)
245 
246  def toDict(self, instance):
247  """
248  Convert the field value so that it can be set as the value of an item
249  in a dict.
250  This is invoked by the owning config object and should not be called
251  directly
252 
253  Simple values are passed through. Complex data structures must be
254  manipulated. For example, a field holding a sub-config should, instead
255  of the subconfig object, return a dict where the keys are the field
256  names in the subconfig, and the values are the field values in the
257  subconfig.
258  """
259  return self.__get__(instance)
260 
261  def __get__(self, instance, owner=None, at=None, label="default"):
262  """
263  Define how attribute access should occur on the Config instance
264  This is invoked by the owning config object and should not be called
265  directly
266 
267  When the field attribute is accessed on a Config class object, it
268  returns the field object itself in order to allow inspection of
269  Config classes.
270 
271  When the field attribute is access on a config instance, the actual
272  value described by the field (and held by the Config instance) is
273  returned.
274  """
275  if instance is None or not isinstance(instance, Config):
276  return self
277  else:
278  return instance._storage[self.name]
279 
280  def __set__(self, instance, value, at=None, label='assignment'):
281  """
282  Describe how attribute setting should occur on the config instance.
283  This is invoked by the owning config object and should not be called
284  directly
285 
286  Derived Field classes may need to override the behavior. When overriding
287  __set__, Field authors should follow the following rules:
288  * Do not allow modification of frozen configs
289  * Validate the new value *BEFORE* modifying the field. Except if the
290  new value is None. None is special and no attempt should be made to
291  validate it until Config.validate is called.
292  * Do not modify the Config instance to contain invalid values.
293  * If the field is modified, update the history of the field to reflect the
294  changes
295 
296  In order to decrease the need to implement this method in derived Field
297  types, value validation is performed in the method _validateValue. If
298  only the validation step differs in the derived Field, it is simpler to
299  implement _validateValue than to re-implement __set__. More complicated
300  behavior, however, may require a reimplementation.
301  """
302  if instance._frozen:
303  raise FieldValidationError(self, instance, "Cannot modify a frozen Config")
304 
305  history = instance._history.setdefault(self.name, [])
306  if value is not None:
307  value = _autocast(value, self.dtype)
308  try:
309  self._validateValue(value)
310  except BaseException, e:
311  raise FieldValidationError(self, instance, e.message)
312 
313  instance._storage[self.name] = value
314  if at is None:
315  at = traceback.extract_stack()[:-1]
316  history.append((value, at, label))
317 
318  def __delete__(self, instance, at=None, label='deletion'):
319  """
320  Describe how attribute deletion should occur on the Config instance.
321  This is invoked by the owning config object and should not be called
322  directly
323  """
324  if at is None:
325  at = traceback.extract_stack()[:-1]
326  self.__set__(instance, None, at=at, label=label)
327 
328  def _compare(self, instance1, instance2, shortcut, rtol, atol, output):
329  """Helper function for Config.compare; used to compare two fields for equality.
330 
331  Must be overridden by more complex field types.
332 
333  @param[in] instance1 LHS Config instance to compare.
334  @param[in] instance2 RHS Config instance to compare.
335  @param[in] shortcut If True, return as soon as an inequality is found.
336  @param[in] rtol Relative tolerance for floating point comparisons.
337  @param[in] atol Absolute tolerance for floating point comparisons.
338  @param[in] output If not None, a callable that takes a string, used (possibly repeatedly)
339  to report inequalities.
340 
341  Floating point comparisons are performed by numpy.allclose; refer to that for details.
342  """
343  v1 = getattr(instance1, self.name)
344  v2 = getattr(instance2, self.name)
345  name = getComparisonName(
346  _joinNamePath(instance1._name, self.name),
347  _joinNamePath(instance2._name, self.name)
348  )
349  return compareScalars(name, v1, v2, dtype=self.dtype, rtol=rtol, atol=atol, output=output)
350 
351 class RecordingImporter(object):
352  """An Importer (for sys.meta_path) that records which modules are being imported.
353 
354  Objects also act as Context Managers, so you can:
355  with RecordingImporter() as importer:
356  import stuff
357  print "Imported: " + importer.getModules()
358  This ensures it is properly uninstalled when done.
359 
360  This class makes no effort to do any importing itself.
361  """
362  def __init__(self):
363  """Create and install the Importer"""
364  self._modules = set()
365 
366  def __enter__(self):
367 
368  self.origMetaPath = sys.meta_path
369  sys.meta_path = [self] + sys.meta_path
370  return self
371 
372  def __exit__(self, *args):
373  self.uninstall()
374  return False # Don't suppress exceptions
375 
376  def uninstall(self):
377  """Uninstall the Importer"""
378  sys.meta_path = self.origMetaPath
379 
380  def find_module(self, fullname, path=None):
381  """Called as part of the 'import' chain of events.
382 
383  We return None because we don't do any importing.
384  """
385  self._modules.add(fullname)
386  return None
387 
388  def getModules(self):
389  """Return the set of modules that were imported."""
390  return self._modules
391 
392 class Config(object):
393  """Base class for control objects.
394 
395  A Config object will usually have several Field instances as class
396  attributes; these are used to define most of the base class behavior.
397  Simple derived class should be able to be defined simply by setting those
398  attributes.
399 
400  Config also emulates a dict of field name: field value
401  """
402 
403  __metaclass__ = ConfigMeta
404 
405  def __iter__(self):
406  """!Iterate over fields
407  """
408  return self._fields.__iter__()
409 
410  def keys(self):
411  """!Return the list of field names
412  """
413  return self._storage.keys()
414  def values(self):
415  """!Return the list of field values
416  """
417  return self._storage.values()
418  def items(self):
419  """!Return the list of (field name, field value) pairs
420  """
421  return self._storage.items()
422 
423  def iteritems(self):
424  """!Iterate over (field name, field value) pairs
425  """
426  return self._storage.iteritems()
427 
428  def itervalues(self):
429  """!Iterate over field values
430  """
431  return self.storage.itervalues()
432 
433  def iterkeys(self):
434  """!Iterate over field names
435  """
436  return self.storage.iterkeys()
437 
438  def __contains__(self, name):
439  """!Return True if the specified field exists in this config
440 
441  @param[in] name field name to test for
442  """
443  return self._storage.__contains__(name)
444 
445  def __new__(cls, *args, **kw):
446  """!Allocate a new Config object.
447 
448  In order to ensure that all Config object are always in a proper
449  state when handed to users or to derived Config classes, some
450  attributes are handled at allocation time rather than at initialization
451 
452  This ensures that even if a derived Config class implements __init__,
453  the author does not need to be concerned about when or even if he
454  should call the base Config.__init__
455  """
456  name = kw.pop("__name", None)
457  at = kw.pop("__at", traceback.extract_stack()[:-1])
458  # remove __label and ignore it
459  kw.pop("__label", "default")
460 
461  instance = object.__new__(cls)
462  instance._frozen=False
463  instance._name=name
464  instance._storage = {}
465  instance._history = {}
466  instance._imports = set()
467  # load up defaults
468  for field in instance._fields.itervalues():
469  instance._history[field.name]=[]
470  field.__set__(instance, field.default, at=at+[field.source], label="default")
471  # set custom default-overides
472  instance.setDefaults()
473  # set constructor overides
474  instance.update(__at=at, **kw)
475  return instance
476 
477  def __reduce__(self):
478  """Reduction for pickling (function with arguments to reproduce).
479 
480  We need to condense and reconstitute the Config, since it may contain lambdas
481  (as the 'check' elements) that cannot be pickled.
482  """
483  stream = io.BytesIO()
484  self.saveToStream(stream)
485  return (unreduceConfig, (self.__class__, stream.getvalue()))
486 
487  def setDefaults(self):
488  """
489  Derived config classes that must compute defaults rather than using the
490  Field defaults should do so here.
491  To correctly use inherited defaults, implementations of setDefaults()
492  must call their base class' setDefaults()
493  """
494  pass
495 
496  def update(self, **kw):
497  """!Update values specified by the keyword arguments
498 
499  @warning The '__at' and '__label' keyword arguments are special internal
500  keywords. They are used to strip out any internal steps from the
501  history tracebacks of the config. Modifying these keywords allows users
502  to lie about a Config's history. Please do not do so!
503  """
504  at = kw.pop("__at", traceback.extract_stack()[:-1])
505  label = kw.pop("__label", "update")
506 
507  for name, value in kw.iteritems():
508  try:
509  field = self._fields[name]
510  field.__set__(self, value, at=at, label=label)
511  except KeyError:
512  raise KeyError("No field of name %s exists in config type %s"%(name, _typeStr(self)))
513 
514  def load(self, filename, root="config"):
515  """!Modify this config in place by executing the Python code in the named file.
516 
517  @param[in] filename name of file containing config override code
518  @param[in] root name of variable in file that refers to the config being overridden
519 
520  For example: if the value of root is "config" and the file contains this text:
521  "config.myField = 5" then this config's field "myField" is set to 5.
522 
523  @deprecated For purposes of backwards compatibility, older config files that use
524  root="root" instead of root="config" will be loaded with a warning printed to sys.stderr.
525  This feature will be removed at some point.
526  """
527  with open(filename) as f:
528  code = compile(f.read(), filename=filename, mode="exec")
529  self.loadFromStream(stream=code, root=root)
530 
531  def loadFromStream(self, stream, root="config", filename=None):
532  """!Modify this config in place by executing the python code in the provided stream.
533 
534  @param[in] stream open file object, string or compiled string containing config override code
535  @param[in] root name of variable in stream that refers to the config being overridden
536  @param[in] filename name of config override file, or None if unknown or contained
537  in the stream; used for error reporting
538 
539  For example: if the value of root is "config" and the stream contains this text:
540  "config.myField = 5" then this config's field "myField" is set to 5.
541 
542  @deprecated For purposes of backwards compatibility, older config files that use
543  root="root" instead of root="config" will be loaded with a warning printed to sys.stderr.
544  This feature will be removed at some point.
545  """
546  with RecordingImporter() as importer:
547  try:
548  local = {root: self}
549  exec stream in {}, local
550  except NameError as e:
551  if root == "config" and "root" in e.args[0]:
552  if filename is None:
553  # try to determine the file name; a compiled string has attribute "co_filename",
554  # an open file has attribute "name", else give up
555  filename = getattr(stream, "co_filename", None)
556  if filename is None:
557  filename = getattr(stream, "name", "?")
558  sys.stderr.write("Config override file %r" % (filename,) + \
559  " appears to use 'root' instead of 'config'; trying with 'root'")
560  local = {"root": self}
561  exec stream in {}, local
562 
563  self._imports.update(importer.getModules())
564 
565  def save(self, filename, root="config"):
566  """!Save a python script to the named file, which, when loaded, reproduces this Config
567 
568  @param[in] filename name of file to which to write the config
569  @param[in] root name to use for the root config variable; the same value must be used when loading
570  """
571  with open(filename, 'w') as outfile:
572  self.saveToStream(outfile, root)
573 
574  def saveToStream(self, outfile, root="config"):
575  """!Save a python script to a stream, which, when loaded, reproduces this Config
576 
577  @param outfile [inout] open file object to which to write the config
578  @param root [in] name to use for the root config variable; the same value must be used when loading
579  """
580  tmp = self._name
581  self._rename(root)
582  try:
583  configType = type(self)
584  typeString = _typeStr(configType)
585  print >> outfile, "import %s" % (configType.__module__)
586  print >> outfile, "assert type(%s)==%s, 'config is of type %%s.%%s" % (root, typeString), \
587  "instead of %s' %% (type(%s).__module__, type(%s).__name__)" % (typeString, root, root)
588  self._save(outfile)
589  finally:
590  self._rename(tmp)
591 
592  def freeze(self):
593  """!Make this Config and all sub-configs read-only
594  """
595  self._frozen=True
596  for field in self._fields.itervalues():
597  field.freeze(self)
598 
599  def _save(self, outfile):
600  """!Save this Config to an open stream object
601  """
602  for imp in self._imports:
603  if imp in sys.modules and sys.modules[imp] is not None:
604  print >> outfile, "import %s" % imp
605  for field in self._fields.itervalues():
606  field.save(outfile, self)
607 
608  def toDict(self):
609  """!Return a dict of field name: value
610 
611  Correct behavior is dependent on proper implementation of Field.toDict. If implementing a new
612  Field type, you may need to implement your own toDict method.
613  """
614  dict_ = {}
615  for name, field in self._fields.iteritems():
616  dict_[name] = field.toDict(self)
617  return dict_
618 
619  def _rename(self, name):
620  """!Rename this Config object in its parent config
621 
622  @param[in] name new name for this config in its parent config
623 
624  Correct behavior is dependent on proper implementation of Field.rename. If implementing a new
625  Field type, you may need to implement your own rename method.
626  """
627  self._name = name
628  for field in self._fields.itervalues():
629  field.rename(self)
630 
631  def validate(self):
632  """!Validate the Config; raise an exception if invalid
633 
634  The base class implementation performs type checks on all fields by
635  calling Field.validate().
636 
637  Complex single-field validation can be defined by deriving new Field
638  types. As syntactic sugar, some derived Field types are defined in
639  this module which handle recursing into sub-configs
640  (ConfigField, ConfigChoiceField)
641 
642  Inter-field relationships should only be checked in derived Config
643  classes after calling this method, and base validation is complete
644  """
645  for field in self._fields.itervalues():
646  field.validate(self)
647 
648  def formatHistory(self, name, **kwargs):
649  """!Format the specified config field's history to a more human-readable format
650 
651  @param[in] name name of field whose history is wanted
652  @param[in] kwargs keyword arguments for lsst.pex.config.history.format
653  @return a string containing the formatted history
654  """
655  import lsst.pex.config.history as pexHist
656  return pexHist.format(self, name, **kwargs)
657 
658  """
659  Read-only history property
660  """
661  history = property(lambda x: x._history)
662 
663  def __setattr__(self, attr, value, at=None, label="assignment"):
664  """!Regulate which attributes can be set
665 
666  Unlike normal python objects, Config objects are locked such
667  that no additional attributes nor properties may be added to them
668  dynamically.
669 
670  Although this is not the standard Python behavior, it helps to
671  protect users from accidentally mispelling a field name, or
672  trying to set a non-existent field.
673  """
674  if attr in self._fields:
675  if at is None:
676  at=traceback.extract_stack()[:-1]
677  # This allows Field descriptors to work.
678  self._fields[attr].__set__(self, value, at=at, label=label)
679  elif hasattr(getattr(self.__class__, attr, None), '__set__'):
680  # This allows properties and other non-Field descriptors to work.
681  return object.__setattr__(self, attr, value)
682  elif attr in self.__dict__ or attr in ("_name", "_history", "_storage", "_frozen", "_imports"):
683  # This allows specific private attributes to work.
684  self.__dict__[attr] = value
685  else:
686  # We throw everything else.
687  raise AttributeError("%s has no attribute %s"%(_typeStr(self), attr))
688 
689  def __delattr__(self, attr, at=None, label="deletion"):
690  if attr in self._fields:
691  if at is None:
692  at=traceback.extract_stack()[:-1]
693  self._fields[attr].__delete__(self, at=at, label=label)
694  else:
695  object.__delattr__(self, attr)
696 
697  def __eq__(self, other):
698  if type(other) == type(self):
699  for name in self._fields:
700  thisValue = getattr(self, name)
701  otherValue = getattr(other, name)
702  if isinstance(thisValue, float) and math.isnan(thisValue):
703  if not math.isnan(otherValue):
704  return False
705  elif thisValue != otherValue:
706  return False
707  return True
708  return False
709 
710  def __ne__(self, other):
711  return not self.__eq__(other)
712 
713  def __str__(self):
714  return str(self.toDict())
715 
716  def __repr__(self):
717  return "%s(%s)" % (
718  _typeStr(self),
719  ", ".join("%s=%r" % (k, v) for k, v in self.toDict().iteritems() if v is not None)
720  )
721 
722  def compare(self, other, shortcut=True, rtol=1E-8, atol=1E-8, output=None):
723  """!Compare two Configs for equality; return True if equal
724 
725  If the Configs contain RegistryFields or ConfigChoiceFields, unselected Configs
726  will not be compared.
727 
728  @param[in] other Config object to compare with self.
729  @param[in] shortcut If True, return as soon as an inequality is found.
730  @param[in] rtol Relative tolerance for floating point comparisons.
731  @param[in] atol Absolute tolerance for floating point comparisons.
732  @param[in] output If not None, a callable that takes a string, used (possibly repeatedly)
733  to report inequalities.
734 
735  Floating point comparisons are performed by numpy.allclose; refer to that for details.
736  """
737  name1 = self._name if self._name is not None else "config"
738  name2 = other._name if other._name is not None else "config"
739  name = getComparisonName(name1, name2)
740  return compareConfigs(name, self, other, shortcut=shortcut,
741  rtol=rtol, atol=atol, output=output)
742 
743 def unreduceConfig(cls, stream):
744  config = cls()
745  config.loadFromStream(stream)
746  return config
def keys
Return the list of field names.
Definition: config.py:410
def __setattr__
Regulate which attributes can be set.
Definition: config.py:663
def freeze
Make this Config and all sub-configs read-only.
Definition: config.py:592
def saveToStream
Save a python script to a stream, which, when loaded, reproduces this Config.
Definition: config.py:574
def loadFromStream
Modify this config in place by executing the python code in the provided stream.
Definition: config.py:531
def compare
Compare two Configs for equality; return True if equal.
Definition: config.py:722
def iteritems
Iterate over (field name, field value) pairs.
Definition: config.py:423
def __contains__
Return True if the specified field exists in this config.
Definition: config.py:438
def save
Save a python script to the named file, which, when loaded, reproduces this Config.
Definition: config.py:565
def _rename
Rename this Config object in its parent config.
Definition: config.py:619
def _save
Save this Config to an open stream object.
Definition: config.py:599
def load
Modify this config in place by executing the Python code in the named file.
Definition: config.py:514
def itervalues
Iterate over field values.
Definition: config.py:428
def iterkeys
Iterate over field names.
Definition: config.py:433
def toDict
Return a dict of field name: value.
Definition: config.py:608
def __iter__
Iterate over fields.
Definition: config.py:405
def formatHistory
Format the specified config field&#39;s history to a more human-readable format.
Definition: config.py:648
def items
Return the list of (field name, field value) pairs.
Definition: config.py:418
def update
Update values specified by the keyword arguments.
Definition: config.py:496
def validate
Validate the Config; raise an exception if invalid.
Definition: config.py:631
def __new__
Allocate a new Config object.
Definition: config.py:445
def values
Return the list of field values.
Definition: config.py:414