22 __all__ = (
"Config",
"Field",
"FieldValidationError")
33 from .comparison
import getComparisonName, compareScalars, compareConfigs
34 from .callStack
import getStackFrame, getCallStack
37 def _joinNamePath(prefix=None, name=None, index=None):
38 """Generate nested configuration names. 40 if not prefix
and not name:
41 raise ValueError(
"Invalid name: cannot be None")
45 name = prefix +
"." + name
48 return "%s[%r]" % (name, index)
53 def _autocast(x, dtype):
54 """Cast a value to a type, if appropriate. 61 Data type, such as `float`, `int`, or `str`. 66 If appropriate, the returned value is ``x`` cast to the given type 67 ``dtype``. If the cast cannot be performed the original value of 70 if dtype == float
and isinstance(x, int):
76 """Generate a fully-qualified type name. 81 Fully-qualified type name. 85 This function is used primarily for writing config files to be executed 86 later upon with the 'load' function. 88 if hasattr(x,
'__module__')
and hasattr(x,
'__name__'):
92 if (sys.version_info.major <= 2
and xtype.__module__ ==
'__builtin__')
or xtype.__module__ ==
'builtins':
95 return "%s.%s" % (xtype.__module__, xtype.__name__)
99 """A metaclass for `lsst.pex.config.Config`. 103 ``ConfigMeta`` adds a dictionary containing all `~lsst.pex.config.Field` 104 class attributes as a class attribute called ``_fields``, and adds 105 the name of each field as an instance variable of the field itself (so you 106 don't have to pass the name of the field to the field constructor). 110 type.__init__(cls, name, bases, dict_)
114 def getFields(classtype):
116 bases =
list(classtype.__bases__)
119 fields.update(getFields(b))
121 for k, v
in classtype.__dict__.items():
122 if isinstance(v, Field):
126 fields = getFields(cls)
127 for k, v
in fields.items():
128 setattr(cls, k, copy.deepcopy(v))
131 if isinstance(value, Field):
134 type.__setattr__(cls, name, value)
138 """Raised when a ``~lsst.pex.config.Field`` is not valid in a 139 particular ``~lsst.pex.config.Config``. 143 field : `lsst.pex.config.Field` 144 The field that was not valid. 145 config : `lsst.pex.config.Config` 146 The config containing the invalid field. 148 Text describing why the field was not valid. 153 """Type of the `~lsst.pex.config.Field` that incurred the error. 157 """Name of the `~lsst.pex.config.Field` instance that incurred the 162 lsst.pex.config.Field.name 165 self.
fullname = _joinNamePath(config._name, field.name)
166 """Fully-qualified name of the `~lsst.pex.config.Field` instance 170 self.
history = config.history.setdefault(field.name, [])
171 """Full history of all changes to the `~lsst.pex.config.Field` 176 """File and line number of the `~lsst.pex.config.Field` definition. 180 error =
"%s '%s' failed validation: %s\n"\
181 "For more information see the Field definition at:\n%s"\
182 " and the Config definition at:\n%s" % \
189 """A field in a `~lsst.pex.config.Config` that supports `int`, `float`, 190 `complex`, `bool`, and `str` data types. 195 A description of the field for users. 197 The field's data type. ``Field`` only supports basic data types: 198 `int`, `float`, `complex`, `bool`, and `str`. See 199 `Field.supportedTypes`. 200 default : object, optional 201 The field's default value. 202 check : callable, optional 203 A callable that is called with the field's value. This callable should 204 return `False` if the value is invalid. More complex inter-field 205 validation can be written as part of the 206 `lsst.pex.config.Config.validate` method. 207 optional : `bool`, optional 208 This sets whether the field is considered optional, and therefore 209 doesn't need to be set by the user. When `False`, 210 `lsst.pex.config.Config.validate` fails if the field's value is `None`. 215 Raised when the ``dtype`` parameter is not one of the supported types 216 (see `Field.supportedTypes`). 232 ``Field`` instances (including those of any subclass of ``Field``) are used 233 as class attributes of `~lsst.pex.config.Config` subclasses (see the 234 example, below). ``Field`` attributes work like the `property` attributes 235 of classes that implement custom setters and getters. `Field` attributes 236 belong to the class, but operate on the instance. Formally speaking, 237 `Field` attributes are `descriptors 238 <https://docs.python.org/3/howto/descriptor.html>`_. 240 When you access a `Field` attribute on a `Config` instance, you don't 241 get the `Field` instance itself. Instead, you get the value of that field, 242 which might be a simple type (`int`, `float`, `str`, `bool`) or a custom 243 container type (like a `lsst.pex.config.List`) depending on the field's 244 type. See the example, below. 248 Instances of ``Field`` should be used as class attributes of 249 `lsst.pex.config.Config` subclasses: 251 >>> from lsst.pex.config import Config, Field 252 >>> class Example(Config): 253 ... myInt = Field("An integer field.", int, default=0) 255 >>> print(config.myInt) 258 >>> print(config.myInt) 262 supportedTypes =
set((str, bool, float, int, complex))
263 """Supported data types for field values (`set` of types). 266 def __init__(self, doc, dtype, default=None, check=None, optional=False):
268 raise ValueError(
"Unsupported Field dtype %s" % _typeStr(dtype))
271 self.
_setup(doc=doc, dtype=dtype, default=default, check=check, optional=optional, source=source)
273 def _setup(self, doc, dtype, default, check, optional, source):
274 """Set attributes, usually during initialization. 277 """Data type for the field. 281 """A description of the field (`str`). 284 self.
__doc__ = f
"{doc} (`{dtype.__name__}`" 285 if optional
or default
is not None:
286 self.
__doc__ += f
", default ``{default!r}``" 290 """Default value for this field. 294 """A user-defined function that validates the value of the field. 298 """Flag that determines if the field is required to be set (`bool`). 300 When `False`, `lsst.pex.config.Config.validate` will fail if the 301 field's value is `None`. 305 """The stack frame where this field is defined (`list` of 306 `lsst.pex.config.callStack.StackFrame`). 310 """Rename the field in a `~lsst.pex.config.Config` (for internal use 315 instance : `lsst.pex.config.Config` 316 The config instance that contains this field. 320 This method is invoked by the `lsst.pex.config.Config` object that 321 contains this field and should not be called directly. 323 Renaming is only relevant for `~lsst.pex.config.Field` instances that 324 hold subconfigs. `~lsst.pex.config.Fields` that hold subconfigs should 325 rename each subconfig with the full field name as generated by 326 `lsst.pex.config.config._joinNamePath`. 331 """Validate the field (for internal use only). 335 instance : `lsst.pex.config.Config` 336 The config instance that contains this field. 340 lsst.pex.config.FieldValidationError 341 Raised if verification fails. 345 This method provides basic validation: 347 - Ensures that the value is not `None` if the field is not optional. 348 - Ensures type correctness. 349 - Ensures that the user-provided ``check`` function is valid. 351 Most `~lsst.pex.config.Field` subclasses should call 352 `lsst.pex.config.field.Field.validate` if they re-implement 353 `~lsst.pex.config.field.Field.validate`. 355 value = self.__get__(instance)
356 if not self.optional
and value
is None:
357 raise FieldValidationError(self, instance,
"Required value cannot be None")
360 """Make this field read-only (for internal use only). 364 instance : `lsst.pex.config.Config` 365 The config instance that contains this field. 369 Freezing is only relevant for fields that hold subconfigs. Fields which 370 hold subconfigs should freeze each subconfig. 372 **Subclasses should implement this method.** 376 def _validateValue(self, value):
382 The value being validated. 387 Raised if the value's type is incompatible with the field's 390 Raised if the value is rejected by the ``check`` method. 395 if not isinstance(value, self.dtype):
396 msg =
"Value %s is of incorrect type %s. Expected type %s" % \
397 (value, _typeStr(value), _typeStr(self.dtype))
399 if self.check
is not None and not self.check(value):
400 msg =
"Value %s is not a valid value" %
str(value)
401 raise ValueError(msg)
403 def _collectImports(self, instance, imports):
404 """This function should call the _collectImports method on all config 405 objects the field may own, and union them with the supplied imports 410 instance : instance or subclass of `lsst.pex.config.Config` 411 A config object that has this field defined on it 413 Set of python modules that need imported after persistence 417 def save(self, outfile, instance):
418 """Save this field to a file (for internal use only). 422 outfile : file-like object 423 A writeable field handle. 425 The `Config` instance that contains this field. 429 This method is invoked by the `~lsst.pex.config.Config` object that 430 contains this field and should not be called directly. 432 The output consists of the documentation string 433 (`lsst.pex.config.Field.doc`) formatted as a Python comment. The second 434 line is formatted as an assignment: ``{fullname}={value}``. 436 This output can be executed with Python. 438 value = self.__get__(instance)
439 fullname = _joinNamePath(instance._name, self.name)
442 doc =
"# " +
str(self.doc).replace(
"\n",
"\n# ")
443 if isinstance(value, float)
and (math.isinf(value)
or math.isnan(value)):
445 outfile.write(
u"{}\n{}=float('{!r}')\n\n".
format(doc, fullname, value))
447 outfile.write(
u"{}\n{}={!r}\n\n".
format(doc, fullname, value))
450 """Convert the field value so that it can be set as the value of an 451 item in a `dict` (for internal use only). 456 The `Config` that contains this field. 461 The field's value. See *Notes*. 465 This method invoked by the owning `~lsst.pex.config.Config` object and 466 should not be called directly. 468 Simple values are passed through. Complex data structures must be 469 manipulated. For example, a `~lsst.pex.config.Field` holding a 470 subconfig should, instead of the subconfig object, return a `dict` 471 where the keys are the field names in the subconfig, and the values are 472 the field values in the subconfig. 476 def __get__(self, instance, owner=None, at=None, label="default"):
477 """Define how attribute access should occur on the Config instance 478 This is invoked by the owning config object and should not be called 481 When the field attribute is accessed on a Config class object, it 482 returns the field object itself in order to allow inspection of 485 When the field attribute is access on a config instance, the actual 486 value described by the field (and held by the Config instance) is 489 if instance
is None or not isinstance(instance, Config):
492 return instance._storage[self.name]
494 def __set__(self, instance, value, at=None, label='assignment'):
495 """Set an attribute on the config instance. 499 instance : `lsst.pex.config.Config` 500 The config instance that contains this field. 502 Value to set on this field. 503 at : `list` of `lsst.pex.config.callStack.StackFrame` 504 The call stack (created by 505 `lsst.pex.config.callStack.getCallStack`). 506 label : `str`, optional 507 Event label for the history. 511 This method is invoked by the owning `lsst.pex.config.Config` object 512 and should not be called directly. 514 Derived `~lsst.pex.config.Field` classes may need to override the 515 behavior. When overriding ``__set__``, `~lsst.pex.config.Field` authors 516 should follow the following rules: 518 - Do not allow modification of frozen configs. 519 - Validate the new value **before** modifying the field. Except if the 520 new value is `None`. `None` is special and no attempt should be made 521 to validate it until `lsst.pex.config.Config.validate` is called. 522 - Do not modify the `~lsst.pex.config.Config` instance to contain 524 - If the field is modified, update the history of the 525 `lsst.pex.config.field.Field` to reflect the changes. 527 In order to decrease the need to implement this method in derived 528 `~lsst.pex.config.Field` types, value validation is performed in the 529 `lsst.pex.config.Field._validateValue`. If only the validation step 530 differs in the derived `~lsst.pex.config.Field`, it is simpler to 531 implement `lsst.pex.config.Field._validateValue` than to reimplement 532 ``__set__``. More complicated behavior, however, may require 538 history = instance._history.setdefault(self.name, [])
539 if value
is not None:
540 value = _autocast(value, self.
dtype)
543 except BaseException
as e:
546 instance._storage[self.name] = value
549 history.append((value, at, label))
552 """Delete an attribute from a `lsst.pex.config.Config` instance. 556 instance : `lsst.pex.config.Config` 557 The config instance that contains this field. 558 at : `list` of `lsst.pex.config.callStack.StackFrame` 559 The call stack (created by 560 `lsst.pex.config.callStack.getCallStack`). 561 label : `str`, optional 562 Event label for the history. 566 This is invoked by the owning `~lsst.pex.config.Config` object and 567 should not be called directly. 571 self.
__set__(instance,
None, at=at, label=label)
573 def _compare(self, instance1, instance2, shortcut, rtol, atol, output):
574 """Compare a field (named `Field.name`) in two 575 `~lsst.pex.config.Config` instances for equality. 579 instance1 : `lsst.pex.config.Config` 580 Left-hand side `Config` instance to compare. 581 instance2 : `lsst.pex.config.Config` 582 Right-hand side `Config` instance to compare. 583 shortcut : `bool`, optional 585 rtol : `float`, optional 586 Relative tolerance for floating point comparisons. 587 atol : `float`, optional 588 Absolute tolerance for floating point comparisons. 589 output : callable, optional 590 A callable that takes a string, used (possibly repeatedly) to 595 This method must be overridden by more complex `Field` subclasses. 599 lsst.pex.config.compareScalars 601 v1 = getattr(instance1, self.name)
602 v2 = getattr(instance2, self.name)
604 _joinNamePath(instance1._name, self.name),
605 _joinNamePath(instance2._name, self.name)
611 """Importer (for `sys.meta_path`) that records which modules are being 614 *This class does not do any importing itself.* 618 Use this class as a context manager to ensure it is properly uninstalled 621 >>> with RecordingImporter() as importer: 623 ... import numpy as np 624 ... print("Imported: " + importer.getModules()) 632 sys.meta_path = [self] + sys.meta_path
640 """Uninstall the importer. 645 """Called as part of the ``import`` chain of events. 652 """Get the set of modules that were imported. 656 modules : `set` of `str` 657 Set of imported module names. 663 """Base class for configuration (*config*) objects. 667 A ``Config`` object will usually have several `~lsst.pex.config.Field` 668 instances as class attributes. These are used to define most of the base 671 ``Config`` implements a mapping API that provides many `dict`-like methods, 672 such as `keys`, `values`, `items`, `iteritems`, `iterkeys`, and 673 `itervalues`. ``Config`` instances also support the ``in`` operator to 674 test if a field is in the config. Unlike a `dict`, ``Config`` classes are 675 not subscriptable. Instead, access individual fields as attributes of the 676 configuration instance. 680 Config classes are subclasses of ``Config`` that have 681 `~lsst.pex.config.Field` instances (or instances of 682 `~lsst.pex.config.Field` subclasses) as class attributes: 684 >>> from lsst.pex.config import Config, Field, ListField 685 >>> class DemoConfig(Config): 686 ... intField = Field(doc="An integer field", dtype=int, default=42) 687 ... listField = ListField(doc="List of favorite beverages.", dtype=str, 688 ... default=['coffee', 'green tea', 'water']) 690 >>> config = DemoConfig() 692 Configs support many `dict`-like APIs: 695 ['intField', 'listField'] 696 >>> 'intField' in config 699 Individual fields can be accessed as attributes of the configuration: 703 >>> config.listField.append('earl grey tea') 704 >>> print(config.listField) 705 ['coffee', 'green tea', 'water', 'earl grey tea'] 709 """Iterate over fields. 719 List of `lsst.pex.config.Field` names. 723 lsst.pex.config.Config.iterkeys 733 List of field values. 737 lsst.pex.config.Config.itervalues 742 """Get configurations as ``(field name, field value)`` pairs. 747 List of tuples for each configuration. Tuple items are: 754 lsst.pex.config.Config.iteritems 759 """Iterate over (field name, field value) pairs. 771 lsst.pex.config.Config.items 773 return iter(self._storage.
items())
776 """Iterate over field values. 785 lsst.pex.config.Config.values 787 return iter(self.storage.
values())
790 """Iterate over field names 795 A field's key (attribute name). 799 lsst.pex.config.Config.values 801 return iter(self.storage.
keys())
804 """!Return True if the specified field exists in this config 806 @param[in] name field name to test for 811 """Allocate a new `lsst.pex.config.Config` object. 813 In order to ensure that all Config object are always in a proper state 814 when handed to users or to derived `~lsst.pex.config.Config` classes, 815 some attributes are handled at allocation time rather than at 818 This ensures that even if a derived `~lsst.pex.config.Config` class 819 implements ``__init__``, its author does not need to be concerned about 820 when or even the base ``Config.__init__`` should be called. 822 name = kw.pop(
"__name",
None)
825 kw.pop(
"__label",
"default")
827 instance = object.__new__(cls)
828 instance._frozen =
False 829 instance._name = name
830 instance._storage = {}
831 instance._history = {}
832 instance._imports =
set()
834 for field
in instance._fields.values():
835 instance._history[field.name] = []
836 field.__set__(instance, field.default, at=at + [field.source], label=
"default")
838 instance.setDefaults()
840 instance.update(__at=at, **kw)
844 """Reduction for pickling (function with arguments to reproduce). 846 We need to condense and reconstitute the `~lsst.pex.config.Config`, 847 since it may contain lambdas (as the ``check`` elements) that cannot 851 stream = io.StringIO()
853 return (unreduceConfig, (self.__class__, stream.getvalue().encode()))
856 """Subclass hook for computing defaults. 860 Derived `~lsst.pex.config.Config` classes that must compute defaults 861 rather than using the `~lsst.pex.config.Field` instances's defaults 862 should do so here. To correctly use inherited defaults, 863 implementations of ``setDefaults`` must call their base class's 869 """Update values of fields specified by the keyword arguments. 874 Keywords are configuration field names. Values are configuration 879 The ``__at`` and ``__label`` keyword arguments are special internal 880 keywords. They are used to strip out any internal steps from the 881 history tracebacks of the config. Do not modify these keywords to 882 subvert a `~lsst.pex.config.Config` instance's history. 886 This is a config with three fields: 888 >>> from lsst.pex.config import Config, Field 889 >>> class DemoConfig(Config): 890 ... fieldA = Field(doc='Field A', dtype=int, default=42) 891 ... fieldB = Field(doc='Field B', dtype=bool, default=True) 892 ... fieldC = Field(doc='Field C', dtype=str, default='Hello world') 894 >>> config = DemoConfig() 896 These are the default values of each field: 898 >>> for name, value in config.iteritems(): 899 ... print(f"{name}: {value}") 903 fieldC: 'Hello world' 905 Using this method to update ``fieldA`` and ``fieldC``: 907 >>> config.update(fieldA=13, fieldC='Updated!') 909 Now the values of each field are: 911 >>> for name, value in config.iteritems(): 912 ... print(f"{name}: {value}") 919 label = kw.pop(
"__label",
"update")
921 for name, value
in kw.items():
923 field = self._fields[name]
924 field.__set__(self, value, at=at, label=label)
926 raise KeyError(
"No field of name %s exists in config type %s" % (name, _typeStr(self)))
928 def load(self, filename, root="config"):
929 """Modify this config in place by executing the Python code in a 935 Name of the configuration file. A configuration file is Python 937 root : `str`, optional 938 Name of the variable in file that refers to the config being 941 For example, the value of root is ``"config"`` and the file 946 Then this config's field ``myField`` is set to ``5``. 948 **Deprecated:** For backwards compatibility, older config files 949 that use ``root="root"`` instead of ``root="config"`` will be 950 loaded with a warning printed to `sys.stderr`. This feature will be 951 removed at some point. 955 lsst.pex.config.Config.loadFromStream 956 lsst.pex.config.Config.save 957 lsst.pex.config.Config.saveFromStream 959 with open(filename,
"r") as f: 960 code = compile(f.read(), filename=filename, mode="exec")
964 """Modify this Config in place by executing the Python code in the 969 stream : file-like object, `str`, or compiled string 970 Stream containing configuration override code. 971 root : `str`, optional 972 Name of the variable in file that refers to the config being 975 For example, the value of root is ``"config"`` and the file 980 Then this config's field ``myField`` is set to ``5``. 982 **Deprecated:** For backwards compatibility, older config files 983 that use ``root="root"`` instead of ``root="config"`` will be 984 loaded with a warning printed to `sys.stderr`. This feature will be 985 removed at some point. 986 filename : `str`, optional 987 Name of the configuration file, or `None` if unknown or contained 988 in the stream. Used for error reporting. 992 lsst.pex.config.Config.load 993 lsst.pex.config.Config.save 994 lsst.pex.config.Config.saveFromStream 999 exec(stream, {}, local)
1000 except NameError
as e:
1001 if root ==
"config" and "root" in e.args[0]:
1002 if filename
is None:
1005 filename = getattr(stream,
"co_filename",
None)
1006 if filename
is None:
1007 filename = getattr(stream,
"name",
"?")
1008 print(f
"Config override file {filename!r}" 1009 " appears to use 'root' instead of 'config'; trying with 'root'", file=sys.stderr)
1010 local = {
"root": self}
1011 exec(stream, {}, local)
1015 self._imports.
update(importer.getModules())
1017 def save(self, filename, root="config"):
1018 """Save a Python script to the named file, which, when loaded, 1019 reproduces this config. 1024 Desination filename of this configuration. 1025 root : `str`, optional 1026 Name to use for the root config variable. The same value must be 1027 used when loading (see `lsst.pex.config.Config.load`). 1031 lsst.pex.config.Config.saveToStream 1032 lsst.pex.config.Config.load 1033 lsst.pex.config.Config.loadFromStream 1035 d = os.path.dirname(filename)
1036 with tempfile.NamedTemporaryFile(mode=
"w", delete=
False, dir=d)
as outfile:
1041 umask = os.umask(0o077)
1043 os.chmod(outfile.name, (~umask & 0o666))
1047 shutil.move(outfile.name, filename)
1050 """Save a configuration file to a stream, which, when loaded, 1051 reproduces this config. 1055 outfile : file-like object 1056 Destination file object write the config into. Accepts strings not 1059 Name to use for the root config variable. The same value must be 1060 used when loading (see `lsst.pex.config.Config.load`). 1064 lsst.pex.config.Config.save 1065 lsst.pex.config.Config.load 1066 lsst.pex.config.Config.loadFromStream 1073 self._imports.remove(self.__module__)
1074 configType =
type(self)
1075 typeString = _typeStr(configType)
1076 outfile.write(
u"import {}\n".
format(configType.__module__))
1077 outfile.write(
u"assert type({})=={}, 'config is of type %s.%s ".
format(root, typeString))
1078 outfile.write(
u"instead of {}' % (type({}).__module__, type({}).__name__)\n".
format(typeString,
1081 for imp
in self._imports:
1082 if imp
in sys.modules
and sys.modules[imp]
is not None:
1083 outfile.write(
u"import {}\n".
format(imp))
1089 """Make this config, and all subconfigs, read-only. 1095 def _save(self, outfile):
1096 """Save this config to an open stream object. 1100 outfile : file-like object 1101 Destination file object write the config into. Accepts strings not 1105 field.save(outfile, self)
1107 def _collectImports(self):
1108 """Adds module containing self to the list of things to import and 1109 then loops over all the fields in the config calling a corresponding 1110 collect method. The field method will call _collectImports on any configs 1111 it may own and return the set of things to import. This returned set 1112 will be merged with the set of imports for this config class. 1114 self._imports.add(self.__module__)
1116 field._collectImports(self, self._imports)
1119 """Make a dictionary of field names and their values. 1124 Dictionary with keys that are `~lsst.pex.config.Field` names. 1125 Values are `~lsst.pex.config.Field` values. 1129 lsst.pex.config.Field.toDict 1133 This method uses the `~lsst.pex.config.Field.toDict` method of 1134 individual fields. Subclasses of `~lsst.pex.config.Field` may need to 1135 implement a ``toDict`` method for *this* method to work. 1139 dict_[name] = field.toDict(self)
1143 """Get all the field names in the config, recursively. 1147 names : `list` of `str` 1154 with io.StringIO()
as strFd:
1156 contents = strFd.getvalue()
1162 for line
in contents.split(
"\n"):
1163 if re.search(
r"^((assert|import)\s+|\s*$|#)", line):
1166 mat = re.search(
r"^(?:config\.)?([^=]+)\s*=\s*.*", line)
1168 keys.append(mat.group(1))
1172 def _rename(self, name):
1173 """Rename this config object in its parent `~lsst.pex.config.Config`. 1178 New name for this config in its parent `~lsst.pex.config.Config`. 1182 This method uses the `~lsst.pex.config.Field.rename` method of 1183 individual `lsst.pex.config.Field` instances. 1184 `lsst.pex.config.Field` subclasses may need to implement a ``rename`` 1185 method for *this* method to work. 1189 lsst.pex.config.Field.rename 1196 """Validate the Config, raising an exception if invalid. 1200 lsst.pex.config.FieldValidationError 1201 Raised if verification fails. 1205 The base class implementation performs type checks on all fields by 1206 calling their `~lsst.pex.config.Field.validate` methods. 1208 Complex single-field validation can be defined by deriving new Field 1209 types. For convenience, some derived `lsst.pex.config.Field`-types 1210 (`~lsst.pex.config.ConfigField` and 1211 `~lsst.pex.config.ConfigChoiceField`) are defined in `lsst.pex.config` 1212 that handle recursing into subconfigs. 1214 Inter-field relationships should only be checked in derived 1215 `~lsst.pex.config.Config` classes after calling this method, and base 1216 validation is complete. 1219 field.validate(self)
1222 """Format a configuration field's history to a human-readable format. 1227 Name of a `~lsst.pex.config.Field` in this config. 1229 Keyword arguments passed to `lsst.pex.config.history.format`. 1234 A string containing the formatted history. 1238 lsst.pex.config.history.format 1241 return pexHist.format(self, name, **kwargs)
1243 history = property(
lambda x: x._history)
1244 """Read-only history. 1248 """Set an attribute (such as a field's value). 1252 Unlike normal Python objects, `~lsst.pex.config.Config` objects are 1253 locked such that no additional attributes nor properties may be added 1254 to them dynamically. 1256 Although this is not the standard Python behavior, it helps to protect 1257 users from accidentally mispelling a field name, or trying to set a 1264 self.
_fields[attr].__set__(self, value, at=at, label=label)
1265 elif hasattr(getattr(self.__class__, attr,
None),
'__set__'):
1267 return object.__setattr__(self, attr, value)
1268 elif attr
in self.__dict__
or attr
in (
"_name",
"_history",
"_storage",
"_frozen",
"_imports"):
1270 self.__dict__[attr] = value
1273 raise AttributeError(
"%s has no attribute %s" % (_typeStr(self), attr))
1279 self.
_fields[attr].__delete__(self, at=at, label=label)
1281 object.__delattr__(self, attr)
1286 thisValue = getattr(self, name)
1287 otherValue = getattr(other, name)
1288 if isinstance(thisValue, float)
and math.isnan(thisValue):
1289 if not math.isnan(otherValue):
1291 elif thisValue != otherValue:
1297 return not self.
__eq__(other)
1305 ", ".join(
"%s=%r" % (k, v)
for k, v
in self.
toDict().
items()
if v
is not None)
1308 def compare(self, other, shortcut=True, rtol=1E-8, atol=1E-8, output=None):
1309 """Compare this configuration to another `~lsst.pex.config.Config` for 1314 other : `lsst.pex.config.Config` 1315 Other `~lsst.pex.config.Config` object to compare against this 1317 shortcut : `bool`, optional 1318 If `True`, return as soon as an inequality is found. Default is 1320 rtol : `float`, optional 1321 Relative tolerance for floating point comparisons. 1322 atol : `float`, optional 1323 Absolute tolerance for floating point comparisons. 1324 output : callable, optional 1325 A callable that takes a string, used (possibly repeatedly) to 1326 report inequalities. 1331 `True` when the two `lsst.pex.config.Config` instances are equal. 1332 `False` if there is an inequality. 1336 lsst.pex.config.compareConfigs 1340 Unselected targets of `~lsst.pex.config.RegistryField` fields and 1341 unselected choices of `~lsst.pex.config.ConfigChoiceField` fields 1342 are not considered by this method. 1344 Floating point comparisons are performed by `numpy.allclose`. 1346 name1 = self.
_name if self.
_name is not None else "config" 1347 name2 = other._name
if other._name
is not None else "config" 1350 rtol=rtol, atol=atol, output=output)
1354 """Create a `~lsst.pex.config.Config` from a stream. 1358 cls : `lsst.pex.config.Config`-type 1359 A `lsst.pex.config.Config` type (not an instance) that is instantiated 1360 with configurations in the ``stream``. 1361 stream : file-like object, `str`, or compiled string 1362 Stream containing configuration override code. 1366 config : `lsst.pex.config.Config` 1371 lsst.pex.config.Config.loadFromStream 1374 config.loadFromStream(stream)
def toDict(self, instance)
def formatHistory(self, name, kwargs)
def _collectImports(self)
def load(self, filename, root="config")
def __init__(self, doc, dtype, default=None, check=None, optional=False)
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 _setup(self, doc, dtype, default, check, optional, source)
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 __set__(self, instance, value, at=None, label='assignment')
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)