Skip to content

Commit

Permalink
Add NumberMeta and register required types
Browse files Browse the repository at this point in the history
  • Loading branch information
c-mita committed Jun 20, 2016
1 parent 9670006 commit e348bc0
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 0 deletions.
1 change: 1 addition & 0 deletions malcolm/core/__init__.py
@@ -1,2 +1,3 @@
# Need to import these so that the register hooks are called
from malcolm.core.stringmeta import StringMeta # noqa
from malcolm.core.numbermeta import NumberMeta # noqa
40 changes: 40 additions & 0 deletions malcolm/core/numbermeta.py
@@ -0,0 +1,40 @@
from malcolm.core.attributemeta import AttributeMeta
from malcolm.compat import base_string

import numpy


@AttributeMeta.register_subclass("malcolm:core/Byte:1.0", numpy.int8)
@AttributeMeta.register_subclass("malcolm:core/UByte:1.0", numpy.uint8)
@AttributeMeta.register_subclass("malcolm:core/Short:1.0", numpy.int16)
@AttributeMeta.register_subclass("malcolm:core/UShort:1.0", numpy.uint16)
@AttributeMeta.register_subclass("malcolm:core/Int:1.0", numpy.int32)
@AttributeMeta.register_subclass("malcolm:core/UInt:1.0", numpy.uint32)
@AttributeMeta.register_subclass("malcolm:core/Long:1.0", numpy.int64)
@AttributeMeta.register_subclass("malcolm:core/ULong:1.0", numpy.uint64)
@AttributeMeta.register_subclass("malcolm:core/Float:1.0", numpy.float32)
@AttributeMeta.register_subclass("malcolm:core/Double:1.0", numpy.float64)
class NumberMeta(AttributeMeta):
"""Meta object containing information for a numerical value"""

def __init__(self, name, description, dtype):
super(NumberMeta, self).__init__(name, description, dtype)
self.dtype = dtype

def validate(self, value):
if value is None:
return None
cast = self.dtype(value)
if not isinstance(value, base_string):
assert cast == value, \
"Lost information converting %s to %s" % (value, cast)
return cast

def to_dict(self):
d = super(NumberMeta, self).to_dict()
return d

@classmethod
def from_dict(self, name, d, *args):
number_meta = NumberMeta(name, d["description"], *args)
return number_meta
56 changes: 56 additions & 0 deletions tests/test_core/test_numbermeta.py
@@ -0,0 +1,56 @@
from . import util
import unittest
from collections import OrderedDict

import numpy as np

from malcolm.core.numbermeta import NumberMeta
from malcolm.core.attributemeta import AttributeMeta

class TestNumberMeta(unittest.TestCase):
def test_init_int(self):
nm = NumberMeta("nm", "desc", np.int32)
self.assertEqual(nm.metaOf, "malcolm:core/Int:1.0")

def test_init_float(self):
nm = NumberMeta("nm", "desc", np.float64)
self.assertEqual(nm.metaOf, "malcolm:core/Double:1.0")

def test_to_dict(self):
nm = NumberMeta("nm", "desc", np.float64)
expected = OrderedDict()
expected["description"] = "desc"
expected["metaOf"] = "malcolm:core/Double:1.0"

self.assertEqual(expected, nm.to_dict())

def test_from_dict(self):
d = {"description":"desc", "metaOf":"malcolm:core/Double:1.0"}
nm = AttributeMeta.from_dict("nm", d)
self.assertEqual(NumberMeta, type(nm))
self.assertEqual("nm", nm.name)
self.assertEqual(np.float64, nm.dtype)

class TestNumberMetaValidation(unittest.TestCase):
def test_float_against_float(self):
nm = NumberMeta("nm", "desc", np.float64)
self.assertEqual(123.456, nm.validate(123.456))

def test_int_against_float(self):
nm = NumberMeta("nm", "desc", np.float64)
self.assertEqual(123, nm.validate(123))

def test_int_against_int(self):
nm = NumberMeta("nm", "desc", np.int32)
self.assertEqual(123, nm.validate(123))

def test_float_fails_against_int(self):
nm = NumberMeta("nm", "desc", np.int32)
self.assertRaises(AssertionError, nm.validate, 123.456)

def test_none_validates(self):
nm = NumberMeta("nm", "desc", np.int32)
self.assertIsNone(nm.validate(None))

if __name__ == "__main__":
unittest.main(verbosity=2)

0 comments on commit e348bc0

Please sign in to comment.