25 __all__ = [
"getPropertySetState",
"getPropertyListState",
"setPropertySetState",
"setPropertyListState"]
30 from collections.abc
import Mapping, KeysView
34 from .propertySet
import PropertySet
35 from .propertyList
import PropertyList
36 from ..dateTime
import DateTime
40 """Get the state of a PropertySet in a form that can be pickled. 44 container : `PropertySet` 45 The property container. 46 asLists : `bool`, optional 47 If False, the default, `tuple` will be used for the contents. If true 48 a `list` will be used. 49 names : `list` or `tuple` 50 Override the default list of names with this subset. 54 state : `list` of `tuple` or `list` of `list` 55 The state, as a list of tuples (or lists), each of which contains 56 the following 3 items: 57 - name (a `str`): the name of the item 58 - elementTypeName (a `str`): the suffix of a ``setX`` method name 59 which is appropriate for the data type. For example integer 60 data has ``elementTypeName="Int"` which corresponds to 61 the ``setInt`` method. 62 - value: the data for the item, in a form compatible 63 with the set method named by ``elementTypeName`` 70 names = container.names(topLevelOnly=
True)
71 sequence = list
if asLists
else tuple
72 return [sequence((name, _propertyContainerElementTypeName(container, name),
73 _propertyContainerGet(container, name, returnStyle=ReturnStyle.AUTO)))
78 """Get the state of a PropertyList in a form that can be pickled. 82 container : `PropertyList` 83 The property container. 84 asLists : `bool`, optional 85 If False, the default, `tuple` will be used for the contents. If true 86 a `list` will be used. 90 state : `list` of `tuple` or `list` of `list` 91 The state, as a list of tuples (or lists), each of which contains 92 the following 4 items: 93 - name (a `str`): the name of the item 94 - elementTypeName (a `str`): the suffix of a ``setX`` method name 95 which is appropriate for the data type. For example integer 96 data has ``elementTypeName="Int"` which corresponds to 97 the ``setInt`` method. 98 - value: the data for the item, in a form compatible 99 with the set method named by ``elementTypeName`` 100 - comment (a `str`): the comment. This item is only present 101 if ``container`` is a PropertyList. 103 sequence = list
if asLists
else tuple
104 return [sequence((name, _propertyContainerElementTypeName(container, name),
105 _propertyContainerGet(container, name, returnStyle=ReturnStyle.AUTO),
106 container.getComment(name)))
107 for name
in container.getOrderedNames()]
111 """Restore the state of a PropertySet, in place. 115 container : `PropertySet` 116 The property container whose state is to be restored. 117 It should be empty to start with and is updated in place. 119 The state, as returned by `getPropertySetState` 121 for name, elemType, value
in state:
122 if elemType
is not None:
123 getattr(container,
"set" + elemType)(name, value)
125 raise ValueError(f
"Unrecognized values for state restoration: ({name}, {elemType}, {value})")
129 """Restore the state of a PropertyList, in place. 133 container : `PropertyList` 134 The property container whose state is to be restored. 135 It should be empty to start with and is updated in place. 137 The state, as returned by ``getPropertyListState`` 139 for name, elemType, value, comment
in state:
140 getattr(container,
"set" + elemType)(name, value, comment)
149 def _propertyContainerElementTypeName(container, name):
150 """Return name of the type of a particular element""" 152 t = container.typeOf(name)
157 for checkType
in (
"Bool",
"Short",
"Int",
"Long",
"LongLong",
"Float",
"Double",
"String",
"DateTime",
159 if t == getattr(container,
"TYPE_" + checkType):
164 def _propertyContainerGet(container, name, returnStyle):
165 """Get a value of unknown type as a scalar or array 169 container : `lsst.daf.base.PropertySet` or `lsst.daf.base.PropertyList` 170 Container from which to get the value 173 returnStyle : `ReturnStyle` 174 Control whether numeric or string data is returned as an array 175 or scalar (the other types, ``PropertyList``, ``PropertySet`` 176 and ``PersistablePtr``, are always returned as a scalar): 177 - ReturnStyle.ARRAY: return numeric or string data types 178 as an array of values. 179 - ReturnStyle.SCALAR: return numeric or string data types 180 as a single value; if the item has multiple values then 181 return the last value. 182 - ReturnStyle.AUTO: (deprecated) return numeric or string data 183 as a scalar if there is just one item, or as an array 189 The specified key does not exist in the container. 191 The value retrieved is of an unexpected type. 193 The value for ``returnStyle`` is not correct. 195 if not container.exists(name):
196 raise KeyError(name +
" not found")
197 if returnStyle
not in ReturnStyle:
198 raise ValueError(
"returnStyle {} must be a ReturnStyle".format(returnStyle))
200 elemType = _propertyContainerElementTypeName(container, name)
201 if elemType
and elemType !=
"PropertySet":
202 value = getattr(container,
"getArray" + elemType)(name)
203 if returnStyle == ReturnStyle.ARRAY
or (returnStyle == ReturnStyle.AUTO
and len(value) > 1):
207 if container.isPropertySetPtr(name):
209 return container.getAsPropertyListPtr(name)
211 return container.getAsPropertySetPtr(name)
213 return container.getAsPersistablePtr(name)
216 raise TypeError(
'Unknown PropertySet value type for ' + name)
219 def _guessIntegerType(container, name, value):
220 """Given an existing container and name, determine the type 221 that should be used for the supplied value. The supplied value 222 is assumed to be a scalar. 224 On Python 3 all ints are LongLong but we need to be able to store them 225 in Int containers if that is what is being used (testing for truncation). 226 Int is assumed to mean 32bit integer (2147483647 to -2147483648). 228 If there is no pre-existing value we have to decide what to do. For now 229 we pick Int if the value is less than maxsize. 231 Returns None if the value supplied is a bool or not an integral value. 239 if isinstance(value, bool):
242 if isinstance(value, numbers.Integral):
244 containerType = _propertyContainerElementTypeName(container, name)
248 if value <= maxInt
and value >= minInt:
253 if containerType ==
"Int":
259 elif containerType ==
"LongLong":
264 def _propertyContainerSet(container, name, value, typeMenu, *args):
265 """Set a single Python value of unknown type""" 266 if hasattr(value,
"__iter__")
and not isinstance(value, (str, PropertySet, PropertyList)):
272 setType = _guessIntegerType(container, name, exemplar)
274 if setType
is not None or t
in typeMenu:
276 setType = typeMenu[t]
277 return getattr(container,
"set" + setType)(name, value, *args)
279 for checkType
in typeMenu:
280 if isinstance(exemplar, checkType):
281 return getattr(container,
"set" + typeMenu[checkType])(name, value, *args)
282 raise TypeError(
"Unknown value type for %s: %s" % (name, t))
285 def _propertyContainerAdd(container, name, value, typeMenu, *args):
286 """Add a single Python value of unknown type""" 287 if hasattr(value,
"__iter__"):
293 addType = _guessIntegerType(container, name, exemplar)
295 if addType
is not None or t
in typeMenu:
297 addType = typeMenu[t]
298 return getattr(container,
"add" + addType)(name, value, *args)
300 for checkType
in typeMenu:
301 if isinstance(exemplar, checkType):
302 return getattr(container,
"add" + typeMenu[checkType])(name, value, *args)
303 raise TypeError(
"Unknown value type for %s: %s" % (name, t))
306 def _makePropertySet(state):
307 """Make a `PropertySet` from the state returned by `getPropertySetState` 312 The data returned by `getPropertySetState`. 319 def _makePropertyList(state):
320 """Make a `PropertyList` from the state returned by 321 `getPropertyListState` 326 The data returned by `getPropertySetState`. 337 _typeMenu = {bool:
"Bool",
340 DateTime:
"DateTime",
341 PropertySet:
"PropertySet",
342 PropertyList:
"PropertySet",
346 """Return an item as a scalar or array 348 Return an array if the item is of numeric or string type and has 349 more than one value, otherwise return a scalar. 351 .. deprecated:: 20180-06 352 `get` is superseded by `getArray` or `getScalar` 362 If the item does not exist. 364 warnings.warn(
"Use getArray or getScalar instead", DeprecationWarning, stacklevel=2)
365 return _propertyContainerGet(self, name, returnStyle=ReturnStyle.AUTO)
368 """Return an item as an array if the item is numeric or string 370 If the item is a `PropertySet`, `PropertyList` or 371 `lsst.daf.base.PersistablePtr` then return the item as a scalar. 381 If the item does not exist. 383 return _propertyContainerGet(self, name, returnStyle=ReturnStyle.ARRAY)
386 """Return an item as a scalar 388 If the item has more than one value then the last value is returned 398 If the item does not exist. 400 return _propertyContainerGet(self, name, returnStyle=ReturnStyle.SCALAR)
402 def set(self, name, value):
403 """Set the value of an item 405 If the item already exists it is silently replaced; the types 412 value : any supported type 413 Value of item; may be a scalar or array 415 return _propertyContainerSet(self, name, value, self.
_typeMenu)
417 def add(self, name, value):
418 """Append one or more values to a given item, which need not exist 420 If the item exists then the new value(s) are appended; 421 otherwise it is like calling `set` 427 value : any supported type 428 Value of item; may be a scalar or array 432 If ``value`` is an `lsst.daf.base.PropertySet` or 433 `lsst.daf.base.PropertyList` then ``value`` replaces 434 the existing value. Also the item is added as a live 435 reference, so updating ``value`` will update this container 440 lsst::pex::exceptions::TypeError 441 If the type of `value` is incompatible with the existing value 444 return _propertyContainerAdd(self, name, value, self.
_typeMenu)
447 """Returns a (possibly nested) dictionary with all properties. 452 Dictionary with all names and values (no comments). 456 for name
in self.names():
457 v = _propertyContainerGet(self, name, returnStyle=ReturnStyle.AUTO)
459 if isinstance(v, PropertySet):
460 d[name] = PropertySet.toDict(v)
466 if type(self) != type(other):
469 if len(self) != len(other):
473 if _propertyContainerGet(self, name, returnStyle=ReturnStyle.AUTO) != \
474 _propertyContainerGet(other, name, returnStyle=ReturnStyle.AUTO):
476 if self.typeOf(name) != other.typeOf(name):
486 return _makePropertySet(state)
490 return name
in self.names(topLevelOnly=
True)
493 if isinstance(value, Mapping):
496 for k, v
in value.items():
499 self.
set(name, value)
505 raise KeyError(f
"{name} not present in dict")
508 return self.toString()
511 return self.nameCount(topLevelOnly=
True)
514 for n
in self.names(topLevelOnly=
True):
518 return KeysView(self)
532 _typeMenu = {bool:
"Bool",
536 DateTime:
"DateTime",
537 PropertySet:
"PropertySet",
538 PropertyList:
"PropertySet",
541 COMMENTSUFFIX =
"#COMMENT" 544 """Return an item as a scalar or array 546 Return an array if the item has more than one value, 547 otherwise return a scalar. 549 .. deprecated:: 20180-06 550 `get` is superseded by `getArray` or `getScalar` 560 If the item does not exist. 562 warnings.warn(
"Use getArray or getScalar instead", DeprecationWarning, stacklevel=2)
563 return _propertyContainerGet(self, name, returnStyle=ReturnStyle.AUTO)
566 """Return an item as an array 576 If the item does not exist. 578 return _propertyContainerGet(self, name, returnStyle=ReturnStyle.ARRAY)
581 """Return an item as a scalar 583 If the item has more than one value then the last value is returned 593 If the item does not exist. 595 return _propertyContainerGet(self, name, returnStyle=ReturnStyle.SCALAR)
597 def set(self, name, value, comment=None):
598 """Set the value of an item 600 If the item already exists it is silently replaced; the types 607 value : any supported type 608 Value of item; may be a scalar or array 611 if comment
is not None:
613 return _propertyContainerSet(self, name, value, self.
_typeMenu, *args)
615 def add(self, name, value, comment=None):
616 """Append one or more values to a given item, which need not exist 618 If the item exists then the new value(s) are appended; 619 otherwise it is like calling `set` 625 value : any supported type 626 Value of item; may be a scalar or array 630 If `value` is an `lsst.daf.base.PropertySet` items are added 631 using dotted names (e.g. if name="a" and value contains 632 an item "b" which is another PropertySet and contains an 633 item "c" which is numeric or string, then the value of "c" 634 is added as "a.b.c", appended to the existing values of 635 "a.b.c" if any (in which case the types must be compatible). 639 lsst::pex::exceptions::TypeError 640 If the type of `value` is incompatible with the existing value 644 if comment
is not None:
646 return _propertyContainerAdd(self, name, value, self.
_typeMenu, *args)
649 """Set the comment for an existing entry. 654 Name of the key to receive updated comment. 660 containerType = _propertyContainerElementTypeName(self, name)
661 if self.isArray(name):
665 getattr(self, f
"set{containerType}")(name, value, comment)
668 """Return a list of tuples of name, value, comment for each property 669 in the order that they were inserted. 673 ret : `list` of `tuple` 674 Tuples of name, value, comment for each property in the order 675 in which they were inserted. 677 orderedNames = self.getOrderedNames()
679 for name
in orderedNames:
680 if self.isArray(name):
681 values = _propertyContainerGet(self, name, returnStyle=ReturnStyle.AUTO)
683 ret.append((name, v, self.getComment(name)))
685 ret.append((name, _propertyContainerGet(self, name, returnStyle=ReturnStyle.AUTO),
686 self.getComment(name)))
690 """Return an ordered dictionary with all properties in the order that 695 d : `~collections.OrderedDict` 696 Ordered dictionary with all properties in the order that they 697 were inserted. Comments are not included. 699 from collections
import OrderedDict
702 for name
in self.getOrderedNames():
703 d[name] = _propertyContainerGet(self, name, returnStyle=ReturnStyle.AUTO)
707 if not super(PropertySet, self).
__eq__(other):
711 if self.getComment(name) != other.getComment(name):
721 return _makePropertyList(state)
724 for n
in self.getOrderedNames():
732 if isinstance(value, Mapping):
735 for k, v
in value.items():
738 self.
set(name, value)
def __contains__(self, name)
def add(self, name, value, comment=None)
def set(self, name, value, comment=None)
def set(self, name, value)
def __setitem__(self, name, value)
def add(self, name, value)
def getPropertySetState(container, asLists=False, names=None)
def setComment(self, name, comment)
def __setitem__(self, name, value)
def getScalar(self, name)
def setPropertyListState(container, state)
def getPropertyListState(container, asLists=False)
def setPropertySetState(container, state)
def __delitem__(self, name)
def getScalar(self, name)