25 __all__ = [
"getPropertySetState",
"getPropertyListState",
"setPropertySetState",
"setPropertyListState"]
30 from collections.abc
import Mapping, KeysView
36 from .propertySet
import PropertySet
37 from .propertyList
import PropertyList
38 from ..dateTime
import DateTime
42 """Get the state of a PropertySet in a form that can be pickled. 46 container : `PropertySet` 47 The property container. 48 asLists : `bool`, optional 49 If False, the default, `tuple` will be used for the contents. If true 50 a `list` will be used. 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`` 65 names = container.names(topLevelOnly=
True)
66 sequence = list
if asLists
else tuple
67 return [sequence((name, _propertyContainerElementTypeName(container, name),
68 _propertyContainerGet(container, name, returnStyle=ReturnStyle.AUTO)))
73 """Get the state of a PropertyList in a form that can be pickled. 77 container : `PropertyList` 78 The property container. 79 asLists : `bool`, optional 80 If False, the default, `tuple` will be used for the contents. If true 81 a `list` will be used. 85 state : `list` of `tuple` or `list` of `list` 86 The state, as a list of tuples (or lists), each of which contains 87 the following 4 items: 88 - name (a `str`): the name of the item 89 - elementTypeName (a `str`): the suffix of a ``setX`` method name 90 which is appropriate for the data type. For example integer 91 data has ``elementTypeName="Int"` which corresponds to 92 the ``setInt`` method. 93 - value: the data for the item, in a form compatible 94 with the set method named by ``elementTypeName`` 95 - comment (a `str`): the comment. This item is only present 96 if ``container`` is a PropertyList. 98 sequence = list
if asLists
else tuple
99 return [sequence((name, _propertyContainerElementTypeName(container, name),
100 _propertyContainerGet(container, name, returnStyle=ReturnStyle.AUTO),
101 container.getComment(name)))
102 for name
in container.getOrderedNames()]
106 """Restore the state of a PropertySet, in place. 110 container : `PropertySet` 111 The property container whose state is to be restored. 112 It should be empty to start with and is updated in place. 114 The state, as returned by `getPropertySetState` 116 for name, elemType, value
in state:
117 if elemType
is not None:
118 getattr(container,
"set" + elemType)(name, value)
120 raise ValueError(f
"Unrecognized values for state restoration: ({name}, {elemType}, {value})")
124 """Restore the state of a PropertyList, in place. 128 container : `PropertyList` 129 The property container whose state is to be restored. 130 It should be empty to start with and is updated in place. 132 The state, as returned by ``getPropertyListState`` 134 for name, elemType, value, comment
in state:
135 getattr(container,
"set" + elemType)(name, value, comment)
144 def _propertyContainerElementTypeName(container, name):
145 """Return name of the type of a particular element""" 147 t = container.typeOf(name)
148 except LookupError
as e:
151 raise KeyError(str(e))
152 for checkType
in (
"Bool",
"Short",
"Int",
"Long",
"LongLong",
"Float",
"Double",
"String",
"DateTime",
153 "PropertySet",
"Undef"):
154 if t == getattr(container,
"TYPE_" + checkType):
159 def _propertyContainerGet(container, name, returnStyle):
160 """Get a value of unknown type as a scalar or array 164 container : `lsst.daf.base.PropertySet` or `lsst.daf.base.PropertyList` 165 Container from which to get the value 168 returnStyle : `ReturnStyle` 169 Control whether numeric or string data is returned as an array 170 or scalar (the other types, ``PropertyList``, ``PropertySet`` 171 and ``PersistablePtr``, are always returned as a scalar): 172 - ReturnStyle.ARRAY: return numeric or string data types 173 as an array of values. 174 - ReturnStyle.SCALAR: return numeric or string data types 175 as a single value; if the item has multiple values then 176 return the last value. 177 - ReturnStyle.AUTO: (deprecated) return numeric or string data 178 as a scalar if there is just one item, or as an array 184 The specified key does not exist in the container. 186 The value retrieved is of an unexpected type. 188 The value for ``returnStyle`` is not correct. 190 if not container.exists(name):
191 raise KeyError(name +
" not found")
192 if returnStyle
not in ReturnStyle:
193 raise ValueError(
"returnStyle {} must be a ReturnStyle".format(returnStyle))
195 elemType = _propertyContainerElementTypeName(container, name)
196 if elemType
and elemType !=
"PropertySet":
197 value = getattr(container,
"getArray" + elemType)(name)
198 if returnStyle == ReturnStyle.ARRAY
or (returnStyle == ReturnStyle.AUTO
and len(value) > 1):
202 if container.isPropertySetPtr(name):
204 return container.getAsPropertyListPtr(name)
206 return container.getAsPropertySetPtr(name)
208 return container.getAsPersistablePtr(name)
211 raise TypeError(
'Unknown PropertySet value type for ' + name)
214 def _guessIntegerType(container, name, value):
215 """Given an existing container and name, determine the type 216 that should be used for the supplied value. The supplied value 217 is assumed to be a scalar. 219 On Python 3 all ints are LongLong but we need to be able to store them 220 in Int containers if that is what is being used (testing for truncation). 221 Int is assumed to mean 32bit integer (2147483647 to -2147483648). 223 If there is no pre-existing value we have to decide what to do. For now 224 we pick Int if the value is less than maxsize. 226 Returns None if the value supplied is a bool or not an integral value. 234 if isinstance(value, bool):
237 if isinstance(value, numbers.Integral):
239 containerType = _propertyContainerElementTypeName(container, name)
243 if value <= maxInt
and value >= minInt:
248 if containerType ==
"Int":
254 elif containerType ==
"LongLong":
259 def _propertyContainerSet(container, name, value, typeMenu, *args):
260 """Set a single Python value of unknown type""" 261 if hasattr(value,
"__iter__")
and not isinstance(value, (str, PropertySet, PropertyList)):
267 setType = _guessIntegerType(container, name, exemplar)
269 if setType
is not None or t
in typeMenu:
271 setType = typeMenu[t]
272 return getattr(container,
"set" + setType)(name, value, *args)
274 for checkType
in typeMenu:
275 if (checkType
is None and exemplar
is None)
or \
276 (checkType
is not None and isinstance(exemplar, checkType)):
277 return getattr(container,
"set" + typeMenu[checkType])(name, value, *args)
278 raise TypeError(
"Unknown value type for key '%s': %s" % (name, t))
281 def _propertyContainerAdd(container, name, value, typeMenu, *args):
282 """Add a single Python value of unknown type""" 283 if hasattr(value,
"__iter__"):
289 addType = _guessIntegerType(container, name, exemplar)
291 if addType
is not None or t
in typeMenu:
293 addType = typeMenu[t]
294 return getattr(container,
"add" + addType)(name, value, *args)
296 for checkType
in typeMenu:
297 if (checkType
is None and exemplar
is None)
or \
298 (checkType
is not None and isinstance(exemplar, checkType)):
299 return getattr(container,
"add" + typeMenu[checkType])(name, value, *args)
300 raise TypeError(
"Unknown value type for key '%s': %s" % (name, t))
303 def _makePropertySet(state):
304 """Make a `PropertySet` from the state returned by `getPropertySetState` 309 The data returned by `getPropertySetState`. 316 def _makePropertyList(state):
317 """Make a `PropertyList` from the state returned by 318 `getPropertyListState` 323 The data returned by `getPropertySetState`. 334 _typeMenu = {bool:
"Bool",
337 DateTime:
"DateTime",
338 PropertySet:
"PropertySet",
339 PropertyList:
"PropertySet",
344 """Return an item as a scalar or array 346 Return an array if the item is of numeric or string type and has 347 more than one value, otherwise return a scalar. 349 .. deprecated:: 20180-06 350 `get` is superseded by `getArray` or `getScalar` 360 If the item does not exist. 362 warnings.warn(
"Use getArray or getScalar instead", DeprecationWarning, stacklevel=2)
363 return _propertyContainerGet(self, name, returnStyle=ReturnStyle.AUTO)
366 """Return an item as an array if the item is numeric or string 368 If the item is a `PropertySet`, `PropertyList` or 369 `lsst.daf.base.PersistablePtr` then return the item as a scalar. 379 If the item does not exist. 381 return _propertyContainerGet(self, name, returnStyle=ReturnStyle.ARRAY)
384 """Return an item as a scalar 386 If the item has more than one value then the last value is returned 396 If the item does not exist. 398 return _propertyContainerGet(self, name, returnStyle=ReturnStyle.SCALAR)
400 def set(self, name, value):
401 """Set the value of an item 403 If the item already exists it is silently replaced; the types 410 value : any supported type 411 Value of item; may be a scalar or array 413 return _propertyContainerSet(self, name, value, self.
_typeMenu)
415 def add(self, name, value):
416 """Append one or more values to a given item, which need not exist 418 If the item exists then the new value(s) are appended; 419 otherwise it is like calling `set` 425 value : any supported type 426 Value of item; may be a scalar or array 430 If ``value`` is an `lsst.daf.base.PropertySet` or 431 `lsst.daf.base.PropertyList` then ``value`` replaces 432 the existing value. Also the item is added as a live 433 reference, so updating ``value`` will update this container 438 lsst::pex::exceptions::TypeError 439 If the type of `value` is incompatible with the existing value 442 return _propertyContainerAdd(self, name, value, self.
_typeMenu)
445 """Returns a (possibly nested) dictionary with all properties. 450 Dictionary with all names and values (no comments). 454 for name
in self.names():
455 v = _propertyContainerGet(self, name, returnStyle=ReturnStyle.AUTO)
457 if isinstance(v, PropertySet):
458 d[name] = PropertySet.toDict(v)
464 if type(self) != type(other):
467 if len(self) != len(other):
471 if _propertyContainerGet(self, name, returnStyle=ReturnStyle.AUTO) != \
472 _propertyContainerGet(other, name, returnStyle=ReturnStyle.AUTO):
474 if self.typeOf(name) != other.typeOf(name):
482 for itemName
in self:
483 ps.copy(itemName, self, itemName)
487 result = self.deepCopy()
488 memo[id(self)] = result
493 return name
in self.names(topLevelOnly=
True)
496 if isinstance(value, Mapping):
499 for k, v
in value.items():
502 self.
set(name, value)
508 raise KeyError(f
"{name} not present in dict")
511 return self.toString()
514 return self.nameCount(topLevelOnly=
True)
517 for n
in self.names(topLevelOnly=
True):
521 return KeysView(self)
535 _typeMenu = {bool:
"Bool",
539 DateTime:
"DateTime",
540 PropertySet:
"PropertySet",
541 PropertyList:
"PropertySet",
545 COMMENTSUFFIX =
"#COMMENT" 548 """Return an item as a scalar or array 550 Return an array if the item has more than one value, 551 otherwise return a scalar. 553 .. deprecated:: 20180-06 554 `get` is superseded by `getArray` or `getScalar` 564 If the item does not exist. 566 warnings.warn(
"Use getArray or getScalar instead", DeprecationWarning, stacklevel=2)
567 return _propertyContainerGet(self, name, returnStyle=ReturnStyle.AUTO)
570 """Return an item as an array 580 If the item does not exist. 582 return _propertyContainerGet(self, name, returnStyle=ReturnStyle.ARRAY)
585 """Return an item as a scalar 587 If the item has more than one value then the last value is returned 597 If the item does not exist. 599 return _propertyContainerGet(self, name, returnStyle=ReturnStyle.SCALAR)
601 def set(self, name, value, comment=None):
602 """Set the value of an item 604 If the item already exists it is silently replaced; the types 611 value : any supported type 612 Value of item; may be a scalar or array 615 if comment
is not None:
617 return _propertyContainerSet(self, name, value, self.
_typeMenu, *args)
619 def add(self, name, value, comment=None):
620 """Append one or more values to a given item, which need not exist 622 If the item exists then the new value(s) are appended; 623 otherwise it is like calling `set` 629 value : any supported type 630 Value of item; may be a scalar or array 634 If `value` is an `lsst.daf.base.PropertySet` items are added 635 using dotted names (e.g. if name="a" and value contains 636 an item "b" which is another PropertySet and contains an 637 item "c" which is numeric or string, then the value of "c" 638 is added as "a.b.c", appended to the existing values of 639 "a.b.c" if any (in which case the types must be compatible). 643 lsst::pex::exceptions::TypeError 644 If the type of `value` is incompatible with the existing value 648 if comment
is not None:
650 return _propertyContainerAdd(self, name, value, self.
_typeMenu, *args)
653 """Set the comment for an existing entry. 658 Name of the key to receive updated comment. 664 containerType = _propertyContainerElementTypeName(self, name)
665 if self.isArray(name):
669 getattr(self, f
"set{containerType}")(name, value, comment)
672 """Return a list of tuples of name, value, comment for each property 673 in the order that they were inserted. 677 ret : `list` of `tuple` 678 Tuples of name, value, comment for each property in the order 679 in which they were inserted. 681 orderedNames = self.getOrderedNames()
683 for name
in orderedNames:
684 if self.isArray(name):
685 values = _propertyContainerGet(self, name, returnStyle=ReturnStyle.AUTO)
687 ret.append((name, v, self.getComment(name)))
689 ret.append((name, _propertyContainerGet(self, name, returnStyle=ReturnStyle.AUTO),
690 self.getComment(name)))
694 """Return an ordered dictionary with all properties in the order that 700 Ordered dictionary with all properties in the order that they 701 were inserted. Comments are not included. 705 As of Python 3.6 dicts retain their insertion order. 709 d[name] = _propertyContainerGet(self, name, returnStyle=ReturnStyle.AUTO)
713 toDict = toOrderedDict
719 if not PropertySet.__eq__(self, other):
723 if self.getComment(name) != other.getComment(name):
731 for itemName
in self:
732 pl.copy(itemName, self, itemName)
736 result = self.deepCopy()
737 memo[id(self)] = result
741 for n
in self.getOrderedNames():
749 if isinstance(value, Mapping):
752 for k, v
in value.items():
755 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 set(self, name, value)
def __setitem__(self, name, value)
def add(self, name, value)
def getPropertySetState(container, asLists=False)
def setComment(self, name, comment)
def __setitem__(self, name, value)
def getScalar(self, name)
def setPropertyListState(container, state)
def __deepcopy__(self, memo)
def getPropertyListState(container, asLists=False)
def setPropertySetState(container, state)
def __delitem__(self, name)
def getScalar(self, name)