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 """An exception that holds additional information, as attributes, 139 for debugging `lsst.pex.config.Config` errors. 144 """Type of the `~lsst.pex.config.Field` that incurred the error. 148 """Name of the `~lsst.pex.config.Field` instance that incurred the 153 lsst.pex.config.Field.name 156 self.
fullname = _joinNamePath(config._name, field.name)
157 """Fully-qualified name of the `~lsst.pex.config.Field` instance 161 self.
history = config.history.setdefault(field.name, [])
162 """Full history of all changes to the `~lsst.pex.config.Field` 167 """File and line number of the `~lsst.pex.config.Field` definition. 171 error =
"%s '%s' failed validation: %s\n"\
172 "For more information read the Field definition at:\n%s"\
173 "And the Config definition at:\n%s" % \
176 ValueError.__init__(self, error)
180 """A field in a `~lsst.pex.config.Config` that supports `int`, `float`, 181 `complex`, `bool`, and `str` data types. 186 A description of the field for users. 188 The field's data type. ``Field`` only supports basic data types: 189 `int`, `float`, `complex`, `bool`, and `str`. See 190 `Field.supportedTypes`. 191 default : object, optional 192 The field's default value. 193 check : callable, optional 194 A callable that is called with the field's value. This callable should 195 return `False` if the value is invalid. More complex inter-field 196 validation can be written as part of the 197 `lsst.pex.config.Config.validate` method. 198 optional : `bool`, optional 199 This sets whether the field is considered optional, and therefore 200 doesn't need to be set by the user. When `False`, 201 `lsst.pex.config.Config.validate` fails if the field's value is `None`. 206 Raised when the ``dtype`` parameter is not one of the supported types 207 (see `Field.supportedTypes`). 223 ``Field`` instances (including those of any subclass of ``Field``) are used 224 as class attributes of `~lsst.pex.config.Config` subclasses (see the 225 example, below). ``Field`` attributes work like the `property` attributes 226 of classes that implement custom setters and getters. `Field` attributes 227 belong to the class, but operate on the instance. Formally speaking, 228 `Field` attributes are `descriptors 229 <https://docs.python.org/3/howto/descriptor.html>`_. 231 When you access a `Field` attribute on a `Config` instance, you don't 232 get the `Field` instance itself. Instead, you get the value of that field, 233 which might be a simple type (`int`, `float`, `str`, `bool`) or a custom 234 container type (like a `lsst.pex.config.List`) depending on the field's 235 type. See the example, below. 239 Instances of ``Field`` should be used as class attributes of 240 `lsst.pex.config.Config` subclasses: 242 >>> from lsst.pex.config import Config, Field 243 >>> class Example(Config): 244 ... myInt = Field("An integer field.", int, default=0) 246 >>> print(config.myInt) 249 >>> print(config.myInt) 253 supportedTypes =
set((str, bool, float, int, complex))
254 """Supported data types for field values (`set` of types). 257 def __init__(self, doc, dtype, default=None, check=None, optional=False):
259 raise ValueError(
"Unsupported Field dtype %s" % _typeStr(dtype))
262 self.
_setup(doc=doc, dtype=dtype, default=default, check=check, optional=optional, source=source)
264 def _setup(self, doc, dtype, default, check, optional, source):
265 """Set attributes, usually during initialization. 268 """Data type for the field. 272 """A description of the field (`str`). 275 self.
__doc__ = f
"{doc} (`{dtype.__name__}`" 276 if optional
or default
is not None:
277 self.
__doc__ += f
", default ``{default!r}``" 281 """Default value for this field. 285 """A user-defined function that validates the value of the field. 289 """Flag that determines if the field is required to be set (`bool`). 291 When `False`, `lsst.pex.config.Config.validate` will fail if the 292 field's value is `None`. 296 """The stack frame where this field is defined (`list` of 297 `lsst.pex.config.callStack.StackFrame`). 301 """Rename the field in a `~lsst.pex.config.Config` (for internal use 306 instance : `lsst.pex.config.Config` 307 The config instance that contains this field. 311 This method is invoked by the `lsst.pex.config.Config` object that 312 contains this field and should not be called directly. 314 Renaming is only relevant for `~lsst.pex.config.Field` instances that 315 hold subconfigs. `~lsst.pex.config.Fields` that hold subconfigs should 316 rename each subconfig with the full field name as generated by 317 `lsst.pex.config.config._joinNamePath`. 322 """Validate the field (for internal use only). 326 instance : `lsst.pex.config.Config` 327 The config instance that contains this field. 331 lsst.pex.config.FieldValidationError 332 Raised if verification fails. 336 This method provides basic validation: 338 - Ensures that the value is not `None` if the field is not optional. 339 - Ensures type correctness. 340 - Ensures that the user-provided ``check`` function is valid. 342 Most `~lsst.pex.config.Field` subclasses should call 343 `lsst.pex.config.field.Field.validate` if they re-implement 344 `~lsst.pex.config.field.Field.validate`. 346 value = self.__get__(instance)
347 if not self.optional
and value
is None:
348 raise FieldValidationError(self, instance,
"Required value cannot be None")
351 """Make this field read-only (for internal use only). 355 instance : `lsst.pex.config.Config` 356 The config instance that contains this field. 360 Freezing is only relevant for fields that hold subconfigs. Fields which 361 hold subconfigs should freeze each subconfig. 363 **Subclasses should implement this method.** 367 def _validateValue(self, value):
373 The value being validated. 378 Raised if the value's type is incompatible with the field's 381 Raised if the value is rejected by the ``check`` method. 386 if not isinstance(value, self.dtype):
387 msg =
"Value %s is of incorrect type %s. Expected type %s" % \
388 (value, _typeStr(value), _typeStr(self.dtype))
390 if self.check
is not None and not self.check(value):
391 msg =
"Value %s is not a valid value" %
str(value)
392 raise ValueError(msg)
394 def _collectImports(self, instance, imports):
395 """This function should call the _collectImports method on all config 396 objects the field may own, and union them with the supplied imports 401 instance : instance or subclass of `lsst.pex.config.Config` 402 A config object that has this field defined on it 404 Set of python modules that need imported after persistence 408 def save(self, outfile, instance):
409 """Save this field to a file (for internal use only). 413 outfile : file-like object 414 A writeable field handle. 416 The `Config` instance that contains this field. 420 This method is invoked by the `~lsst.pex.config.Config` object that 421 contains this field and should not be called directly. 423 The output consists of the documentation string 424 (`lsst.pex.config.Field.doc`) formatted as a Python comment. The second 425 line is formatted as an assignment: ``{fullname}={value}``. 427 This output can be executed with Python. 429 value = self.__get__(instance)
430 fullname = _joinNamePath(instance._name, self.name)
433 doc =
"# " +
str(self.doc).replace(
"\n",
"\n# ")
434 if isinstance(value, float)
and (math.isinf(value)
or math.isnan(value)):
436 outfile.write(
u"{}\n{}=float('{!r}')\n\n".
format(doc, fullname, value))
438 outfile.write(
u"{}\n{}={!r}\n\n".
format(doc, fullname, value))
441 """Convert the field value so that it can be set as the value of an 442 item in a `dict` (for internal use only). 447 The `Config` that contains this field. 452 The field's value. See *Notes*. 456 This method invoked by the owning `~lsst.pex.config.Config` object and 457 should not be called directly. 459 Simple values are passed through. Complex data structures must be 460 manipulated. For example, a `~lsst.pex.config.Field` holding a 461 subconfig should, instead of the subconfig object, return a `dict` 462 where the keys are the field names in the subconfig, and the values are 463 the field values in the subconfig. 467 def __get__(self, instance, owner=None, at=None, label="default"):
468 """Define how attribute access should occur on the Config instance 469 This is invoked by the owning config object and should not be called 472 When the field attribute is accessed on a Config class object, it 473 returns the field object itself in order to allow inspection of 476 When the field attribute is access on a config instance, the actual 477 value described by the field (and held by the Config instance) is 480 if instance
is None or not isinstance(instance, Config):
483 return instance._storage[self.name]
485 def __set__(self, instance, value, at=None, label='assignment'):
486 """Set an attribute on the config instance. 490 instance : `lsst.pex.config.Config` 491 The config instance that contains this field. 493 Value to set on this field. 494 at : `list` of `lsst.pex.config.callStack.StackFrame` 495 The call stack (created by 496 `lsst.pex.config.callStack.getCallStack`). 497 label : `str`, optional 498 Event label for the history. 502 This method is invoked by the owning `lsst.pex.config.Config` object 503 and should not be called directly. 505 Derived `~lsst.pex.config.Field` classes may need to override the 506 behavior. When overriding ``__set__``, `~lsst.pex.config.Field` authors 507 should follow the following rules: 509 - Do not allow modification of frozen configs. 510 - Validate the new value **before** modifying the field. Except if the 511 new value is `None`. `None` is special and no attempt should be made 512 to validate it until `lsst.pex.config.Config.validate` is called. 513 - Do not modify the `~lsst.pex.config.Config` instance to contain 515 - If the field is modified, update the history of the 516 `lsst.pex.config.field.Field` to reflect the changes. 518 In order to decrease the need to implement this method in derived 519 `~lsst.pex.config.Field` types, value validation is performed in the 520 `lsst.pex.config.Field._validateValue`. If only the validation step 521 differs in the derived `~lsst.pex.config.Field`, it is simpler to 522 implement `lsst.pex.config.Field._validateValue` than to reimplement 523 ``__set__``. More complicated behavior, however, may require 529 history = instance._history.setdefault(self.name, [])
530 if value
is not None:
531 value = _autocast(value, self.
dtype)
534 except BaseException
as e:
537 instance._storage[self.name] = value
540 history.append((value, at, label))
543 """Delete an attribute from a `lsst.pex.config.Config` instance. 547 instance : `lsst.pex.config.Config` 548 The config instance that contains this field. 549 at : `list` of `lsst.pex.config.callStack.StackFrame` 550 The call stack (created by 551 `lsst.pex.config.callStack.getCallStack`). 552 label : `str`, optional 553 Event label for the history. 557 This is invoked by the owning `~lsst.pex.config.Config` object and 558 should not be called directly. 562 self.
__set__(instance,
None, at=at, label=label)
564 def _compare(self, instance1, instance2, shortcut, rtol, atol, output):
565 """Compare a field (named `Field.name`) in two 566 `~lsst.pex.config.Config` instances for equality. 570 instance1 : `lsst.pex.config.Config` 571 Left-hand side `Config` instance to compare. 572 instance2 : `lsst.pex.config.Config` 573 Right-hand side `Config` instance to compare. 574 shortcut : `bool`, optional 576 rtol : `float`, optional 577 Relative tolerance for floating point comparisons. 578 atol : `float`, optional 579 Absolute tolerance for floating point comparisons. 580 output : callable, optional 581 A callable that takes a string, used (possibly repeatedly) to 586 This method must be overridden by more complex `Field` subclasses. 590 lsst.pex.config.compareScalars 592 v1 = getattr(instance1, self.name)
593 v2 = getattr(instance2, self.name)
595 _joinNamePath(instance1._name, self.name),
596 _joinNamePath(instance2._name, self.name)
602 """Importer (for `sys.meta_path`) that records which modules are being 605 *This class does not do any importing itself.* 609 Use this class as a context manager to ensure it is properly uninstalled 612 >>> with RecordingImporter() as importer: 614 ... import numpy as np 615 ... print("Imported: " + importer.getModules()) 623 sys.meta_path = [self] + sys.meta_path
631 """Uninstall the importer. 636 """Called as part of the ``import`` chain of events. 643 """Get the set of modules that were imported. 647 modules : `set` of `str` 648 Set of imported module names. 654 """Base class for configuration (*config*) objects. 658 A ``Config`` object will usually have several `~lsst.pex.config.Field` 659 instances as class attributes. These are used to define most of the base 662 ``Config`` implements a mapping API that provides many `dict`-like methods, 663 such as `keys`, `values`, `items`, `iteritems`, `iterkeys`, and 664 `itervalues`. ``Config`` instances also support the ``in`` operator to 665 test if a field is in the config. Unlike a `dict`, ``Config`` classes are 666 not subscriptable. Instead, access individual fields as attributes of the 667 configuration instance. 671 Config classes are subclasses of ``Config`` that have 672 `~lsst.pex.config.Field` instances (or instances of 673 `~lsst.pex.config.Field` subclasses) as class attributes: 675 >>> from lsst.pex.config import Config, Field, ListField 676 >>> class DemoConfig(Config): 677 ... intField = Field(doc="An integer field", dtype=int, default=42) 678 ... listField = ListField(doc="List of favorite beverages.", dtype=str, 679 ... default=['coffee', 'green tea', 'water']) 681 >>> config = DemoConfig() 683 Configs support many `dict`-like APIs: 686 ['intField', 'listField'] 687 >>> 'intField' in config 690 Individual fields can be accessed as attributes of the configuration: 694 >>> config.listField.append('earl grey tea') 695 >>> print(config.listField) 696 ['coffee', 'green tea', 'water', 'earl grey tea'] 700 """Iterate over fields. 710 List of `lsst.pex.config.Field` names. 714 lsst.pex.config.Config.iterkeys 724 List of field values. 728 lsst.pex.config.Config.itervalues 733 """Get configurations as ``(field name, field value)`` pairs. 738 List of tuples for each configuration. Tuple items are: 745 lsst.pex.config.Config.iteritems 750 """Iterate over (field name, field value) pairs. 762 lsst.pex.config.Config.items 764 return iter(self._storage.
items())
767 """Iterate over field values. 776 lsst.pex.config.Config.values 778 return iter(self.storage.
values())
781 """Iterate over field names 786 A field's key (attribute name). 790 lsst.pex.config.Config.values 792 return iter(self.storage.
keys())
795 """!Return True if the specified field exists in this config 797 @param[in] name field name to test for 802 """Allocate a new `lsst.pex.config.Config` object. 804 In order to ensure that all Config object are always in a proper state 805 when handed to users or to derived `~lsst.pex.config.Config` classes, 806 some attributes are handled at allocation time rather than at 809 This ensures that even if a derived `~lsst.pex.config.Config` class 810 implements ``__init__``, its author does not need to be concerned about 811 when or even the base ``Config.__init__`` should be called. 813 name = kw.pop(
"__name",
None)
816 kw.pop(
"__label",
"default")
818 instance = object.__new__(cls)
819 instance._frozen =
False 820 instance._name = name
821 instance._storage = {}
822 instance._history = {}
823 instance._imports =
set()
825 for field
in instance._fields.values():
826 instance._history[field.name] = []
827 field.__set__(instance, field.default, at=at + [field.source], label=
"default")
829 instance.setDefaults()
831 instance.update(__at=at, **kw)
835 """Reduction for pickling (function with arguments to reproduce). 837 We need to condense and reconstitute the `~lsst.pex.config.Config`, 838 since it may contain lambdas (as the ``check`` elements) that cannot 842 stream = io.StringIO()
844 return (unreduceConfig, (self.__class__, stream.getvalue().encode()))
847 """Subclass hook for computing defaults. 851 Derived `~lsst.pex.config.Config` classes that must compute defaults 852 rather than using the `~lsst.pex.config.Field` instances's defaults 853 should do so here. To correctly use inherited defaults, 854 implementations of ``setDefaults`` must call their base class's 860 """Update values of fields specified by the keyword arguments. 865 Keywords are configuration field names. Values are configuration 870 The ``__at`` and ``__label`` keyword arguments are special internal 871 keywords. They are used to strip out any internal steps from the 872 history tracebacks of the config. Do not modify these keywords to 873 subvert a `~lsst.pex.config.Config` instance's history. 877 This is a config with three fields: 879 >>> from lsst.pex.config import Config, Field 880 >>> class DemoConfig(Config): 881 ... fieldA = Field(doc='Field A', dtype=int, default=42) 882 ... fieldB = Field(doc='Field B', dtype=bool, default=True) 883 ... fieldC = Field(doc='Field C', dtype=str, default='Hello world') 885 >>> config = DemoConfig() 887 These are the default values of each field: 889 >>> for name, value in config.iteritems(): 890 ... print(f"{name}: {value}") 894 fieldC: 'Hello world' 896 Using this method to update ``fieldA`` and ``fieldC``: 898 >>> config.update(fieldA=13, fieldC='Updated!') 900 Now the values of each field are: 902 >>> for name, value in config.iteritems(): 903 ... print(f"{name}: {value}") 910 label = kw.pop(
"__label",
"update")
912 for name, value
in kw.items():
914 field = self._fields[name]
915 field.__set__(self, value, at=at, label=label)
917 raise KeyError(
"No field of name %s exists in config type %s" % (name, _typeStr(self)))
919 def load(self, filename, root="config"):
920 """Modify this config in place by executing the Python code in a 926 Name of the configuration file. A configuration file is Python 928 root : `str`, optional 929 Name of the variable in file that refers to the config being 932 For example, the value of root is ``"config"`` and the file 937 Then this config's field ``myField`` is set to ``5``. 939 **Deprecated:** For backwards compatibility, older config files 940 that use ``root="root"`` instead of ``root="config"`` will be 941 loaded with a warning printed to `sys.stderr`. This feature will be 942 removed at some point. 946 lsst.pex.config.Config.loadFromStream 947 lsst.pex.config.Config.save 948 lsst.pex.config.Config.saveFromStream 950 with open(filename,
"r") as f: 951 code = compile(f.read(), filename=filename, mode="exec")
955 """Modify this Config in place by executing the Python code in the 960 stream : file-like object, `str`, or compiled string 961 Stream containing configuration override code. 962 root : `str`, optional 963 Name of the variable in file that refers to the config being 966 For example, the value of root is ``"config"`` and the file 971 Then this config's field ``myField`` is set to ``5``. 973 **Deprecated:** For backwards compatibility, older config files 974 that use ``root="root"`` instead of ``root="config"`` will be 975 loaded with a warning printed to `sys.stderr`. This feature will be 976 removed at some point. 977 filename : `str`, optional 978 Name of the configuration file, or `None` if unknown or contained 979 in the stream. Used for error reporting. 983 lsst.pex.config.Config.load 984 lsst.pex.config.Config.save 985 lsst.pex.config.Config.saveFromStream 990 exec(stream, {}, local)
991 except NameError
as e:
992 if root ==
"config" and "root" in e.args[0]:
996 filename = getattr(stream,
"co_filename",
None)
998 filename = getattr(stream,
"name",
"?")
999 print(f
"Config override file {filename!r}" 1000 " appears to use 'root' instead of 'config'; trying with 'root'", file=sys.stderr)
1001 local = {
"root": self}
1002 exec(stream, {}, local)
1006 self._imports.
update(importer.getModules())
1008 def save(self, filename, root="config"):
1009 """Save a Python script to the named file, which, when loaded, 1010 reproduces this config. 1015 Desination filename of this configuration. 1016 root : `str`, optional 1017 Name to use for the root config variable. The same value must be 1018 used when loading (see `lsst.pex.config.Config.load`). 1022 lsst.pex.config.Config.saveToStream 1023 lsst.pex.config.Config.load 1024 lsst.pex.config.Config.loadFromStream 1026 d = os.path.dirname(filename)
1027 with tempfile.NamedTemporaryFile(mode=
"w", delete=
False, dir=d)
as outfile:
1032 umask = os.umask(0o077)
1034 os.chmod(outfile.name, (~umask & 0o666))
1038 shutil.move(outfile.name, filename)
1041 """Save a configuration file to a stream, which, when loaded, 1042 reproduces this config. 1046 outfile : file-like object 1047 Destination file object write the config into. Accepts strings not 1050 Name to use for the root config variable. The same value must be 1051 used when loading (see `lsst.pex.config.Config.load`). 1055 lsst.pex.config.Config.save 1056 lsst.pex.config.Config.load 1057 lsst.pex.config.Config.loadFromStream 1064 self._imports.remove(self.__module__)
1065 configType =
type(self)
1066 typeString = _typeStr(configType)
1067 outfile.write(
u"import {}\n".
format(configType.__module__))
1068 outfile.write(
u"assert type({})=={}, 'config is of type %s.%s ".
format(root, typeString))
1069 outfile.write(
u"instead of {}' % (type({}).__module__, type({}).__name__)\n".
format(typeString,
1072 for imp
in self._imports:
1073 if imp
in sys.modules
and sys.modules[imp]
is not None:
1074 outfile.write(
u"import {}\n".
format(imp))
1080 """Make this config, and all subconfigs, read-only. 1086 def _save(self, outfile):
1087 """Save this config to an open stream object. 1091 outfile : file-like object 1092 Destination file object write the config into. Accepts strings not 1096 field.save(outfile, self)
1098 def _collectImports(self):
1099 """Adds module containing self to the list of things to import and 1100 then loops over all the fields in the config calling a corresponding 1101 collect method. The field method will call _collectImports on any configs 1102 it may own and return the set of things to import. This returned set 1103 will be merged with the set of imports for this config class. 1105 self._imports.add(self.__module__)
1107 field._collectImports(self, self._imports)
1110 """Make a dictionary of field names and their values. 1115 Dictionary with keys that are `~lsst.pex.config.Field` names. 1116 Values are `~lsst.pex.config.Field` values. 1120 lsst.pex.config.Field.toDict 1124 This method uses the `~lsst.pex.config.Field.toDict` method of 1125 individual fields. Subclasses of `~lsst.pex.config.Field` may need to 1126 implement a ``toDict`` method for *this* method to work. 1130 dict_[name] = field.toDict(self)
1134 """Get all the field names in the config, recursively. 1138 names : `list` of `str` 1145 with io.StringIO()
as strFd:
1147 contents = strFd.getvalue()
1153 for line
in contents.split(
"\n"):
1154 if re.search(
r"^((assert|import)\s+|\s*$|#)", line):
1157 mat = re.search(
r"^(?:config\.)?([^=]+)\s*=\s*.*", line)
1159 keys.append(mat.group(1))
1163 def _rename(self, name):
1164 """Rename this config object in its parent `~lsst.pex.config.Config`. 1169 New name for this config in its parent `~lsst.pex.config.Config`. 1173 This method uses the `~lsst.pex.config.Field.rename` method of 1174 individual `lsst.pex.config.Field` instances. 1175 `lsst.pex.config.Field` subclasses may need to implement a ``rename`` 1176 method for *this* method to work. 1180 lsst.pex.config.Field.rename 1187 """Validate the Config, raising an exception if invalid. 1191 lsst.pex.config.FieldValidationError 1192 Raised if verification fails. 1196 The base class implementation performs type checks on all fields by 1197 calling their `~lsst.pex.config.Field.validate` methods. 1199 Complex single-field validation can be defined by deriving new Field 1200 types. For convenience, some derived `lsst.pex.config.Field`-types 1201 (`~lsst.pex.config.ConfigField` and 1202 `~lsst.pex.config.ConfigChoiceField`) are defined in `lsst.pex.config` 1203 that handle recursing into subconfigs. 1205 Inter-field relationships should only be checked in derived 1206 `~lsst.pex.config.Config` classes after calling this method, and base 1207 validation is complete. 1210 field.validate(self)
1213 """Format a configuration field's history to a human-readable format. 1218 Name of a `~lsst.pex.config.Field` in this config. 1220 Keyword arguments passed to `lsst.pex.config.history.format`. 1225 A string containing the formatted history. 1229 lsst.pex.config.history.format 1232 return pexHist.format(self, name, **kwargs)
1234 history = property(
lambda x: x._history)
1235 """Read-only history. 1239 """Set an attribute (such as a field's value). 1243 Unlike normal Python objects, `~lsst.pex.config.Config` objects are 1244 locked such that no additional attributes nor properties may be added 1245 to them dynamically. 1247 Although this is not the standard Python behavior, it helps to protect 1248 users from accidentally mispelling a field name, or trying to set a 1255 self.
_fields[attr].__set__(self, value, at=at, label=label)
1256 elif hasattr(getattr(self.__class__, attr,
None),
'__set__'):
1258 return object.__setattr__(self, attr, value)
1259 elif attr
in self.__dict__
or attr
in (
"_name",
"_history",
"_storage",
"_frozen",
"_imports"):
1261 self.__dict__[attr] = value
1264 raise AttributeError(
"%s has no attribute %s" % (_typeStr(self), attr))
1270 self.
_fields[attr].__delete__(self, at=at, label=label)
1272 object.__delattr__(self, attr)
1277 thisValue = getattr(self, name)
1278 otherValue = getattr(other, name)
1279 if isinstance(thisValue, float)
and math.isnan(thisValue):
1280 if not math.isnan(otherValue):
1282 elif thisValue != otherValue:
1288 return not self.
__eq__(other)
1296 ", ".join(
"%s=%r" % (k, v)
for k, v
in self.
toDict().
items()
if v
is not None)
1299 def compare(self, other, shortcut=True, rtol=1E-8, atol=1E-8, output=None):
1300 """Compare this configuration to another `~lsst.pex.config.Config` for 1305 other : `lsst.pex.config.Config` 1306 Other `~lsst.pex.config.Config` object to compare against this 1308 shortcut : `bool`, optional 1309 If `True`, return as soon as an inequality is found. Default is 1311 rtol : `float`, optional 1312 Relative tolerance for floating point comparisons. 1313 atol : `float`, optional 1314 Absolute tolerance for floating point comparisons. 1315 output : callable, optional 1316 A callable that takes a string, used (possibly repeatedly) to 1317 report inequalities. 1322 `True` when the two `lsst.pex.config.Config` instances are equal. 1323 `False` if there is an inequality. 1327 lsst.pex.config.compareConfigs 1331 Unselected targets of `~lsst.pex.config.RegistryField` fields and 1332 unselected choices of `~lsst.pex.config.ConfigChoiceField` fields 1333 are not considered by this method. 1335 Floating point comparisons are performed by `numpy.allclose`. 1337 name1 = self.
_name if self.
_name is not None else "config" 1338 name2 = other._name
if other._name
is not None else "config" 1341 rtol=rtol, atol=atol, output=output)
1345 """Create a `~lsst.pex.config.Config` from a stream. 1349 cls : `lsst.pex.config.Config`-type 1350 A `lsst.pex.config.Config` type (not an instance) that is instantiated 1351 with configurations in the ``stream``. 1352 stream : file-like object, `str`, or compiled string 1353 Stream containing configuration override code. 1357 config : `lsst.pex.config.Config` 1362 lsst.pex.config.Config.loadFromStream 1365 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)