Browse Source

classex.AttributeDescriptor: added type filter

Fabian Peter Hammerle 8 years ago
parent
commit
cf1e83f6c6
2 changed files with 30 additions and 1 deletions
  1. 11 1
      ioex/classex.py
  2. 19 0
      tests/classex/test_attribute_descriptor.py

+ 11 - 1
ioex/classex.py

@@ -1,10 +1,20 @@
+# -*- coding: utf-8 -*-
+
+
 class AttributeDescriptor(object):
 
-    def __init__(self, name):
+    def __init__(self, name, types=None):
         self._name = name
+        self._types = types
 
     def __get__(self, instance, owner):
         return getattr(instance, self._name)
 
     def __set__(self, instance, value):
+        if self._types and not any([isinstance(value, t) for t in self._types]):
+            raise TypeError('expected type ϵ {{{}}}, {} ({!r}) given'.format(
+                ', '.join([t.__name__ for t in self._types]),
+                type(value).__name__,
+                value,
+            ))
         setattr(instance, self._name, value)

+ 19 - 0
tests/classex/test_attribute_descriptor.py

@@ -64,10 +64,12 @@ class IntAttr(AttributeDescriptor):
         else:
             super(IntAttr, self).__set__(instance, value)
 
+
 class Qux(object):
 
     desc = IntAttr('attr')
 
+
 def test_subclass():
     obj = Qux()
     obj.attr = 'first'
@@ -78,3 +80,20 @@ def test_subclass():
     assert 42 == obj.desc
     with pytest.raises(TypeError):
         obj.desc = 3.14
+
+
+class Xyzzy(object):
+
+    desc = AttributeDescriptor('attr', types=(int, float))
+
+
+def test_types():
+    obj = Xyzzy()
+    obj.desc = 1
+    assert 1 == obj.attr
+    assert isinstance(obj.desc, int) and 1 == obj.desc
+    obj.desc = 1.23
+    assert isinstance(obj.desc, float) and 1.23 == obj.desc
+    with pytest.raises(TypeError):
+        obj.desc = '123'
+    assert isinstance(obj.desc, float) and 1.23 == obj.desc