Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DM-29117: Allow dict interface to upgrade integer types #64

Merged
merged 4 commits into from
Mar 12, 2021
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -270,29 +270,34 @@ def _guessIntegerType(container, name, value):
return useType

if isinstance(value, numbers.Integral):

def _choose_int_from_range(int_value, current_type):
print(f"Checking in '{name}' for {int_value} ({current_type})")
timj marked this conversation as resolved.
Show resolved Hide resolved
if int_value <= maxInt and int_value >= minInt and current_type in (None, "Int"):
# Use Int only if in range and either no current type or the
# current type is an Int.
use_type = "Int"
elif int_value >= minLongLong and int_value < 0:
# All large negatives must be LongLong if they did not fit
# in Int clause above.
use_type = "LongLong"
elif int_value >= 0 and int_value <= maxLongLong and current_type in (None, "Int", "LongLong"):
# Larger than Int or already a LongLong
use_type = "LongLong"
elif int_value <= maxU64 and int_value >= minU64:
use_type = "UnsignedLongLong"
else:
raise RuntimeError("Unable to guess integer type for storing out of "
f"range value: {int_value}")
return use_type

try:
containerType = _propertyContainerElementTypeName(container, name)
except LookupError:
# nothing in the container so choose based on size.
if value <= maxInt and value >= minInt:
useType = "Int"
elif value <= maxLongLong and value >= minLongLong:
useType = "LongLong"
elif value <= maxU64 and value >= minU64:
useType = "UnsignedLongLong"
else:
raise RuntimeError("Unable to guess integer type for storing value: %d" % (value,))
useType = _choose_int_from_range(value, None)
else:
if containerType == "Int":
# Always use an Int even if we know it won't fit. The later
# code will trigger OverflowError if appropriate. Setting the
# type to LongLong here will trigger a TypeError instead so
# it's best to trigger a predictable OverflowError.
useType = "Int"
elif containerType == "LongLong":
useType = "LongLong"
elif containerType == "UnsignedLongLong":
useType = "UnsignedLongLong"
useType = _choose_int_from_range(value, containerType)

return useType


Expand Down
30 changes: 30 additions & 0 deletions tests/test_dict.py
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,22 @@ def testDictPropertySet(self):

container["a_property_list"] = self.pl

# Upgrading of integer
key = "upgrade"
container[key] = 1
self.assertEqual(container.typeOf(key), lsst.daf.base.PropertySet.TYPE_Int)
self.assertEqual(container[key], 1)

# Set to 64-bit int value
container[key] = 8589934592
self.assertEqual(container[key], 8589934592)
self.assertEqual(container.typeOf(key), lsst.daf.base.PropertySet.TYPE_LongLong)

# Set to small int again, type should not change
container[key] = 42
self.assertEqual(container[key], 42)
self.assertEqual(container.typeOf(key), lsst.daf.base.PropertySet.TYPE_LongLong)

def testDictPropertyList(self):
container = self.pl
self.assertIn("string", container)
Expand Down Expand Up @@ -196,6 +212,20 @@ def testDictPropertyList(self):
container["dict"] = {"a": 1, "b": 2}
self.assertEqual(container.getScalar("dict.b"), 2)

# Upgrading of integer
key = "upgrade"
container[key] = 1
self.assertEqual(container.typeOf(key), lsst.daf.base.PropertySet.TYPE_Int)
self.assertEqual(container[key], 1)
container[key] = 8589934592
self.assertEqual(container[key], 8589934592)
self.assertEqual(container.typeOf(key), lsst.daf.base.PropertySet.TYPE_LongLong)

# Set to small int again, type should not change
container[key] = 42
self.assertEqual(container[key], 42)
self.assertEqual(container.typeOf(key), lsst.daf.base.PropertySet.TYPE_LongLong)

def testCopyPropertyList(self):
# For PropertyList shallow copy and deep copy are identical
shallow = copy.copy(self.pl)
Expand Down