25 __all__ = [
"getPropertySetState",
"getPropertyListState",
"setPropertySetState",
"setPropertyListState"]
29 from collections.abc
import Mapping, KeysView
35 from .propertySet
import PropertySet
36 from .propertyList
import PropertyList
37 from ..dateTime
import DateTime
41 """Get the state of a PropertySet in a form that can be pickled. 45 container : `PropertySet` 46 The property container. 47 asLists : `bool`, optional 48 If False, the default, `tuple` will be used for the contents. If true 49 a `list` will be used. 53 state : `list` of `tuple` or `list` of `list` 54 The state, as a list of tuples (or lists), each of which contains 55 the following 3 items: 56 - name (a `str`): the name of the item 57 - elementTypeName (a `str`): the suffix of a ``setX`` method name 58 which is appropriate for the data type. For example integer 59 data has ``elementTypeName="Int"` which corresponds to 60 the ``setInt`` method. 61 - value: the data for the item, in a form compatible 62 with the set method named by ``elementTypeName`` 64 names = container.names(topLevelOnly=
True)
65 sequence = list
if asLists
else tuple
66 return [sequence((name, _propertyContainerElementTypeName(container, name),
67 _propertyContainerGet(container, name, returnStyle=ReturnStyle.AUTO)))
72 """Get the state of a PropertyList in a form that can be pickled. 76 container : `PropertyList` 77 The property container. 78 asLists : `bool`, optional 79 If False, the default, `tuple` will be used for the contents. If true 80 a `list` will be used. 84 state : `list` of `tuple` or `list` of `list` 85 The state, as a list of tuples (or lists), each of which contains 86 the following 4 items: 87 - name (a `str`): the name of the item 88 - elementTypeName (a `str`): the suffix of a ``setX`` method name 89 which is appropriate for the data type. For example integer 90 data has ``elementTypeName="Int"` which corresponds to 91 the ``setInt`` method. 92 - value: the data for the item, in a form compatible 93 with the set method named by ``elementTypeName`` 94 - comment (a `str`): the comment. This item is only present 95 if ``container`` is a PropertyList. 97 sequence = list
if asLists
else tuple
98 return [sequence((name, _propertyContainerElementTypeName(container, name),
99 _propertyContainerGet(container, name, returnStyle=ReturnStyle.AUTO),
100 container.getComment(name)))
101 for name
in container.getOrderedNames()]
105 """Restore the state of a PropertySet, in place. 109 container : `PropertySet` 110 The property container whose state is to be restored. 111 It should be empty to start with and is updated in place. 113 The state, as returned by `getPropertySetState` 115 for name, elemType, value
in state:
116 if elemType
is not None:
117 getattr(container,
"set" + elemType)(name, value)
119 raise ValueError(f
"Unrecognized values for state restoration: ({name}, {elemType}, {value})")
123 """Restore the state of a PropertyList, in place. 127 container : `PropertyList` 128 The property container whose state is to be restored. 129 It should be empty to start with and is updated in place. 131 The state, as returned by ``getPropertyListState`` 133 for name, elemType, value, comment
in state:
134 getattr(container,
"set" + elemType)(name, value, comment)
143 def _propertyContainerElementTypeName(container, name):
144 """Return name of the type of a particular element""" 146 t = container.typeOf(name)
147 except LookupError
as e:
150 raise KeyError(
str(e))
151 for checkType
in (
"Bool",
"Short",
"Int",
"Long",
"LongLong",
"Float",
"Double",
"String",
"DateTime",
152 "PropertySet",
"Undef"):
153 if t == getattr(container,
"TYPE_" + checkType):
158 def _propertyContainerGet(container, name, returnStyle):
159 """Get a value of unknown type as a scalar or array 163 container : `lsst.daf.base.PropertySet` or `lsst.daf.base.PropertyList` 164 Container from which to get the value 167 returnStyle : `ReturnStyle` 168 Control whether numeric or string data is returned as an array 169 or scalar (the other types, ``PropertyList``, ``PropertySet`` 170 and ``PersistablePtr``, are always returned as a scalar): 171 - ReturnStyle.ARRAY: return numeric or string data types 172 as an array of values. 173 - ReturnStyle.SCALAR: return numeric or string data types 174 as a single value; if the item has multiple values then 175 return the last value. 176 - ReturnStyle.AUTO: (deprecated) return numeric or string data 177 as a scalar if there is just one item, or as an array 183 Raised if the specified key does not exist in the container. 185 Raised if the value retrieved is of an unexpected type. 187 Raised if the value for ``returnStyle`` is not correct. 189 if not container.exists(name):
190 raise KeyError(name +
" not found")
191 if returnStyle
not in ReturnStyle:
192 raise ValueError(
"returnStyle {} must be a ReturnStyle".
format(returnStyle))
194 elemType = _propertyContainerElementTypeName(container, name)
195 if elemType
and elemType !=
"PropertySet":
196 value = getattr(container,
"getArray" + elemType)(name)
197 if returnStyle == ReturnStyle.ARRAY
or (returnStyle == ReturnStyle.AUTO
and len(value) > 1):
201 if container.isPropertySetPtr(name):
203 return container.getAsPropertyListPtr(name)
205 return container.getAsPropertySetPtr(name)
207 return container.getAsPersistablePtr(name)
210 raise TypeError(
'Unknown PropertySet value type for ' + name)
213 def _guessIntegerType(container, name, value):
214 """Given an existing container and name, determine the type 215 that should be used for the supplied value. The supplied value 216 is assumed to be a scalar. 218 On Python 3 all ints are LongLong but we need to be able to store them 219 in Int containers if that is what is being used (testing for truncation). 220 Int is assumed to mean 32bit integer (2147483647 to -2147483648). 222 If there is no pre-existing value we have to decide what to do. For now 223 we pick Int if the value is less than maxsize. 225 Returns None if the value supplied is a bool or not an integral value. 233 if isinstance(value, bool):
236 if isinstance(value, numbers.Integral):
238 containerType = _propertyContainerElementTypeName(container, name)
242 if value <= maxInt
and value >= minInt:
247 if containerType ==
"Int":
253 elif containerType ==
"LongLong":
258 def _propertyContainerSet(container, name, value, typeMenu, *args):
259 """Set a single Python value of unknown type""" 260 if hasattr(value,
"__iter__")
and not isinstance(value, (str, PropertySet, PropertyList)):
266 setType = _guessIntegerType(container, name, exemplar)
268 if setType
is not None or t
in typeMenu:
270 setType = typeMenu[t]
271 return getattr(container,
"set" + setType)(name, value, *args)
273 for checkType
in typeMenu:
274 if (checkType
is None and exemplar
is None)
or \
275 (checkType
is not None and isinstance(exemplar, checkType)):
276 return getattr(container,
"set" + typeMenu[checkType])(name, value, *args)
277 raise TypeError(
"Unknown value type for key '%s': %s" % (name, t))
280 def _propertyContainerAdd(container, name, value, typeMenu, *args):
281 """Add a single Python value of unknown type""" 282 if hasattr(value,
"__iter__"):
288 addType = _guessIntegerType(container, name, exemplar)
290 if addType
is not None or t
in typeMenu:
292 addType = typeMenu[t]
293 return getattr(container,
"add" + addType)(name, value, *args)
295 for checkType
in typeMenu:
296 if (checkType
is None and exemplar
is None)
or \
297 (checkType
is not None and isinstance(exemplar, checkType)):
298 return getattr(container,
"add" + typeMenu[checkType])(name, value, *args)
299 raise TypeError(
"Unknown value type for key '%s': %s" % (name, t))
302 def _makePropertySet(state):
303 """Make a `PropertySet` from the state returned by `getPropertySetState` 308 The data returned by `getPropertySetState`. 315 def _makePropertyList(state):
316 """Make a `PropertyList` from the state returned by 317 `getPropertyListState` 322 The data returned by `getPropertySetState`. 333 _typeMenu = {bool:
"Bool",
336 DateTime:
"DateTime",
337 PropertySet:
"PropertySet",
338 PropertyList:
"PropertySet",
342 def get(self, name, default=None):
343 """Return an item as a scalar, else default. 345 Identical to `getScalar` except that a default value is returned 346 if the requested key is not present. If an array item is requested 347 the final value in the array will be returned. 353 default : `object`, optional 354 Default value to use if the named item is not present. 358 value : any type supported by container 359 Single value of any type supported by the container, else the 360 default value if the requested item is not present in the 361 container. For array items the most recently added value is 365 return _propertyContainerGet(self, name, returnStyle=ReturnStyle.SCALAR)
370 """Return an item as an array if the item is numeric or string 372 If the item is a `PropertySet`, `PropertyList` or 373 `lsst.daf.base.PersistablePtr` then return the item as a scalar. 382 values : `list` of any type supported by container 383 The contents of the item, guaranteed to be returned as a `list.` 388 Raised if the item does not exist. 390 return _propertyContainerGet(self, name, returnStyle=ReturnStyle.ARRAY)
393 """Return an item as a scalar 395 If the item has more than one value then the last value is returned. 405 Value stored in the item. If the item refers to an array the 406 most recently added value is returned. 411 Raised if the item does not exist. 413 return _propertyContainerGet(self, name, returnStyle=ReturnStyle.SCALAR)
415 def set(self, name, value):
416 """Set the value of an item 418 If the item already exists it is silently replaced; the types 425 value : any supported type 426 Value of item; may be a scalar or array 428 return _propertyContainerSet(self, name, value, self.
_typeMenu)
430 def add(self, name, value):
431 """Append one or more values to a given item, which need not exist 433 If the item exists then the new value(s) are appended; 434 otherwise it is like calling `set` 440 value : any supported type 441 Value of item; may be a scalar or array 445 If ``value`` is an `lsst.daf.base.PropertySet` or 446 `lsst.daf.base.PropertyList` then ``value`` replaces 447 the existing value. Also the item is added as a live 448 reference, so updating ``value`` will update this container 453 lsst::pex::exceptions::TypeError 454 Raised if the type of `value` is incompatible with the existing 457 return _propertyContainerAdd(self, name, value, self.
_typeMenu)
460 """Update the current container with the supplied additions. 464 addition : `collections.abc.Mapping` or `PropertySet` 465 The content to merge into the current container. 469 If the supplied parameter is a `PropertySet` then the 470 `PropertySet.combine` method will be used. If the supplied parameter 471 is a `collections.abc.Mapping` each item will be copied out of the 472 mapping and value assigned using `PropertySet.set`, overwriting 475 if isinstance(addition, PropertySet):
476 self.combine(addition)
478 for k, v
in addition.items():
482 """Returns a (possibly nested) dictionary with all properties. 487 Dictionary with all names and values (no comments). 491 for name
in self.names():
492 v = _propertyContainerGet(self, name, returnStyle=ReturnStyle.AUTO)
494 if isinstance(v, PropertySet):
495 d[name] = PropertySet.toDict(v)
504 if len(self) != len(other):
508 if _propertyContainerGet(self, name, returnStyle=ReturnStyle.AUTO) != \
509 _propertyContainerGet(other, name, returnStyle=ReturnStyle.AUTO):
511 if self.typeOf(name) != other.typeOf(name):
519 for itemName
in self:
520 ps.copy(itemName, self, itemName)
524 result = self.deepCopy()
525 memo[
id(self)] = result
529 """Determines if the name is found at the top level hierarchy 534 Does not use `PropertySet.exists()`` because that includes support 535 for "."-delimited names. This method is consistent with the 536 items returned from ``__iter__``. 538 return name
in self.names(topLevelOnly=
True)
541 """Assigns the supplied value to the container. 546 Name of item to update. 547 value : Value to assign 548 Can be any value supported by the container's ``set()`` 549 method. `~collections.abc.Mapping` are converted to 550 `PropertySet` before assignment. 554 Uses `PropertySet.set`, overwriting any previous value. 556 if isinstance(value, Mapping):
559 for k, v
in value.items():
562 self.
set(name, value)
565 """Returns a scalar item from the container. 569 Uses `PropertySet.getScalar` to guarantee that a single value 578 raise KeyError(f
"{name} not present in dict")
581 return self.toString()
584 return self.nameCount(topLevelOnly=
True)
587 for n
in self.names(topLevelOnly=
True):
591 return KeysView(self)
605 _typeMenu = {bool:
"Bool",
609 DateTime:
"DateTime",
610 PropertySet:
"PropertySet",
611 PropertyList:
"PropertySet",
615 COMMENTSUFFIX =
"#COMMENT" 616 """Special suffix used to indicate that a named item being assigned 617 using dict syntax is referring to a comment, not value.""" 619 def get(self, name, default=None):
620 """Return an item as a scalar, else default. 622 Identical to `getScalar` except that a default value is returned 623 if the requested key is not present. If an array item is requested 624 the final value in the array will be returned. 630 default : `object`, optional 631 Default value to use if the named item is not present. 635 value : any type supported by container 636 Single value of any type supported by the container, else the 637 default value if the requested item is not present in the 638 container. For array items the most recently added value is 642 return _propertyContainerGet(self, name, returnStyle=ReturnStyle.SCALAR)
647 """Return an item as a list. 656 values : `list` of values 657 The contents of the item, guaranteed to be returned as a `list.` 662 Raised if the item does not exist. 664 return _propertyContainerGet(self, name, returnStyle=ReturnStyle.ARRAY)
667 """Return an item as a scalar 669 If the item has more than one value then the last value is returned. 679 Value stored in the item. If the item refers to an array the 680 most recently added value is returned. 685 Raised if the item does not exist. 687 return _propertyContainerGet(self, name, returnStyle=ReturnStyle.SCALAR)
689 def set(self, name, value, comment=None):
690 """Set the value of an item 692 If the item already exists it is silently replaced; the types 699 value : any supported type 700 Value of item; may be a scalar or array 703 if comment
is not None:
705 return _propertyContainerSet(self, name, value, self.
_typeMenu, *args)
707 def add(self, name, value, comment=None):
708 """Append one or more values to a given item, which need not exist 710 If the item exists then the new value(s) are appended; 711 otherwise it is like calling `set` 717 value : any supported type 718 Value of item; may be a scalar or array 722 If `value` is an `lsst.daf.base.PropertySet` items are added 723 using dotted names (e.g. if name="a" and value contains 724 an item "b" which is another PropertySet and contains an 725 item "c" which is numeric or string, then the value of "c" 726 is added as "a.b.c", appended to the existing values of 727 "a.b.c" if any (in which case the types must be compatible). 731 lsst::pex::exceptions::TypeError 732 Raise if the type of ``value`` is incompatible with the existing 736 if comment
is not None:
738 return _propertyContainerAdd(self, name, value, self.
_typeMenu, *args)
741 """Set the comment for an existing entry. 746 Name of the key to receive updated comment. 752 containerType = _propertyContainerElementTypeName(self, name)
753 if self.isArray(name):
757 getattr(self, f
"set{containerType}")(name, value, comment)
760 """Return a list of tuples of name, value, comment for each property 761 in the order that they were inserted. 765 ret : `list` of `tuple` 766 Tuples of name, value, comment for each property in the order 767 in which they were inserted. 769 orderedNames = self.getOrderedNames()
771 for name
in orderedNames:
772 if self.isArray(name):
773 values = _propertyContainerGet(self, name, returnStyle=ReturnStyle.AUTO)
775 ret.append((name, v, self.getComment(name)))
777 ret.append((name, _propertyContainerGet(self, name, returnStyle=ReturnStyle.AUTO),
778 self.getComment(name)))
782 """Return an ordered dictionary with all properties in the order that 788 Ordered dictionary with all properties in the order that they 789 were inserted. Comments are not included. 793 As of Python 3.6 dicts retain their insertion order. 797 d[name] = _propertyContainerGet(self, name, returnStyle=ReturnStyle.AUTO)
801 toDict = toOrderedDict
807 if not PropertySet.__eq__(self, other):
811 if self.getComment(name) != other.getComment(name):
819 for itemName
in self:
820 pl.copy(itemName, self, itemName)
824 result = self.deepCopy()
825 memo[
id(self)] = result
829 for n
in self.getOrderedNames():
833 """Assigns the supplied value to the container. 838 Name of item to update. If the name ends with 839 `PropertyList.COMMENTSUFFIX`, the comment is updated rather 841 value : Value to assign 842 Can be any value supported by the container's ``set()`` 843 method. `~collections.abc.Mapping` are converted to 844 `PropertySet` before assignment. 848 Uses `PropertySet.set`, overwriting any previous value. 854 if isinstance(value, Mapping):
857 for k, v
in value.items():
860 self.
set(name, value)
def __contains__(self, name)
def add(self, name, value, comment=None)
def set(self, name, value, comment=None)
def __deepcopy__(self, memo)
def get(self, name, default=None)
def set(self, name, value)
def __setitem__(self, name, value)
def add(self, name, value)
def __getitem__(self, name)
def getPropertySetState(container, asLists=False)
def setComment(self, name, comment)
def __setitem__(self, name, value)
def getScalar(self, name)
def setPropertyListState(container, state)
def format(config, name=None, writeSourceLine=True, prefix="", verbose=False)
def __deepcopy__(self, memo)
def getPropertyListState(container, asLists=False)
def setPropertySetState(container, state)
def __delitem__(self, name)
def get(self, name, default=None)
def getScalar(self, name)
def update(self, addition)