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 save(self, outfile, instance):
395 """Save this field to a file (for internal use only). 399 outfile : file-like object 400 A writeable field handle. 402 The `Config` instance that contains this field. 406 This method is invoked by the `~lsst.pex.config.Config` object that 407 contains this field and should not be called directly. 409 The output consists of the documentation string 410 (`lsst.pex.config.Field.doc`) formatted as a Python comment. The second 411 line is formatted as an assignment: ``{fullname}={value}``. 413 This output can be executed with Python. 416 fullname = _joinNamePath(instance._name, self.name)
419 doc =
"# " +
str(self.
doc).replace(
"\n",
"\n# ")
420 if isinstance(value, float)
and (math.isinf(value)
or math.isnan(value)):
422 outfile.write(
u"{}\n{}=float('{!r}')\n\n".
format(doc, fullname, value))
424 outfile.write(
u"{}\n{}={!r}\n\n".
format(doc, fullname, value))
427 """Convert the field value so that it can be set as the value of an 428 item in a `dict` (for internal use only). 433 The `Config` that contains this field. 438 The field's value. See *Notes*. 442 This method invoked by the owning `~lsst.pex.config.Config` object and 443 should not be called directly. 445 Simple values are passed through. Complex data structures must be 446 manipulated. For example, a `~lsst.pex.config.Field` holding a 447 subconfig should, instead of the subconfig object, return a `dict` 448 where the keys are the field names in the subconfig, and the values are 449 the field values in the subconfig. 453 def __get__(self, instance, owner=None, at=None, label="default"):
454 """Define how attribute access should occur on the Config instance 455 This is invoked by the owning config object and should not be called 458 When the field attribute is accessed on a Config class object, it 459 returns the field object itself in order to allow inspection of 462 When the field attribute is access on a config instance, the actual 463 value described by the field (and held by the Config instance) is 466 if instance
is None or not isinstance(instance, Config):
469 return instance._storage[self.name]
471 def __set__(self, instance, value, at=None, label='assignment'):
472 """Set an attribute on the config instance. 476 instance : `lsst.pex.config.Config` 477 The config instance that contains this field. 479 Value to set on this field. 480 at : `list` of `lsst.pex.config.callStack.StackFrame` 481 The call stack (created by 482 `lsst.pex.config.callStack.getCallStack`). 483 label : `str`, optional 484 Event label for the history. 488 This method is invoked by the owning `lsst.pex.config.Config` object 489 and should not be called directly. 491 Derived `~lsst.pex.config.Field` classes may need to override the 492 behavior. When overriding ``__set__``, `~lsst.pex.config.Field` authors 493 should follow the following rules: 495 - Do not allow modification of frozen configs. 496 - Validate the new value **before** modifying the field. Except if the 497 new value is `None`. `None` is special and no attempt should be made 498 to validate it until `lsst.pex.config.Config.validate` is called. 499 - Do not modify the `~lsst.pex.config.Config` instance to contain 501 - If the field is modified, update the history of the 502 `lsst.pex.config.field.Field` to reflect the changes. 504 In order to decrease the need to implement this method in derived 505 `~lsst.pex.config.Field` types, value validation is performed in the 506 `lsst.pex.config.Field._validateValue`. If only the validation step 507 differs in the derived `~lsst.pex.config.Field`, it is simpler to 508 implement `lsst.pex.config.Field._validateValue` than to reimplement 509 ``__set__``. More complicated behavior, however, may require 515 history = instance._history.setdefault(self.name, [])
516 if value
is not None:
517 value = _autocast(value, self.
dtype)
520 except BaseException
as e:
523 instance._storage[self.name] = value
526 history.append((value, at, label))
529 """Delete an attribute from a `lsst.pex.config.Config` instance. 533 instance : `lsst.pex.config.Config` 534 The config instance that contains this field. 535 at : `list` of `lsst.pex.config.callStack.StackFrame` 536 The call stack (created by 537 `lsst.pex.config.callStack.getCallStack`). 538 label : `str`, optional 539 Event label for the history. 543 This is invoked by the owning `~lsst.pex.config.Config` object and 544 should not be called directly. 548 self.
__set__(instance,
None, at=at, label=label)
550 def _compare(self, instance1, instance2, shortcut, rtol, atol, output):
551 """Compare a field (named `Field.name`) in two 552 `~lsst.pex.config.Config` instances for equality. 556 instance1 : `lsst.pex.config.Config` 557 Left-hand side `Config` instance to compare. 558 instance2 : `lsst.pex.config.Config` 559 Right-hand side `Config` instance to compare. 560 shortcut : `bool`, optional 562 rtol : `float`, optional 563 Relative tolerance for floating point comparisons. 564 atol : `float`, optional 565 Absolute tolerance for floating point comparisons. 566 output : callable, optional 567 A callable that takes a string, used (possibly repeatedly) to 572 This method must be overridden by more complex `Field` subclasses. 576 lsst.pex.config.compareScalars 578 v1 = getattr(instance1, self.name)
579 v2 = getattr(instance2, self.name)
581 _joinNamePath(instance1._name, self.name),
582 _joinNamePath(instance2._name, self.name)
588 """Importer (for `sys.meta_path`) that records which modules are being 591 *This class does not do any importing itself.* 595 Use this class as a context manager to ensure it is properly uninstalled 598 >>> with RecordingImporter() as importer: 600 ... import numpy as np 601 ... print("Imported: " + importer.getModules()) 609 sys.meta_path = [self] + sys.meta_path
617 """Uninstall the importer. 622 """Called as part of the ``import`` chain of events. 629 """Get the set of modules that were imported. 633 modules : `set` of `str` 634 Set of imported module names. 640 """Base class for configuration (*config*) objects. 644 A ``Config`` object will usually have several `~lsst.pex.config.Field` 645 instances as class attributes. These are used to define most of the base 648 ``Config`` implements a mapping API that provides many `dict`-like methods, 649 such as `keys`, `values`, `items`, `iteritems`, `iterkeys`, and 650 `itervalues`. ``Config`` instances also support the ``in`` operator to 651 test if a field is in the config. Unlike a `dict`, ``Config`` classes are 652 not subscriptable. Instead, access individual fields as attributes of the 653 configuration instance. 657 Config classes are subclasses of ``Config`` that have 658 `~lsst.pex.config.Field` instances (or instances of 659 `~lsst.pex.config.Field` subclasses) as class attributes: 661 >>> from lsst.pex.config import Config, Field, ListField 662 >>> class DemoConfig(Config): 663 ... intField = Field(doc="An integer field", dtype=int, default=42) 664 ... listField = ListField(doc="List of favorite beverages.", dtype=str, 665 ... default=['coffee', 'green tea', 'water']) 667 >>> config = DemoConfig() 669 Configs support many `dict`-like APIs: 672 ['intField', 'listField'] 673 >>> 'intField' in config 676 Individual fields can be accessed as attributes of the configuration: 680 >>> config.listField.append('earl grey tea') 681 >>> print(config.listField) 682 ['coffee', 'green tea', 'water', 'earl grey tea'] 686 """Iterate over fields. 696 List of `lsst.pex.config.Field` names. 700 lsst.pex.config.Config.iterkeys 710 List of field values. 714 lsst.pex.config.Config.itervalues 719 """Get configurations as ``(field name, field value)`` pairs. 724 List of tuples for each configuration. Tuple items are: 731 lsst.pex.config.Config.iteritems 736 """Iterate over (field name, field value) pairs. 748 lsst.pex.config.Config.items 750 return iter(self._storage.
items())
753 """Iterate over field values. 762 lsst.pex.config.Config.values 764 return iter(self.storage.
values())
767 """Iterate over field names 772 A field's key (attribute name). 776 lsst.pex.config.Config.values 778 return iter(self.storage.
keys())
781 """!Return True if the specified field exists in this config 783 @param[in] name field name to test for 788 """Allocate a new `lsst.pex.config.Config` object. 790 In order to ensure that all Config object are always in a proper state 791 when handed to users or to derived `~lsst.pex.config.Config` classes, 792 some attributes are handled at allocation time rather than at 795 This ensures that even if a derived `~lsst.pex.config.Config` class 796 implements ``__init__``, its author does not need to be concerned about 797 when or even the base ``Config.__init__`` should be called. 799 name = kw.pop(
"__name",
None)
802 kw.pop(
"__label",
"default")
804 instance = object.__new__(cls)
805 instance._frozen =
False 806 instance._name = name
807 instance._storage = {}
808 instance._history = {}
809 instance._imports =
set()
811 for field
in instance._fields.values():
812 instance._history[field.name] = []
813 field.__set__(instance, field.default, at=at + [field.source], label=
"default")
815 instance.setDefaults()
817 instance.update(__at=at, **kw)
821 """Reduction for pickling (function with arguments to reproduce). 823 We need to condense and reconstitute the `~lsst.pex.config.Config`, 824 since it may contain lambdas (as the ``check`` elements) that cannot 828 stream = io.StringIO()
830 return (unreduceConfig, (self.__class__, stream.getvalue().encode()))
833 """Subclass hook for computing defaults. 837 Derived `~lsst.pex.config.Config` classes that must compute defaults 838 rather than using the `~lsst.pex.config.Field` instances's defaults 839 should do so here. To correctly use inherited defaults, 840 implementations of ``setDefaults`` must call their base class's 846 """Update values of fields specified by the keyword arguments. 851 Keywords are configuration field names. Values are configuration 856 The ``__at`` and ``__label`` keyword arguments are special internal 857 keywords. They are used to strip out any internal steps from the 858 history tracebacks of the config. Do not modify these keywords to 859 subvert a `~lsst.pex.config.Config` instance's history. 863 This is a config with three fields: 865 >>> from lsst.pex.config import Config, Field 866 >>> class DemoConfig(Config): 867 ... fieldA = Field(doc='Field A', dtype=int, default=42) 868 ... fieldB = Field(doc='Field B', dtype=bool, default=True) 869 ... fieldC = Field(doc='Field C', dtype=str, default='Hello world') 871 >>> config = DemoConfig() 873 These are the default values of each field: 875 >>> for name, value in config.iteritems(): 876 ... print(f"{name}: {value}") 880 fieldC: 'Hello world' 882 Using this method to update ``fieldA`` and ``fieldC``: 884 >>> config.update(fieldA=13, fieldC='Updated!') 886 Now the values of each field are: 888 >>> for name, value in config.iteritems(): 889 ... print(f"{name}: {value}") 896 label = kw.pop(
"__label",
"update")
898 for name, value
in kw.items():
900 field = self._fields[name]
901 field.__set__(self, value, at=at, label=label)
903 raise KeyError(
"No field of name %s exists in config type %s" % (name, _typeStr(self)))
905 def load(self, filename, root="config"):
906 """Modify this config in place by executing the Python code in a 912 Name of the configuration file. A configuration file is Python 914 root : `str`, optional 915 Name of the variable in file that refers to the config being 918 For example, the value of root is ``"config"`` and the file 923 Then this config's field ``myField`` is set to ``5``. 925 **Deprecated:** For backwards compatibility, older config files 926 that use ``root="root"`` instead of ``root="config"`` will be 927 loaded with a warning printed to `sys.stderr`. This feature will be 928 removed at some point. 932 lsst.pex.config.Config.loadFromStream 933 lsst.pex.config.Config.save 934 lsst.pex.config.Config.saveFromStream 936 with open(filename,
"r") as f: 937 code = compile(f.read(), filename=filename, mode="exec")
941 """Modify this Config in place by executing the Python code in the 946 stream : file-like object, `str`, or compiled string 947 Stream containing configuration override code. 948 root : `str`, optional 949 Name of the variable in file that refers to the config being 952 For example, the value of root is ``"config"`` and the file 957 Then this config's field ``myField`` is set to ``5``. 959 **Deprecated:** For backwards compatibility, older config files 960 that use ``root="root"`` instead of ``root="config"`` will be 961 loaded with a warning printed to `sys.stderr`. This feature will be 962 removed at some point. 963 filename : `str`, optional 964 Name of the configuration file, or `None` if unknown or contained 965 in the stream. Used for error reporting. 969 lsst.pex.config.Config.load 970 lsst.pex.config.Config.save 971 lsst.pex.config.Config.saveFromStream 976 exec(stream, {}, local)
977 except NameError
as e:
978 if root ==
"config" and "root" in e.args[0]:
982 filename = getattr(stream,
"co_filename",
None)
984 filename = getattr(stream,
"name",
"?")
985 print(f
"Config override file {filename!r}" 986 " appears to use 'root' instead of 'config'; trying with 'root'", file=sys.stderr)
987 local = {
"root": self}
988 exec(stream, {}, local)
992 self._imports.
update(importer.getModules())
994 def save(self, filename, root="config"):
995 """Save a Python script to the named file, which, when loaded, 996 reproduces this config. 1001 Desination filename of this configuration. 1002 root : `str`, optional 1003 Name to use for the root config variable. The same value must be 1004 used when loading (see `lsst.pex.config.Config.load`). 1008 lsst.pex.config.Config.saveToStream 1009 lsst.pex.config.Config.load 1010 lsst.pex.config.Config.loadFromStream 1012 d = os.path.dirname(filename)
1013 with tempfile.NamedTemporaryFile(mode=
"w", delete=
False, dir=d)
as outfile:
1018 umask = os.umask(0o077)
1020 os.chmod(outfile.name, (~umask & 0o666))
1024 shutil.move(outfile.name, filename)
1027 """Save a configuration file to a stream, which, when loaded, 1028 reproduces this config. 1032 outfile : file-like object 1033 Destination file object write the config into. Accepts strings not 1036 Name to use for the root config variable. The same value must be 1037 used when loading (see `lsst.pex.config.Config.load`). 1041 lsst.pex.config.Config.save 1042 lsst.pex.config.Config.load 1043 lsst.pex.config.Config.loadFromStream 1048 configType =
type(self)
1049 typeString = _typeStr(configType)
1050 outfile.write(
u"import {}\n".
format(configType.__module__))
1051 outfile.write(
u"assert type({})=={}, 'config is of type %s.%s ".
format(root, typeString))
1052 outfile.write(
u"instead of {}' % (type({}).__module__, type({}).__name__)\n".
format(typeString,
1060 """Make this config, and all subconfigs, read-only. 1066 def _save(self, outfile):
1067 """Save this config to an open stream object. 1071 outfile : file-like object 1072 Destination file object write the config into. Accepts strings not 1075 for imp
in self._imports:
1076 if imp
in sys.modules
and sys.modules[imp]
is not None:
1077 outfile.write(
u"import {}\n".
format(imp))
1079 field.save(outfile, self)
1082 """Make a dictionary of field names and their values. 1087 Dictionary with keys that are `~lsst.pex.config.Field` names. 1088 Values are `~lsst.pex.config.Field` values. 1092 lsst.pex.config.Field.toDict 1096 This method uses the `~lsst.pex.config.Field.toDict` method of 1097 individual fields. Subclasses of `~lsst.pex.config.Field` may need to 1098 implement a ``toDict`` method for *this* method to work. 1102 dict_[name] = field.toDict(self)
1106 """Get all the field names in the config, recursively. 1110 names : `list` of `str` 1117 with io.StringIO()
as strFd:
1119 contents = strFd.getvalue()
1125 for line
in contents.split(
"\n"):
1126 if re.search(
r"^((assert|import)\s+|\s*$|#)", line):
1129 mat = re.search(
r"^(?:config\.)?([^=]+)\s*=\s*.*", line)
1131 keys.append(mat.group(1))
1135 def _rename(self, name):
1136 """Rename this config object in its parent `~lsst.pex.config.Config`. 1141 New name for this config in its parent `~lsst.pex.config.Config`. 1145 This method uses the `~lsst.pex.config.Field.rename` method of 1146 individual `lsst.pex.config.Field` instances. 1147 `lsst.pex.config.Field` subclasses may need to implement a ``rename`` 1148 method for *this* method to work. 1152 lsst.pex.config.Field.rename 1159 """Validate the Config, raising an exception if invalid. 1163 lsst.pex.config.FieldValidationError 1164 Raised if verification fails. 1168 The base class implementation performs type checks on all fields by 1169 calling their `~lsst.pex.config.Field.validate` methods. 1171 Complex single-field validation can be defined by deriving new Field 1172 types. For convenience, some derived `lsst.pex.config.Field`-types 1173 (`~lsst.pex.config.ConfigField` and 1174 `~lsst.pex.config.ConfigChoiceField`) are defined in `lsst.pex.config` 1175 that handle recursing into subconfigs. 1177 Inter-field relationships should only be checked in derived 1178 `~lsst.pex.config.Config` classes after calling this method, and base 1179 validation is complete. 1182 field.validate(self)
1185 """Format a configuration field's history to a human-readable format. 1190 Name of a `~lsst.pex.config.Field` in this config. 1192 Keyword arguments passed to `lsst.pex.config.history.format`. 1197 A string containing the formatted history. 1201 lsst.pex.config.history.format 1204 return pexHist.format(self, name, **kwargs)
1206 history = property(
lambda x: x._history)
1207 """Read-only history. 1211 """Set an attribute (such as a field's value). 1215 Unlike normal Python objects, `~lsst.pex.config.Config` objects are 1216 locked such that no additional attributes nor properties may be added 1217 to them dynamically. 1219 Although this is not the standard Python behavior, it helps to protect 1220 users from accidentally mispelling a field name, or trying to set a 1227 self.
_fields[attr].__set__(self, value, at=at, label=label)
1228 elif hasattr(getattr(self.__class__, attr,
None),
'__set__'):
1230 return object.__setattr__(self, attr, value)
1231 elif attr
in self.__dict__
or attr
in (
"_name",
"_history",
"_storage",
"_frozen",
"_imports"):
1233 self.__dict__[attr] = value
1236 raise AttributeError(
"%s has no attribute %s" % (_typeStr(self), attr))
1242 self.
_fields[attr].__delete__(self, at=at, label=label)
1244 object.__delattr__(self, attr)
1249 thisValue = getattr(self, name)
1250 otherValue = getattr(other, name)
1251 if isinstance(thisValue, float)
and math.isnan(thisValue):
1252 if not math.isnan(otherValue):
1254 elif thisValue != otherValue:
1260 return not self.
__eq__(other)
1268 ", ".join(
"%s=%r" % (k, v)
for k, v
in self.
toDict().
items()
if v
is not None)
1271 def compare(self, other, shortcut=True, rtol=1E-8, atol=1E-8, output=None):
1272 """Compare this configuration to another `~lsst.pex.config.Config` for 1277 other : `lsst.pex.config.Config` 1278 Other `~lsst.pex.config.Config` object to compare against this 1280 shortcut : `bool`, optional 1281 If `True`, return as soon as an inequality is found. Default is 1283 rtol : `float`, optional 1284 Relative tolerance for floating point comparisons. 1285 atol : `float`, optional 1286 Absolute tolerance for floating point comparisons. 1287 output : callable, optional 1288 A callable that takes a string, used (possibly repeatedly) to 1289 report inequalities. 1294 `True` when the two `lsst.pex.config.Config` instances are equal. 1295 `False` if there is an inequality. 1299 lsst.pex.config.compareConfigs 1303 Unselected targets of `~lsst.pex.config.RegistryField` fields and 1304 unselected choices of `~lsst.pex.config.ConfigChoiceField` fields 1305 are not considered by this method. 1307 Floating point comparisons are performed by `numpy.allclose`. 1309 name1 = self.
_name if self.
_name is not None else "config" 1310 name2 = other._name
if other._name
is not None else "config" 1313 rtol=rtol, atol=atol, output=output)
1317 """Create a `~lsst.pex.config.Config` from a stream. 1321 cls : `lsst.pex.config.Config`-type 1322 A `lsst.pex.config.Config` type (not an instance) that is instantiated 1323 with configurations in the ``stream``. 1324 stream : file-like object, `str`, or compiled string 1325 Stream containing configuration override code. 1329 config : `lsst.pex.config.Config` 1334 lsst.pex.config.Config.loadFromStream 1337 config.loadFromStream(stream)
def toDict(self, instance)
def formatHistory(self, name, kwargs)
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)