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-20506: PropertySet: add support for u64 #52

Merged
merged 1 commit into from
Jul 23, 2019
Merged
Show file tree
Hide file tree
Changes from all 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
11 changes: 11 additions & 0 deletions include/lsst/daf/base/PropertySet.h
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,17 @@ class LSST_EXPORT PropertySet {
*/
int64_t getAsInt64(std::string const& name) const;

/**
* Get the last value for an bool/char/short/int/int64_t property name
* (possibly hierarchical).
*
* @param[in] name Property name to examine, possibly hierarchical.
* @return Value as an uint64_t.
* @throws NotFoundError Property does not exist.
* @throws TypeError Value cannot be converted to uint64_t.
*/
uint64_t getAsUInt64(std::string const& name) const;

/**
* Get the last value for any arithmetic property name (possibly
* hierarchical).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,8 @@ def _propertyContainerElementTypeName(container, name):
# KeyError is more commonly expected when asking for an element
# from a mapping.
raise KeyError(str(e))
for checkType in ("Bool", "Short", "Int", "Long", "LongLong", "Float", "Double", "String", "DateTime",
for checkType in ("Bool", "Short", "Int", "Long", "LongLong", "UnsignedLongLong",
"Float", "Double", "String", "DateTime",
"PropertySet", "Undef"):
if t == getattr(container, "TYPE_" + checkType):
return checkType
Expand Down Expand Up @@ -227,6 +228,10 @@ def _guessIntegerType(container, name, value):
useType = None
maxInt = 2147483647
minInt = -2147483648
maxLongLong = 2**63 - 1
minLongLong = -2**63
maxU64 = 2**64 - 1
minU64 = 0

# We do not want to convert bool to int so let the system work that
# out itself
Expand All @@ -237,12 +242,15 @@ def _guessIntegerType(container, name, value):
try:
containerType = _propertyContainerElementTypeName(container, name)
except LookupError:
# nothing in the container so choose based on size. Safe option is
# to always use LongLong
# nothing in the container so choose based on size.
if value <= maxInt and value >= minInt:
useType = "Int"
else:
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,))
else:
if containerType == "Int":
# Always use an Int even if we know it won't fit. The later
Expand All @@ -252,6 +260,8 @@ def _guessIntegerType(container, name, value):
useType = "Int"
elif containerType == "LongLong":
useType = "LongLong"
elif containerType == "UnsignedLongLong":
useType = "UnsignedLongLong"
return useType


Expand Down
2 changes: 2 additions & 0 deletions python/lsst/daf/base/propertyContainer/propertySet.cc
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ PYBIND11_MODULE(propertySet, mod) {
cls.def("getAsBool", &PropertySet::getAsBool);
cls.def("getAsInt", &PropertySet::getAsInt);
cls.def("getAsInt64", &PropertySet::getAsInt64);
cls.def("getAsUInt64", &PropertySet::getAsUInt64);
cls.def("getAsDouble", &PropertySet::getAsDouble);
cls.def("getAsString", &PropertySet::getAsString);
cls.def("getAsPropertySetPtr", &PropertySet::getAsPropertySetPtr);
Expand All @@ -89,6 +90,7 @@ PYBIND11_MODULE(propertySet, mod) {
declareAccessors<int>(cls, "Int");
declareAccessors<long>(cls, "Long");
declareAccessors<long long>(cls, "LongLong");
declareAccessors<unsigned long long>(cls, "UnsignedLongLong");
declareAccessors<float>(cls, "Float");
declareAccessors<double>(cls, "Double");
declareAccessors<nullptr_t>(cls, "Undef");
Expand Down
27 changes: 27 additions & 0 deletions src/PropertySet.cc
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,33 @@ int64_t PropertySet::getAsInt64(std::string const& name) const {
return boost::any_cast<int64_t>(v);
}

uint64_t PropertySet::getAsUInt64(std::string const& name) const {
auto const i = _find(name);
if (i == _map.end()) {
throw LSST_EXCEPT(pex::exceptions::NotFoundError, name + " not found");
}
boost::any v = i->second->back();
std::type_info const& t = v.type();
if (t == typeid(bool)) return boost::any_cast<bool>(v);
if (t == typeid(char)) return boost::any_cast<char>(v);
if (t == typeid(signed char)) return boost::any_cast<signed char>(v);
if (t == typeid(unsigned char)) return boost::any_cast<unsigned char>(v);
if (t == typeid(short)) return boost::any_cast<short>(v);
if (t == typeid(unsigned short)) return boost::any_cast<unsigned short>(v);
if (t == typeid(int)) return boost::any_cast<int>(v);
if (t == typeid(unsigned int)) return boost::any_cast<unsigned int>(v);
if (t == typeid(long)) return boost::any_cast<long>(v);
if (t == typeid(long long)) return boost::any_cast<long long>(v);
if (t == typeid(unsigned long long)) return boost::any_cast<unsigned long long>(v);
try {
return boost::any_cast<uint64_t>(v);
} catch (boost::bad_any_cast) {
throw LSST_EXCEPT(pex::exceptions::TypeError, name);
}
// not reached
return boost::any_cast<uint64_t>(v);
}

double PropertySet::getAsDouble(std::string const& name) const {
auto const i = _find(name);
if (i == _map.end()) {
Expand Down
15 changes: 15 additions & 0 deletions tests/test_PropertySet_1.cc
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#include "lsst/pex/exceptions/Runtime.h"

#define INT64CONST(x) static_cast<int64_t>(x##LL)
#define UINT64CONST(x) static_cast<uint64_t>(x##ULL)

namespace test = boost::test_tools;
namespace dafBase = lsst::daf::base;
Expand All @@ -58,6 +59,7 @@ BOOST_AUTO_TEST_CASE(getScalar) { /* parasoft-suppress LsstDm-3-1 LsstDm-3-4a Ls
ps.set("short", s);
ps.set("int", 2008);
ps.set("int64_t", INT64CONST(0xfeeddeadbeef));
ps.set("uint64_t", UINT64CONST(0xFFFFFFFFFFFFFFFF));
float f = 3.14159;
ps.set("float", f);
double d = 2.718281828459045;
Expand All @@ -72,6 +74,7 @@ BOOST_AUTO_TEST_CASE(getScalar) { /* parasoft-suppress LsstDm-3-1 LsstDm-3-4a Ls
BOOST_CHECK_EQUAL(ps.get<short>("short"), 42);
BOOST_CHECK_EQUAL(ps.get<int>("int"), 2008);
BOOST_CHECK_EQUAL(ps.get<int64_t>("int64_t"), INT64CONST(0xfeeddeadbeef));
BOOST_CHECK_EQUAL(ps.get<uint64_t>("uint64_t"), UINT64CONST(0xFFFFFFFFFFFFFFFF));
BOOST_CHECK_EQUAL(ps.get<float>("float"), 3.14159f);
BOOST_CHECK_EQUAL(ps.get<double>("double"), 2.718281828459045);
BOOST_CHECK_EQUAL(ps.get<std::string>("char*"), "foo");
Expand All @@ -91,6 +94,7 @@ BOOST_AUTO_TEST_CASE(resetScalar) { /* parasoft-suppress LsstDm-3-1 LsstDm-3-4a
ps.set("short", s);
ps.set("int", 2008);
ps.set("int64_t", INT64CONST(0xfeeddeadbeef));
ps.set("uint64_t", UINT64CONST(0xFFFFFFFFFFFFFFFF));
float f = 3.14159;
ps.set("float", f);
double d = 2.718281828459045;
Expand All @@ -104,6 +108,7 @@ BOOST_AUTO_TEST_CASE(resetScalar) { /* parasoft-suppress LsstDm-3-1 LsstDm-3-4a
BOOST_CHECK_EQUAL(ps.get<short>("short"), 42);
BOOST_CHECK_EQUAL(ps.get<int>("int"), 2008);
BOOST_CHECK_EQUAL(ps.get<int64_t>("int64_t"), INT64CONST(0xfeeddeadbeef));
BOOST_CHECK_EQUAL(ps.get<uint64_t>("uint64_t"), UINT64CONST(0xFFFFFFFFFFFFFFFF));
BOOST_CHECK_EQUAL(ps.get<float>("float"), 3.14159f);
BOOST_CHECK_EQUAL(ps.get<double>("double"), 2.718281828459045);
BOOST_CHECK_EQUAL(ps.get<std::string>("char*"), "foo");
Expand All @@ -116,6 +121,7 @@ BOOST_AUTO_TEST_CASE(resetScalar) { /* parasoft-suppress LsstDm-3-1 LsstDm-3-4a
ps.set("short", s);
ps.set("int", 42);
ps.set("int64_t", INT64CONST(0xcafefacade));
ps.set("uint64_t", UINT64CONST(0xEEEEEEEEEEEEEEEE));
f = 2.71828;
ps.set("float", f);
d = 3.1415926535897932;
Expand All @@ -129,6 +135,7 @@ BOOST_AUTO_TEST_CASE(resetScalar) { /* parasoft-suppress LsstDm-3-1 LsstDm-3-4a
BOOST_CHECK_EQUAL(ps.get<short>("short"), 2008);
BOOST_CHECK_EQUAL(ps.get<int>("int"), 42);
BOOST_CHECK_EQUAL(ps.get<int64_t>("int64_t"), INT64CONST(0xcafefacade));
BOOST_CHECK_EQUAL(ps.get<uint64_t>("uint64_t"), UINT64CONST(0xEEEEEEEEEEEEEEEE));
BOOST_CHECK_EQUAL(ps.get<float>("float"), 2.71828f);
BOOST_CHECK_EQUAL(ps.get<double>("double"), 3.1415926535897932);
BOOST_CHECK_EQUAL(ps.get<std::string>("char*"), "baz");
Expand Down Expand Up @@ -163,6 +170,7 @@ BOOST_AUTO_TEST_CASE(getScalarThrow) { /* parasoft-suppress LsstDm-3-1 LsstDm-3-
ps.set("short", s);
ps.set("int", 2008);
ps.set("int64_t", INT64CONST(0xfeeddeadbeef));
ps.set("uint64_t", UINT64CONST(0xFFFFFFFFFFFFFFFF));
float f = 3.14159;
ps.set("float", f);
double d = 2.718281828459045;
Expand Down Expand Up @@ -251,6 +259,7 @@ BOOST_AUTO_TEST_CASE(
ps.set("short", s);
ps.set("int", 2008);
ps.set("int64_t", INT64CONST(0xfeeddeadbeef));
ps.set("uint64_t", UINT64CONST(0xFFFFFFFFFFFFFFFF));
float f = 3.14159;
ps.set("float", f);
double d = 2.718281828459045;
Expand All @@ -263,6 +272,7 @@ BOOST_AUTO_TEST_CASE(
BOOST_CHECK(ps.typeOf("short") == typeid(short));
BOOST_CHECK(ps.typeOf("int") == typeid(int));
BOOST_CHECK(ps.typeOf("int64_t") == typeid(int64_t));
BOOST_CHECK(ps.typeOf("uint64_t") == typeid(uint64_t));
BOOST_CHECK(ps.typeOf("float") == typeid(float));
BOOST_CHECK(ps.typeOf("double") == typeid(double));
BOOST_CHECK(ps.typeOf("char*") == typeid(std::string));
Expand Down Expand Up @@ -474,6 +484,7 @@ BOOST_AUTO_TEST_CASE(getAs) { /* parasoft-suppress LsstDm-3-1 LsstDm-3-4a LsstDm
ps.set("short", s);
ps.set("int", 2008);
ps.set("int64_t", INT64CONST(0xfeeddeadbeef));
ps.set("uint64_t", UINT64CONST(0xFFFFFFFFFFFFFFFF));
float f = 3.14159;
ps.set("float", f);
double d = 2.718281828459045;
Expand Down Expand Up @@ -503,6 +514,7 @@ BOOST_AUTO_TEST_CASE(getAs) { /* parasoft-suppress LsstDm-3-1 LsstDm-3-4a LsstDm
BOOST_CHECK_EQUAL(ps.getAsDouble("short"), 42.0);
BOOST_CHECK_EQUAL(ps.getAsDouble("int"), 2008.0);
BOOST_CHECK_EQUAL(ps.getAsDouble("int64_t"), static_cast<double>(INT64CONST(0xfeeddeadbeef)));
BOOST_CHECK_EQUAL(ps.getAsDouble("uint64_t"), static_cast<double>(UINT64CONST(0xFFFFFFFFFFFFFFFF)));
BOOST_CHECK_EQUAL(ps.getAsDouble("float"), 3.14159f);
BOOST_CHECK_EQUAL(ps.getAsDouble("double"), 2.718281828459045);
BOOST_CHECK_THROW(ps.getAsDouble("char*"), pexExcept::TypeError);
Expand Down Expand Up @@ -693,6 +705,7 @@ BOOST_AUTO_TEST_CASE(toString) { /* parasoft-suppress LsstDm-3-1 LsstDm-3-4a Lss
ps.set("short", s);
ps.set("int", 2008);
ps.set("int64_t", INT64CONST(0xfeeddeadbeef));
ps.set("uint64_t", UINT64CONST(0xFFFFFFFFFFFFFFFF));
float f = 3.14159;
ps.set("float", f);
double d = 2.718281828459045;
Expand Down Expand Up @@ -733,6 +746,7 @@ BOOST_AUTO_TEST_CASE(toString) { /* parasoft-suppress LsstDm-3-1 LsstDm-3-4a Lss
"}\n"
"short = 42\n"
"string = \"bar\"\n"
"uint64_t = 18446744073709551615\n"
"v = [ 10, 9, 8 ]\n");
BOOST_CHECK_EQUAL(ps.toString(true),
"bool = 1\n"
Expand All @@ -748,6 +762,7 @@ BOOST_AUTO_TEST_CASE(toString) { /* parasoft-suppress LsstDm-3-1 LsstDm-3-4a Lss
"ps3 = { ... }\n"
"short = 42\n"
"string = \"bar\"\n"
"uint64_t = 18446744073709551615\n"
"v = [ 10, 9, 8 ]\n");
}

Expand Down
45 changes: 45 additions & 0 deletions tests/test_PropertySet_2.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ def testScalar(self):
ps.setShort("short", 42)
ps.setInt("int", 2008)
ps.setLongLong("int64_t", 0xfeeddeadbeef)
ps.setUnsignedLongLong("uint64_t", 0xFFFFFFFFFFFFFFFF)
ps.setFloat("float", 3.14159)
ps.setDouble("double", 2.718281828459045)
ps.set("char*", "foo")
Expand All @@ -68,6 +69,8 @@ def testScalar(self):
self.assertEqual(ps.typeOf("int64_t"),
dafBase.PropertySet.TYPE_LongLong)
self.assertEqual(ps.getLongLong("int64_t"), 0xfeeddeadbeef)
self.assertEqual(ps.typeOf("uint64_t"), dafBase.PropertySet.TYPE_UnsignedLongLong)
self.assertEqual(ps.getUnsignedLongLong("uint64_t"), 0xFFFFFFFFFFFFFFFF)
self.assertEqual(ps.typeOf("float"), dafBase.PropertySet.TYPE_Float)
self.assertAlmostEqual(ps.getFloat("float"), 3.14159, 6)
self.assertEqual(ps.typeOf("double"), dafBase.PropertySet.TYPE_Double)
Expand Down Expand Up @@ -106,6 +109,7 @@ def testNumPyScalars(self):
ps.setShort("short", np.int16(42))
ps.setInt("int", np.int32(2008))
ps.setLongLong("int64_t", np.int64(0xfeeddeadbeef))
ps.setUnsignedLongLong("uint64_t", np.uint64(0xFFFFFFFFFFFFFFFF))
ps.setFloat("float", np.float32(3.14159))
ps.setDouble("double", np.float64(2.718281828459045))
self.assertEqual(ps.typeOf("short"), dafBase.PropertySet.TYPE_Short)
Expand All @@ -115,6 +119,8 @@ def testNumPyScalars(self):
self.assertEqual(ps.typeOf("int64_t"),
dafBase.PropertySet.TYPE_LongLong)
self.assertEqual(ps.getLongLong("int64_t"), 0xfeeddeadbeef)
self.assertEqual(ps.typeOf("uint64_t"), dafBase.PropertySet.TYPE_UnsignedLongLong)
self.assertEqual(ps.getUnsignedLongLong("uint64_t"), 0xFFFFFFFFFFFFFFFF)
self.assertEqual(ps.typeOf("float"), dafBase.PropertySet.TYPE_Float)
self.assertAlmostEqual(ps.getFloat("float"), 3.14159, 6)
self.assertEqual(ps.typeOf("double"), dafBase.PropertySet.TYPE_Double)
Expand Down Expand Up @@ -314,6 +320,7 @@ def testScalar(self):
ps.setShort("short", 42)
ps.setInt("int", 2008)
ps.setLongLong("int64_t", 0xfeeddeadbeef)
ps.setUnsignedLongLong("uint64_t", 0xFFFFFFFFFFFFFFFF)
ps.setFloat("float", 3.14159)
ps.setDouble("double", 2.718281828459045)
ps.set("char*", "foo")
Expand All @@ -334,6 +341,8 @@ def testScalar(self):
self.assertEqual(ps.typeOf("int64_t"),
dafBase.PropertySet.TYPE_LongLong)
self.assertEqual(ps.getLongLong("int64_t"), 0xfeeddeadbeef)
self.assertEqual(ps.typeOf("uint64_t"), dafBase.PropertySet.TYPE_UnsignedLongLong)
self.assertEqual(ps.getUnsignedLongLong("uint64_t"), 0xFFFFFFFFFFFFFFFF)
self.assertEqual(ps.typeOf("float"), dafBase.PropertySet.TYPE_Float)
self.assertAlmostEqual(ps.getFloat("float"), 3.14159, 6)
self.assertEqual(ps.typeOf("double"), dafBase.PropertySet.TYPE_Double)
Expand Down Expand Up @@ -575,6 +584,7 @@ def testToDict(self):
ps.setShort("short", 42)
ps.setInt("int", 2008)
ps.setLongLong("int64_t", 0xfeeddeadbeef)
ps.setUnsignedLongLong("uint64_t", 0xFFFFFFFFFFFFFFFF)
ps.setInt("ints", [10, 9, 8])

ps2 = dafBase.PropertySet()
Expand Down Expand Up @@ -613,6 +623,8 @@ def testToDict(self):
self.assertEqual(d2["int"], 2008)
self.assertIsInstance(d2["int64_t"], (int, int))
self.assertEqual(d2["int64_t"], 0xfeeddeadbeef)
self.assertIsInstance(d2["uint64_t"], (int, int))
self.assertEqual(d2["uint64_t"], 0xFFFFFFFFFFFFFFFF)
self.assertIsInstance(d2["ints"], list)
self.assertIsInstance(d2["ints"][0], (int, int))
self.assertEqual(d2["ints"], [10, 9, 8])
Expand Down Expand Up @@ -737,6 +749,26 @@ def testvariousThrows(self):
ps.remove("foo.bar")
ps.remove("int.sub")

def testIntegerRanges(self):
"""Test that the ranges of the various integer types is as expected"""
ps = dafBase.PropertySet()
minI32 = -2**31
maxI32 = 2**31 - 1
minI64 = -2**63
maxI64 = 2**63 - 1
minU64 = 0
maxU64 = 2**64 - 1
# Out of range for the particular type
self.assertRaises(TypeError, ps.addInt, "int32", minI32 - 1)
self.assertRaises(TypeError, ps.addInt, "int32", maxI32 + 1)
self.assertRaises(TypeError, ps.addLongLong, "int64", minI64 - 1)
self.assertRaises(TypeError, ps.addLongLong, "int64", maxI64 + 1)
self.assertRaises(TypeError, ps.addUnsignedLongLong, "uint64", minU64 - 1)
self.assertRaises(TypeError, ps.addUnsignedLongLong, "uint64", maxU64 + 1)
# Out of all possible integer ranges
self.assertRaises(RuntimeError, ps.add, "number", minI64 - 1)
self.assertRaises(RuntimeError, ps.add, "number", maxU64 + 1)

def testNames(self):
ps = dafBase.PropertySet()
ps.set("ps1.pre", 1)
Expand Down Expand Up @@ -797,6 +829,7 @@ def testGetAs(self):
ps.setShort("short", 42)
ps.set("int", 2008)
ps.set("int64_t", 0xfeeddeadbeef)
ps.set("uint64_t", 0xFFFFFFFFFFFFFFFF)
f = 3.14159
ps.setFloat("float", f)
d = 2.718281828459045
Expand All @@ -814,17 +847,26 @@ def testGetAs(self):
self.assertEqual(ps.getAsInt("int"), 2008)
with self.assertRaises(TypeError):
ps.getAsInt("int64_t")
with self.assertRaises(TypeError):
ps.getAsInt("uint64_t")
with self.assertRaises(TypeError):
ps.getAsInt64("uint64_t")
self.assertEqual(ps.getAsInt64("bool"), 1)
self.assertEqual(ps.getAsInt64("short"), 42)
self.assertEqual(ps.getAsInt64("int"), 2008)
self.assertEqual(ps.getAsInt64("int64_t"), 0xfeeddeadbeef)
self.assertEqual(ps.getAsUInt64("uint64_t"), 0xFFFFFFFFFFFFFFFF)
with self.assertRaises(TypeError):
ps.getAsInt64("float")
with self.assertRaises(TypeError):
ps.getAsUInt64("float")
self.assertEqual(ps.getAsDouble("bool"), 1.0)
self.assertEqual(ps.getAsDouble("short"), 42.0)
self.assertEqual(ps.getAsDouble("int"), 2008.0)
self.assertEqual(ps.getAsDouble("int64_t"),
float(0xfeeddeadbeef))
self.assertEqual(ps.getAsDouble("uint64_t"),
float(0xFFFFFFFFFFFFFFFF))
self.assertAlmostEqual(ps.getAsDouble("float"), 3.14159, places=5)
self.assertAlmostEqual(ps.getAsDouble("double"), 2.718281828459045, places=15)
with self.assertRaises(TypeError):
Expand Down Expand Up @@ -910,6 +952,7 @@ def testToString(self):
ps.setShort("short", s)
ps.set("int", 2008)
ps.set("int64_t", 0xfeeddeadbeef)
ps.set("uint64_t", 0xFFFFFFFFFFFFFFFF)
f = 3.14159
ps.setFloat("float", f)
d = 2.718281828459045
Expand Down Expand Up @@ -949,6 +992,7 @@ def testToString(self):
"}\n"
"short = 42\n"
"string = \"bar\"\n"
"uint64_t = 18446744073709551615\n"
"v = [ 10, 9, 8 ]\n"
)
self.assertEqual(ps.toString(True),
Expand All @@ -964,6 +1008,7 @@ def testToString(self):
"ps3 = { ... }\n"
"short = 42\n"
"string = \"bar\"\n"
"uint64_t = 18446744073709551615\n"
"v = [ 10, 9, 8 ]\n"
)

Expand Down