22 __all__ = (
"Config",
"Field",
"FieldValidationError")
34 from .comparison
import getComparisonName, compareScalars, compareConfigs
35 from .callStack
import getStackFrame, getCallStack
38 def _joinNamePath(prefix=None, name=None, index=None):
39 """Generate nested configuration names. 41 if not prefix
and not name:
42 raise ValueError(
"Invalid name: cannot be None")
46 name = prefix +
"." + name
49 return "%s[%r]" % (name, index)
54 def _autocast(x, dtype):
55 """Cast a value to a type, if appropriate. 62 Data type, such as `float`, `int`, or `str`. 67 If appropriate, the returned value is ``x`` cast to the given type 68 ``dtype``. If the cast cannot be performed the original value of 71 if dtype == float
and isinstance(x, int):
77 """Generate a fully-qualified type name. 82 Fully-qualified type name. 86 This function is used primarily for writing config files to be executed 87 later upon with the 'load' function. 89 if hasattr(x,
'__module__')
and hasattr(x,
'__name__'):
93 if (sys.version_info.major <= 2
and xtype.__module__ ==
'__builtin__')
or xtype.__module__ ==
'builtins':
96 return "%s.%s" % (xtype.__module__, xtype.__name__)
100 """A metaclass for `lsst.pex.config.Config`. 104 ``ConfigMeta`` adds a dictionary containing all `~lsst.pex.config.Field` 105 class attributes as a class attribute called ``_fields``, and adds 106 the name of each field as an instance variable of the field itself (so you 107 don't have to pass the name of the field to the field constructor). 111 type.__init__(cls, name, bases, dict_)
115 def getFields(classtype):
117 bases =
list(classtype.__bases__)
120 fields.update(getFields(b))
122 for k, v
in classtype.__dict__.items():
123 if isinstance(v, Field):
127 fields = getFields(cls)
128 for k, v
in fields.items():
129 setattr(cls, k, copy.deepcopy(v))
132 if isinstance(value, Field):
135 type.__setattr__(cls, name, value)
139 """Raised when a ``~lsst.pex.config.Field`` is not valid in a 140 particular ``~lsst.pex.config.Config``. 144 field : `lsst.pex.config.Field` 145 The field that was not valid. 146 config : `lsst.pex.config.Config` 147 The config containing the invalid field. 149 Text describing why the field was not valid. 154 """Type of the `~lsst.pex.config.Field` that incurred the error. 158 """Name of the `~lsst.pex.config.Field` instance that incurred the 163 lsst.pex.config.Field.name 166 self.
fullname = _joinNamePath(config._name, field.name)
167 """Fully-qualified name of the `~lsst.pex.config.Field` instance 171 self.
history = config.history.setdefault(field.name, [])
172 """Full history of all changes to the `~lsst.pex.config.Field` 177 """File and line number of the `~lsst.pex.config.Field` definition. 181 error =
"%s '%s' failed validation: %s\n"\
182 "For more information see the Field definition at:\n%s"\
183 " and the Config definition at:\n%s" % \
190 """A field in a `~lsst.pex.config.Config` that supports `int`, `float`, 191 `complex`, `bool`, and `str` data types. 196 A description of the field for users. 198 The field's data type. ``Field`` only supports basic data types: 199 `int`, `float`, `complex`, `bool`, and `str`. See 200 `Field.supportedTypes`. 201 default : object, optional 202 The field's default value. 203 check : callable, optional 204 A callable that is called with the field's value. This callable should 205 return `False` if the value is invalid. More complex inter-field 206 validation can be written as part of the 207 `lsst.pex.config.Config.validate` method. 208 optional : `bool`, optional 209 This sets whether the field is considered optional, and therefore 210 doesn't need to be set by the user. When `False`, 211 `lsst.pex.config.Config.validate` fails if the field's value is `None`. 212 deprecated : None or `str`, optional 213 A description of why this Field is deprecated, including removal date. 214 If not None, the string is appended to the docstring for this Field. 219 Raised when the ``dtype`` parameter is not one of the supported types 220 (see `Field.supportedTypes`). 236 ``Field`` instances (including those of any subclass of ``Field``) are used 237 as class attributes of `~lsst.pex.config.Config` subclasses (see the 238 example, below). ``Field`` attributes work like the `property` attributes 239 of classes that implement custom setters and getters. `Field` attributes 240 belong to the class, but operate on the instance. Formally speaking, 241 `Field` attributes are `descriptors 242 <https://docs.python.org/3/howto/descriptor.html>`_. 244 When you access a `Field` attribute on a `Config` instance, you don't 245 get the `Field` instance itself. Instead, you get the value of that field, 246 which might be a simple type (`int`, `float`, `str`, `bool`) or a custom 247 container type (like a `lsst.pex.config.List`) depending on the field's 248 type. See the example, below. 252 Instances of ``Field`` should be used as class attributes of 253 `lsst.pex.config.Config` subclasses: 255 >>> from lsst.pex.config import Config, Field 256 >>> class Example(Config): 257 ... myInt = Field("An integer field.", int, default=0) 259 >>> print(config.myInt) 262 >>> print(config.myInt) 266 supportedTypes =
set((str, bool, float, int, complex))
267 """Supported data types for field values (`set` of types). 270 def __init__(self, doc, dtype, default=None, check=None, optional=False, deprecated=None):
272 raise ValueError(
"Unsupported Field dtype %s" % _typeStr(dtype))
275 self.
_setup(doc=doc, dtype=dtype, default=default, check=check, optional=optional, source=source,
276 deprecated=deprecated)
278 def _setup(self, doc, dtype, default, check, optional, source, deprecated):
279 """Set attributes, usually during initialization. 282 """Data type for the field. 286 if deprecated
is not None:
287 doc = f
"{doc} Deprecated: {deprecated}" 289 """A description of the field (`str`). 293 """If not None, a description of why this field is deprecated (`str`). 296 self.
__doc__ = f
"{doc} (`{dtype.__name__}`" 297 if optional
or default
is not None:
298 self.
__doc__ += f
", default ``{default!r}``" 302 """Default value for this field. 306 """A user-defined function that validates the value of the field. 310 """Flag that determines if the field is required to be set (`bool`). 312 When `False`, `lsst.pex.config.Config.validate` will fail if the 313 field's value is `None`. 317 """The stack frame where this field is defined (`list` of 318 `lsst.pex.config.callStack.StackFrame`). 322 """Rename the field in a `~lsst.pex.config.Config` (for internal use 327 instance : `lsst.pex.config.Config` 328 The config instance that contains this field. 332 This method is invoked by the `lsst.pex.config.Config` object that 333 contains this field and should not be called directly. 335 Renaming is only relevant for `~lsst.pex.config.Field` instances that 336 hold subconfigs. `~lsst.pex.config.Fields` that hold subconfigs should 337 rename each subconfig with the full field name as generated by 338 `lsst.pex.config.config._joinNamePath`. 343 """Validate the field (for internal use only). 347 instance : `lsst.pex.config.Config` 348 The config instance that contains this field. 352 lsst.pex.config.FieldValidationError 353 Raised if verification fails. 357 This method provides basic validation: 359 - Ensures that the value is not `None` if the field is not optional. 360 - Ensures type correctness. 361 - Ensures that the user-provided ``check`` function is valid. 363 Most `~lsst.pex.config.Field` subclasses should call 364 `lsst.pex.config.field.Field.validate` if they re-implement 365 `~lsst.pex.config.field.Field.validate`. 367 value = self.__get__(instance)
368 if not self.optional
and value
is None:
369 raise FieldValidationError(self, instance,
"Required value cannot be None")
372 """Make this field read-only (for internal use only). 376 instance : `lsst.pex.config.Config` 377 The config instance that contains this field. 381 Freezing is only relevant for fields that hold subconfigs. Fields which 382 hold subconfigs should freeze each subconfig. 384 **Subclasses should implement this method.** 388 def _validateValue(self, value):
394 The value being validated. 399 Raised if the value's type is incompatible with the field's 402 Raised if the value is rejected by the ``check`` method. 407 if not isinstance(value, self.dtype):
408 msg =
"Value %s is of incorrect type %s. Expected type %s" % \
409 (value, _typeStr(value), _typeStr(self.dtype))
411 if self.check
is not None and not self.check(value):
412 msg =
"Value %s is not a valid value" %
str(value)
413 raise ValueError(msg)
415 def _collectImports(self, instance, imports):
416 """This function should call the _collectImports method on all config 417 objects the field may own, and union them with the supplied imports 422 instance : instance or subclass of `lsst.pex.config.Config` 423 A config object that has this field defined on it 425 Set of python modules that need imported after persistence 429 def save(self, outfile, instance):
430 """Save this field to a file (for internal use only). 434 outfile : file-like object 435 A writeable field handle. 437 The `Config` instance that contains this field. 441 This method is invoked by the `~lsst.pex.config.Config` object that 442 contains this field and should not be called directly. 444 The output consists of the documentation string 445 (`lsst.pex.config.Field.doc`) formatted as a Python comment. The second 446 line is formatted as an assignment: ``{fullname}={value}``. 448 This output can be executed with Python. 450 value = self.__get__(instance)
451 fullname = _joinNamePath(instance._name, self.name)
454 doc =
"# " +
str(self.doc).replace(
"\n",
"\n# ")
455 if isinstance(value, float)
and (math.isinf(value)
or math.isnan(value)):
457 outfile.write(
u"{}\n{}=float('{!r}')\n\n".
format(doc, fullname, value))
459 outfile.write(
u"{}\n{}={!r}\n\n".
format(doc, fullname, value))
462 """Convert the field value so that it can be set as the value of an 463 item in a `dict` (for internal use only). 468 The `Config` that contains this field. 473 The field's value. See *Notes*. 477 This method invoked by the owning `~lsst.pex.config.Config` object and 478 should not be called directly. 480 Simple values are passed through. Complex data structures must be 481 manipulated. For example, a `~lsst.pex.config.Field` holding a 482 subconfig should, instead of the subconfig object, return a `dict` 483 where the keys are the field names in the subconfig, and the values are 484 the field values in the subconfig. 488 def __get__(self, instance, owner=None, at=None, label="default"):
489 """Define how attribute access should occur on the Config instance 490 This is invoked by the owning config object and should not be called 493 When the field attribute is accessed on a Config class object, it 494 returns the field object itself in order to allow inspection of 497 When the field attribute is access on a config instance, the actual 498 value described by the field (and held by the Config instance) is 501 if instance
is None or not isinstance(instance, Config):
504 return instance._storage[self.name]
506 def __set__(self, instance, value, at=None, label='assignment'):
507 """Set an attribute on the config instance. 511 instance : `lsst.pex.config.Config` 512 The config instance that contains this field. 514 Value to set on this field. 515 at : `list` of `lsst.pex.config.callStack.StackFrame` 516 The call stack (created by 517 `lsst.pex.config.callStack.getCallStack`). 518 label : `str`, optional 519 Event label for the history. 523 This method is invoked by the owning `lsst.pex.config.Config` object 524 and should not be called directly. 526 Derived `~lsst.pex.config.Field` classes may need to override the 527 behavior. When overriding ``__set__``, `~lsst.pex.config.Field` authors 528 should follow the following rules: 530 - Do not allow modification of frozen configs. 531 - Validate the new value **before** modifying the field. Except if the 532 new value is `None`. `None` is special and no attempt should be made 533 to validate it until `lsst.pex.config.Config.validate` is called. 534 - Do not modify the `~lsst.pex.config.Config` instance to contain 536 - If the field is modified, update the history of the 537 `lsst.pex.config.field.Field` to reflect the changes. 539 In order to decrease the need to implement this method in derived 540 `~lsst.pex.config.Field` types, value validation is performed in the 541 `lsst.pex.config.Field._validateValue`. If only the validation step 542 differs in the derived `~lsst.pex.config.Field`, it is simpler to 543 implement `lsst.pex.config.Field._validateValue` than to reimplement 544 ``__set__``. More complicated behavior, however, may require 550 history = instance._history.setdefault(self.name, [])
551 if value
is not None:
552 value = _autocast(value, self.
dtype)
555 except BaseException
as e:
558 instance._storage[self.name] = value
561 history.append((value, at, label))
564 """Delete an attribute from a `lsst.pex.config.Config` instance. 568 instance : `lsst.pex.config.Config` 569 The config instance that contains this field. 570 at : `list` of `lsst.pex.config.callStack.StackFrame` 571 The call stack (created by 572 `lsst.pex.config.callStack.getCallStack`). 573 label : `str`, optional 574 Event label for the history. 578 This is invoked by the owning `~lsst.pex.config.Config` object and 579 should not be called directly. 583 self.
__set__(instance,
None, at=at, label=label)
585 def _compare(self, instance1, instance2, shortcut, rtol, atol, output):
586 """Compare a field (named `Field.name`) in two 587 `~lsst.pex.config.Config` instances for equality. 591 instance1 : `lsst.pex.config.Config` 592 Left-hand side `Config` instance to compare. 593 instance2 : `lsst.pex.config.Config` 594 Right-hand side `Config` instance to compare. 595 shortcut : `bool`, optional 597 rtol : `float`, optional 598 Relative tolerance for floating point comparisons. 599 atol : `float`, optional 600 Absolute tolerance for floating point comparisons. 601 output : callable, optional 602 A callable that takes a string, used (possibly repeatedly) to 607 This method must be overridden by more complex `Field` subclasses. 611 lsst.pex.config.compareScalars 613 v1 = getattr(instance1, self.name)
614 v2 = getattr(instance2, self.name)
616 _joinNamePath(instance1._name, self.name),
617 _joinNamePath(instance2._name, self.name)
623 """Importer (for `sys.meta_path`) that records which modules are being 626 *This class does not do any importing itself.* 630 Use this class as a context manager to ensure it is properly uninstalled 633 >>> with RecordingImporter() as importer: 635 ... import numpy as np 636 ... print("Imported: " + importer.getModules()) 644 sys.meta_path = [self] + sys.meta_path
652 """Uninstall the importer. 657 """Called as part of the ``import`` chain of events. 664 """Get the set of modules that were imported. 668 modules : `set` of `str` 669 Set of imported module names. 675 """Base class for configuration (*config*) objects. 679 A ``Config`` object will usually have several `~lsst.pex.config.Field` 680 instances as class attributes. These are used to define most of the base 683 ``Config`` implements a mapping API that provides many `dict`-like methods, 684 such as `keys`, `values`, `items`, `iteritems`, `iterkeys`, and 685 `itervalues`. ``Config`` instances also support the ``in`` operator to 686 test if a field is in the config. Unlike a `dict`, ``Config`` classes are 687 not subscriptable. Instead, access individual fields as attributes of the 688 configuration instance. 692 Config classes are subclasses of ``Config`` that have 693 `~lsst.pex.config.Field` instances (or instances of 694 `~lsst.pex.config.Field` subclasses) as class attributes: 696 >>> from lsst.pex.config import Config, Field, ListField 697 >>> class DemoConfig(Config): 698 ... intField = Field(doc="An integer field", dtype=int, default=42) 699 ... listField = ListField(doc="List of favorite beverages.", dtype=str, 700 ... default=['coffee', 'green tea', 'water']) 702 >>> config = DemoConfig() 704 Configs support many `dict`-like APIs: 707 ['intField', 'listField'] 708 >>> 'intField' in config 711 Individual fields can be accessed as attributes of the configuration: 715 >>> config.listField.append('earl grey tea') 716 >>> print(config.listField) 717 ['coffee', 'green tea', 'water', 'earl grey tea'] 721 """Iterate over fields. 731 List of `lsst.pex.config.Field` names. 735 lsst.pex.config.Config.iterkeys 745 List of field values. 749 lsst.pex.config.Config.itervalues 754 """Get configurations as ``(field name, field value)`` pairs. 759 List of tuples for each configuration. Tuple items are: 766 lsst.pex.config.Config.iteritems 771 """Iterate over (field name, field value) pairs. 783 lsst.pex.config.Config.items 785 return iter(self._storage.
items())
788 """Iterate over field values. 797 lsst.pex.config.Config.values 799 return iter(self.storage.
values())
802 """Iterate over field names 807 A field's key (attribute name). 811 lsst.pex.config.Config.values 813 return iter(self.storage.
keys())
816 """!Return True if the specified field exists in this config 818 @param[in] name field name to test for 823 """Allocate a new `lsst.pex.config.Config` object. 825 In order to ensure that all Config object are always in a proper state 826 when handed to users or to derived `~lsst.pex.config.Config` classes, 827 some attributes are handled at allocation time rather than at 830 This ensures that even if a derived `~lsst.pex.config.Config` class 831 implements ``__init__``, its author does not need to be concerned about 832 when or even the base ``Config.__init__`` should be called. 834 name = kw.pop(
"__name",
None)
837 kw.pop(
"__label",
"default")
839 instance = object.__new__(cls)
840 instance._frozen =
False 841 instance._name = name
842 instance._storage = {}
843 instance._history = {}
844 instance._imports =
set()
846 for field
in instance._fields.values():
847 instance._history[field.name] = []
848 field.__set__(instance, field.default, at=at + [field.source], label=
"default")
850 instance.setDefaults()
852 instance.update(__at=at, **kw)
856 """Reduction for pickling (function with arguments to reproduce). 858 We need to condense and reconstitute the `~lsst.pex.config.Config`, 859 since it may contain lambdas (as the ``check`` elements) that cannot 863 stream = io.StringIO()
865 return (unreduceConfig, (self.__class__, stream.getvalue().encode()))
868 """Subclass hook for computing defaults. 872 Derived `~lsst.pex.config.Config` classes that must compute defaults 873 rather than using the `~lsst.pex.config.Field` instances's defaults 874 should do so here. To correctly use inherited defaults, 875 implementations of ``setDefaults`` must call their base class's 881 """Update values of fields specified by the keyword arguments. 886 Keywords are configuration field names. Values are configuration 891 The ``__at`` and ``__label`` keyword arguments are special internal 892 keywords. They are used to strip out any internal steps from the 893 history tracebacks of the config. Do not modify these keywords to 894 subvert a `~lsst.pex.config.Config` instance's history. 898 This is a config with three fields: 900 >>> from lsst.pex.config import Config, Field 901 >>> class DemoConfig(Config): 902 ... fieldA = Field(doc='Field A', dtype=int, default=42) 903 ... fieldB = Field(doc='Field B', dtype=bool, default=True) 904 ... fieldC = Field(doc='Field C', dtype=str, default='Hello world') 906 >>> config = DemoConfig() 908 These are the default values of each field: 910 >>> for name, value in config.iteritems(): 911 ... print(f"{name}: {value}") 915 fieldC: 'Hello world' 917 Using this method to update ``fieldA`` and ``fieldC``: 919 >>> config.update(fieldA=13, fieldC='Updated!') 921 Now the values of each field are: 923 >>> for name, value in config.iteritems(): 924 ... print(f"{name}: {value}") 931 label = kw.pop(
"__label",
"update")
933 for name, value
in kw.items():
935 field = self._fields[name]
936 field.__set__(self, value, at=at, label=label)
938 raise KeyError(
"No field of name %s exists in config type %s" % (name, _typeStr(self)))
940 def load(self, filename, root="config"):
941 """Modify this config in place by executing the Python code in a 947 Name of the configuration file. A configuration file is Python 949 root : `str`, optional 950 Name of the variable in file that refers to the config being 953 For example, the value of root is ``"config"`` and the file 958 Then this config's field ``myField`` is set to ``5``. 960 **Deprecated:** For backwards compatibility, older config files 961 that use ``root="root"`` instead of ``root="config"`` will be 962 loaded with a warning printed to `sys.stderr`. This feature will be 963 removed at some point. 967 lsst.pex.config.Config.loadFromStream 968 lsst.pex.config.Config.save 969 lsst.pex.config.Config.saveFromStream 971 with open(filename,
"r") as f: 972 code = compile(f.read(), filename=filename, mode="exec")
976 """Modify this Config in place by executing the Python code in the 981 stream : file-like object, `str`, or compiled string 982 Stream containing configuration override code. 983 root : `str`, optional 984 Name of the variable in file that refers to the config being 987 For example, the value of root is ``"config"`` and the file 992 Then this config's field ``myField`` is set to ``5``. 994 **Deprecated:** For backwards compatibility, older config files 995 that use ``root="root"`` instead of ``root="config"`` will be 996 loaded with a warning printed to `sys.stderr`. This feature will be 997 removed at some point. 998 filename : `str`, optional 999 Name of the configuration file, or `None` if unknown or contained 1000 in the stream. Used for error reporting. 1004 lsst.pex.config.Config.load 1005 lsst.pex.config.Config.save 1006 lsst.pex.config.Config.saveFromStream 1010 local = {root: self}
1011 exec(stream, {}, local)
1012 except NameError
as e:
1013 if root ==
"config" and "root" in e.args[0]:
1014 if filename
is None:
1017 filename = getattr(stream,
"co_filename",
None)
1018 if filename
is None:
1019 filename = getattr(stream,
"name",
"?")
1020 print(f
"Config override file {filename!r}" 1021 " appears to use 'root' instead of 'config'; trying with 'root'", file=sys.stderr)
1022 local = {
"root": self}
1023 exec(stream, {}, local)
1027 self._imports.
update(importer.getModules())
1029 def save(self, filename, root="config"):
1030 """Save a Python script to the named file, which, when loaded, 1031 reproduces this config. 1036 Desination filename of this configuration. 1037 root : `str`, optional 1038 Name to use for the root config variable. The same value must be 1039 used when loading (see `lsst.pex.config.Config.load`). 1043 lsst.pex.config.Config.saveToStream 1044 lsst.pex.config.Config.load 1045 lsst.pex.config.Config.loadFromStream 1047 d = os.path.dirname(filename)
1048 with tempfile.NamedTemporaryFile(mode=
"w", delete=
False, dir=d)
as outfile:
1053 umask = os.umask(0o077)
1055 os.chmod(outfile.name, (~umask & 0o666))
1059 shutil.move(outfile.name, filename)
1062 """Save a configuration file to a stream, which, when loaded, 1063 reproduces this config. 1067 outfile : file-like object 1068 Destination file object write the config into. Accepts strings not 1071 Name to use for the root config variable. The same value must be 1072 used when loading (see `lsst.pex.config.Config.load`). 1076 lsst.pex.config.Config.save 1077 lsst.pex.config.Config.load 1078 lsst.pex.config.Config.loadFromStream 1085 self._imports.remove(self.__module__)
1086 configType =
type(self)
1087 typeString = _typeStr(configType)
1088 outfile.write(
u"import {}\n".
format(configType.__module__))
1089 outfile.write(
u"assert type({})=={}, 'config is of type %s.%s ".
format(root, typeString))
1090 outfile.write(
u"instead of {}' % (type({}).__module__, type({}).__name__)\n".
format(typeString,
1093 for imp
in self._imports:
1094 if imp
in sys.modules
and sys.modules[imp]
is not None:
1095 outfile.write(
u"import {}\n".
format(imp))
1101 """Make this config, and all subconfigs, read-only. 1107 def _save(self, outfile):
1108 """Save this config to an open stream object. 1112 outfile : file-like object 1113 Destination file object write the config into. Accepts strings not 1117 field.save(outfile, self)
1119 def _collectImports(self):
1120 """Adds module containing self to the list of things to import and 1121 then loops over all the fields in the config calling a corresponding 1122 collect method. The field method will call _collectImports on any configs 1123 it may own and return the set of things to import. This returned set 1124 will be merged with the set of imports for this config class. 1126 self._imports.add(self.__module__)
1128 field._collectImports(self, self._imports)
1131 """Make a dictionary of field names and their values. 1136 Dictionary with keys that are `~lsst.pex.config.Field` names. 1137 Values are `~lsst.pex.config.Field` values. 1141 lsst.pex.config.Field.toDict 1145 This method uses the `~lsst.pex.config.Field.toDict` method of 1146 individual fields. Subclasses of `~lsst.pex.config.Field` may need to 1147 implement a ``toDict`` method for *this* method to work. 1151 dict_[name] = field.toDict(self)
1155 """Get all the field names in the config, recursively. 1159 names : `list` of `str` 1166 with io.StringIO()
as strFd:
1168 contents = strFd.getvalue()
1174 for line
in contents.split(
"\n"):
1175 if re.search(
r"^((assert|import)\s+|\s*$|#)", line):
1178 mat = re.search(
r"^(?:config\.)?([^=]+)\s*=\s*.*", line)
1180 keys.append(mat.group(1))
1184 def _rename(self, name):
1185 """Rename this config object in its parent `~lsst.pex.config.Config`. 1190 New name for this config in its parent `~lsst.pex.config.Config`. 1194 This method uses the `~lsst.pex.config.Field.rename` method of 1195 individual `lsst.pex.config.Field` instances. 1196 `lsst.pex.config.Field` subclasses may need to implement a ``rename`` 1197 method for *this* method to work. 1201 lsst.pex.config.Field.rename 1208 """Validate the Config, raising an exception if invalid. 1212 lsst.pex.config.FieldValidationError 1213 Raised if verification fails. 1217 The base class implementation performs type checks on all fields by 1218 calling their `~lsst.pex.config.Field.validate` methods. 1220 Complex single-field validation can be defined by deriving new Field 1221 types. For convenience, some derived `lsst.pex.config.Field`-types 1222 (`~lsst.pex.config.ConfigField` and 1223 `~lsst.pex.config.ConfigChoiceField`) are defined in `lsst.pex.config` 1224 that handle recursing into subconfigs. 1226 Inter-field relationships should only be checked in derived 1227 `~lsst.pex.config.Config` classes after calling this method, and base 1228 validation is complete. 1231 field.validate(self)
1234 """Format a configuration field's history to a human-readable format. 1239 Name of a `~lsst.pex.config.Field` in this config. 1241 Keyword arguments passed to `lsst.pex.config.history.format`. 1246 A string containing the formatted history. 1250 lsst.pex.config.history.format 1253 return pexHist.format(self, name, **kwargs)
1255 history = property(
lambda x: x._history)
1256 """Read-only history. 1260 """Set an attribute (such as a field's value). 1264 Unlike normal Python objects, `~lsst.pex.config.Config` objects are 1265 locked such that no additional attributes nor properties may be added 1266 to them dynamically. 1268 Although this is not the standard Python behavior, it helps to protect 1269 users from accidentally mispelling a field name, or trying to set a 1273 if self.
_fields[attr].deprecated
is not None:
1274 fullname = _joinNamePath(self.
_name, self.
_fields[attr].name)
1275 warnings.warn(f
"Config field {fullname} is deprecated: {self._fields[attr].deprecated}",
1280 self.
_fields[attr].__set__(self, value, at=at, label=label)
1281 elif hasattr(getattr(self.__class__, attr,
None),
'__set__'):
1283 return object.__setattr__(self, attr, value)
1284 elif attr
in self.__dict__
or attr
in (
"_name",
"_history",
"_storage",
"_frozen",
"_imports"):
1286 self.__dict__[attr] = value
1289 raise AttributeError(
"%s has no attribute %s" % (_typeStr(self), attr))
1295 self.
_fields[attr].__delete__(self, at=at, label=label)
1297 object.__delattr__(self, attr)
1302 thisValue = getattr(self, name)
1303 otherValue = getattr(other, name)
1304 if isinstance(thisValue, float)
and math.isnan(thisValue):
1305 if not math.isnan(otherValue):
1307 elif thisValue != otherValue:
1313 return not self.
__eq__(other)
1321 ", ".join(
"%s=%r" % (k, v)
for k, v
in self.
toDict().
items()
if v
is not None)
1324 def compare(self, other, shortcut=True, rtol=1E-8, atol=1E-8, output=None):
1325 """Compare this configuration to another `~lsst.pex.config.Config` for 1330 other : `lsst.pex.config.Config` 1331 Other `~lsst.pex.config.Config` object to compare against this 1333 shortcut : `bool`, optional 1334 If `True`, return as soon as an inequality is found. Default is 1336 rtol : `float`, optional 1337 Relative tolerance for floating point comparisons. 1338 atol : `float`, optional 1339 Absolute tolerance for floating point comparisons. 1340 output : callable, optional 1341 A callable that takes a string, used (possibly repeatedly) to 1342 report inequalities. 1347 `True` when the two `lsst.pex.config.Config` instances are equal. 1348 `False` if there is an inequality. 1352 lsst.pex.config.compareConfigs 1356 Unselected targets of `~lsst.pex.config.RegistryField` fields and 1357 unselected choices of `~lsst.pex.config.ConfigChoiceField` fields 1358 are not considered by this method. 1360 Floating point comparisons are performed by `numpy.allclose`. 1362 name1 = self.
_name if self.
_name is not None else "config" 1363 name2 = other._name
if other._name
is not None else "config" 1366 rtol=rtol, atol=atol, output=output)
1370 """Create a `~lsst.pex.config.Config` from a stream. 1374 cls : `lsst.pex.config.Config`-type 1375 A `lsst.pex.config.Config` type (not an instance) that is instantiated 1376 with configurations in the ``stream``. 1377 stream : file-like object, `str`, or compiled string 1378 Stream containing configuration override code. 1382 config : `lsst.pex.config.Config` 1387 lsst.pex.config.Config.loadFromStream 1390 config.loadFromStream(stream)
def toDict(self, instance)
def formatHistory(self, name, kwargs)
def _collectImports(self)
def load(self, filename, root="config")
def compareConfigs(name, c1, c2, shortcut=True, rtol=1E-8, atol=1E-8, output=None)
def unreduceConfig(cls, stream)
def __init__(self, field, config, msg)
def saveToStream(self, outfile, root="config")
def __delattr__(self, attr, at=None, label="deletion")
daf::base::PropertySet * set
def __get__(self, instance, owner=None, at=None, label="default")
def save(self, filename, root="config")
def getStackFrame(relative=0)
def __contains__(self, name)
Return True if the specified field exists in this config.
def save(self, outfile, instance)
def _validateValue(self, value)
def validate(self, instance)
def format(config, name=None, writeSourceLine=True, prefix="", verbose=False)
def __new__(cls, args, kw)
def __setattr__(self, attr, value, at=None, label="assignment")
def freeze(self, instance)
def compareScalars(name, v1, v2, output, rtol=1E-8, atol=1E-8, dtype=None)
def __init__(self, doc, dtype, default=None, check=None, optional=False, deprecated=None)
def __set__(self, instance, value, at=None, label='assignment')
def _setup(self, doc, dtype, default, check, optional, source, deprecated)
def loadFromStream(self, stream, root="config", filename=None)
def compare(self, other, shortcut=True, rtol=1E-8, atol=1E-8, output=None)
daf::base::PropertyList * list
def getComparisonName(name1, name2)
def rename(self, instance)
def __delete__(self, instance, at=None, label='deletion')
def find_module(self, fullname, path=None)