25 __all__ = [
"getstate",
"setstate"]
33 from .propertySet
import PropertySet
34 from .propertyList
import PropertyList
37 from ..dateTime
import DateTime
46 def _propertyContainerElementTypeName(container, name):
47 """Return name of the type of a particular element""" 48 t = container.typeOf(name)
49 for checkType
in (
"Bool",
"Short",
"Int",
"Long",
"LongLong",
"Float",
"Double",
"String",
"DateTime"):
50 if t == getattr(container,
"TYPE_" + checkType):
55 def _propertyContainerGet(container, name, returnStyle):
56 """Get a value of unknown type as a scalar or array 60 container : ``lsst.daf.base.PropertySet`` or ``lsst.daf.base.PropertyList`` 61 Container from which to get the value 64 returnStyle : ``ReturnStyle`` 65 Control whether numeric or string data is returned as an array 66 or scalar (the other types, ``PropertyList``, ``PropertySet`` 67 and ``PersistablePtr``, are always returned as a scalar): 68 - ReturnStyle.ARRAY: return numeric or string data types 69 as an array of values. 70 - ReturnStyle.SCALAR: return numeric or string data types 71 as a single value; if the item has multiple values then 72 return the last value. 73 - ReturnStyle.AUTO: (deprecated) return numeric or string data 74 as a scalar if there is just one item, or as an array 77 if not container.exists(name):
79 if returnStyle
not in ReturnStyle:
80 raise ValueError(
"returnStyle {} must be a ReturnStyle".format(returnStyle))
82 elemType = _propertyContainerElementTypeName(container, name)
84 value = getattr(container,
"getArray" + elemType)(name)
85 if returnStyle == ReturnStyle.ARRAY
or (returnStyle == ReturnStyle.AUTO
and len(value) > 1):
90 return container.getAsPropertyListPtr(name)
93 if container.typeOf(name) == container.TYPE_PropertySet:
94 return container.getAsPropertySetPtr(name)
96 return container.getAsPersistablePtr(name)
102 def _guessIntegerType(container, name, value):
103 """Given an existing container and name, determine the type 104 that should be used for the supplied value. The supplied value 105 is assumed to be a scalar. 107 On Python 3 all ints are LongLong but we need to be able to store them 108 in Int containers if that is what is being used (testing for truncation). 109 Int is assumed to mean 32bit integer (2147483647 to -2147483648). 111 If there is no pre-existing value we have to decide what to do. For now 112 we pick Int if the value is less than maxsize. 114 Returns None if the value supplied is a bool or not an integral value. 122 if isinstance(value, bool):
125 if isinstance(value, numbers.Integral):
127 containerType = _propertyContainerElementTypeName(container, name)
131 if value <= maxInt
and value >= minInt:
136 if containerType ==
"Int":
142 elif containerType ==
"LongLong":
147 def _propertyContainerSet(container, name, value, typeMenu, *args):
148 """Set a single Python value of unknown type""" 149 if hasattr(value,
"__iter__")
and not isinstance(value, str):
155 setType = _guessIntegerType(container, name, exemplar)
157 if setType
is not None or t
in typeMenu:
159 setType = typeMenu[t]
160 return getattr(container,
"set" + setType)(name, value, *args)
162 for checkType
in typeMenu:
163 if isinstance(exemplar, checkType):
164 return getattr(container,
"set" + typeMenu[checkType])(name, value, *args)
168 def _propertyContainerAdd(container, name, value, typeMenu, *args):
169 """Add a single Python value of unknown type""" 170 if hasattr(value,
"__iter__"):
176 addType = _guessIntegerType(container, name, exemplar)
178 if addType
is not None or t
in typeMenu:
180 addType = typeMenu[t]
181 return getattr(container,
"add" + addType)(name, value, *args)
183 for checkType
in typeMenu:
184 if isinstance(exemplar, checkType):
185 return getattr(container,
"add" + typeMenu[checkType])(name, value, *args)
190 return [(name, _propertyContainerElementTypeName(self, name),
191 _propertyContainerGet(self, name, returnStyle=ReturnStyle.AUTO),
192 self.getComment(name))
for name
in self.getOrderedNames()]
196 for name, elemType, value, comment
in state:
197 getattr(self,
"set" + elemType)(name, value, comment)
204 _typeMenu = {bool:
"Bool",
207 DateTime:
"DateTime",
208 PropertySet:
"PropertySet",
209 PropertyList:
"PropertySet",
215 _typeMenu[unicode] =
"String" 220 """Return an item as a scalar or array 222 Return an array if the item is of numeric or string type and has 223 more than one value, otherwise return a scalar. 225 .. deprecated:: 20180-06 226 `get` is superseded by `getArray` or `getScalar` 235 lsst.pex.exceptions.NotFoundError 236 If the item does not exist. 238 warnings.warn(
"Use getArray or getScalar instead", DeprecationWarning, stacklevel=2)
239 return _propertyContainerGet(self, name, returnStyle=ReturnStyle.AUTO)
242 """Return an item as an array if the item is numeric or string 244 If the item is a ``PropertySet``, ``PropertyList`` or 245 ``lsst.daf.base.PersistablePtr`` then return the item as a scalar. 254 lsst.pex.exceptions.NotFoundError 255 If the item does not exist. 257 return _propertyContainerGet(self, name, returnStyle=ReturnStyle.ARRAY)
260 """Return an item as a scalar 262 If the item has more than one value then the last value is returned 271 lsst.pex.exceptions.NotFoundError 272 If the item does not exist. 274 return _propertyContainerGet(self, name, returnStyle=ReturnStyle.SCALAR)
276 def set(self, name, value):
277 """Set the value of an item 279 If the item already exists it is silently replaced; the types 286 value : any supported type 287 Value of item; may be a scalar or array 289 return _propertyContainerSet(self, name, value, self.
_typeMenu)
291 def add(self, name, value):
292 """Append one or more values to a given item, which need not exist 294 If the item exists then the new value(s) are appended; 295 otherwise it is like calling `set` 301 value : any supported type 302 Value of item; may be a scalar or array 306 If `value` is an ``lsst.daf.base.PropertySet`` or 307 ``lsst.daf.base.PropertyList`` then `value` replaces 308 the existing value. Also the item is added as a live 309 reference, so updating `value` will update this container 314 lsst::pex::exceptions::TypeError 315 If the type of `value` is incompatible with the existing value 318 return _propertyContainerAdd(self, name, value, self.
_typeMenu)
321 """Returns a (possibly nested) dictionary with all properties. 325 for name
in self.names():
326 v = _propertyContainerGet(self, name, returnStyle=ReturnStyle.AUTO)
328 if isinstance(v, PropertySet):
329 d[name] = PropertySet.toDict(v)
338 _typeMenu = {bool:
"Bool",
342 DateTime:
"DateTime",
343 PropertySet:
"PropertySet",
344 PropertyList:
"PropertySet",
350 _typeMenu[unicode] =
"String" 355 """Return an item as a scalar or array 357 Return an array if the item has more than one value, 358 otherwise return a scalar. 360 .. deprecated:: 20180-06 361 `get` is superseded by `getArray` or `getScalar` 370 lsst.pex.exceptions.NotFoundError 371 If the item does not exist. 373 warnings.warn(
"Use getArray or getScalar instead", DeprecationWarning, stacklevel=2)
374 return _propertyContainerGet(self, name, returnStyle=ReturnStyle.AUTO)
377 """Return an item as an array 386 lsst.pex.exceptions.NotFoundError 387 If the item does not exist. 389 return _propertyContainerGet(self, name, returnStyle=ReturnStyle.ARRAY)
392 """Return an item as a scalar 394 If the item has more than one value then the last value is returned 403 lsst.pex.exceptions.NotFoundError 404 If the item does not exist. 406 return _propertyContainerGet(self, name, returnStyle=ReturnStyle.SCALAR)
408 def set(self, name, value, comment=None):
409 """Set the value of an item 411 If the item already exists it is silently replaced; the types 418 value : any supported type 419 Value of item; may be a scalar or array 422 if comment
is not None:
424 return _propertyContainerSet(self, name, value, self.
_typeMenu, *args)
426 def add(self, name, value, comment=None):
427 """Append one or more values to a given item, which need not exist 429 If the item exists then the new value(s) are appended; 430 otherwise it is like calling `set` 436 value : any supported type 437 Value of item; may be a scalar or array 441 If `value` is an ``lsst.daf.base.PropertySet`` items are added 442 using dotted names (e.g. if name="a" and value contains 443 an item "b" which is another PropertySet and contains an 444 item "c" which is numeric or string, then the value of "c" 445 is added as "a.b.c", appended to the existing values of 446 "a.b.c" if any (in which case the types must be compatible). 450 lsst::pex::exceptions::TypeError 451 If the type of `value` is incompatible with the existing value 455 if comment
is not None:
457 return _propertyContainerAdd(self, name, value, self.
_typeMenu, *args)
460 orderedNames = self.getOrderedNames()
462 for name
in orderedNames:
463 if self.isArray(name):
464 values = _propertyContainerGet(self, name, returnStyle=ReturnStyle.AUTO)
466 ret.append((name, v, self.getComment(name)))
468 ret.append((name, _propertyContainerGet(self, name, returnStyle=ReturnStyle.AUTO),
469 self.getComment(name)))
473 """Return an ordered dictionary with all properties in the order that 476 from collections
import OrderedDict
479 for name
in self.getOrderedNames():
480 d[name] = _propertyContainerGet(self, name, returnStyle=ReturnStyle.AUTO)
def setstate(self, state)
def add(self, name, value, comment=None)
def set(self, name, value, comment=None)
def set(self, name, value)
def add(self, name, value)
def getScalar(self, name)
def getScalar(self, name)