Kaynağa Gözat

classex.AttributeDescriptor: added option always_accept_none

Fabian Peter Hammerle 8 yıl önce
ebeveyn
işleme
6115df694a
2 değiştirilmiş dosya ile 35 ekleme ve 2 silme
  1. 5 2
      ioex/classex.py
  2. 30 0
      tests/classex/test_attribute_descriptor.py

+ 5 - 2
ioex/classex.py

@@ -3,16 +3,19 @@
 
 class AttributeDescriptor(object):
 
-    def __init__(self, name, types=None, min=None):
+    def __init__(self, name, types=None, always_accept_none=False, min=None):
         self._name = name
         self._types = types
+        self._always_accept_none = always_accept_none
         self._min = min
 
     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]):
+        if self._always_accept_none and value is None:
+            setattr(instance, self._name, None)
+        elif 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__,

+ 30 - 0
tests/classex/test_attribute_descriptor.py

@@ -112,3 +112,33 @@ def test_min():
     assert 1 == obj.desc
     with pytest.raises(ValueError):
         obj.desc = -1
+
+
+class AlwaysAcceptNone(object):
+
+    a = AttributeDescriptor('_a', types=(str,), always_accept_none=True)
+    b = AttributeDescriptor('_b', types=(str,), always_accept_none=False)
+    c = AttributeDescriptor('_c', types=(str,))
+
+
+def test_always_accept_none_true():
+    obj = AlwaysAcceptNone()
+    obj.a = None
+    assert None == obj.a
+    assert None == obj._a
+
+
+def test_always_accept_none_false():
+    obj = AlwaysAcceptNone()
+    obj.b = 'B'
+    with pytest.raises(TypeError):
+        obj.b = None
+    assert 'B' == obj._b
+
+
+def test_always_accept_none_default():
+    obj = AlwaysAcceptNone()
+    obj.c = 'C'
+    with pytest.raises(TypeError):
+        obj.c = None
+    assert 'C' == obj._c