Exemple #1
0
 def test_modifier(self):
     a1 = MultiValueAttribute()
     a2 = MultiValueAttribute(immutable=True)
     Test = create_cls('Test', {'x': a1, 'y': a2})
     t1 = Test()
     t1.x = (7, 33, 33)
     t1.x.add(5)
     self.assertEqual(t1.x, {5, 7, 33})
     t1.x.add(7)
     self.assertEqual(t1.x, {5, 7, 33})
     t1.x.discard(17)
     self.assertEqual(t1.x, {5, 7, 33})
     t1.x.discard(7)
     self.assertEqual(t1.x, {5, 33})
     t1.x.remove(5)
     self.assertEqual(t1.x, {33})
     self.assertRaises(KeyError, t1.x.remove, 5)
     t1.x.clear()
     self.assertEqual(t1.x, set())
     t1.x.update((1, 2, 2))
     t1.x.update({7, 33})
     self.assertEqual(t1.x, {1, 2, 7, 33})
     i = t1.x.pop()
     self.assertEqual(t1.x, {1, 2, 7, 33} - {i})
     t1.x.add(i)
     self.assertEqual(t1.x, {1, 2, 7, 33})
     s = set(t1.x)
     o = {7, 18, 33, 90}
     t1.x |= o
     self.assertEqual(t1.x, s | o)
     t1.x = s
     t1.x.intersection_update(o)
     self.assertEqual(t1.x, s & o)
     t1.x = s
     t1.x &= o
     self.assertEqual(t1.x, s & o)
     t1.x = s
     t1.x.difference_update(o)
     self.assertEqual(t1.x, s - o)
     t1.x = s
     t1.x -= o
     self.assertEqual(t1.x, s - o)
     t1.x = s
     t1.x.symmetric_difference_update(o)
     self.assertEqual(t1.x, s.symmetric_difference(o))
     # can't modify immutable attribute
     t1.y = {7}
     self.assertRaises(AttributeError, t1.y.add, 2)
     self.assertRaises(AttributeError, t1.y.discard, 8)
     self.assertRaises(AttributeError, t1.y.clear)
     self.assertRaises(AttributeError, t1.y.pop)
     self.assertRaises(AttributeError, t1.y.remove, 8)
     self.assertRaises(AttributeError, t1.y.update, (2, 9))
     self.assertRaises(AttributeError, t1.y.__ior__, {2, 9})
     self.assertRaises(AttributeError, t1.y.intersection_update, {2, 9})
     self.assertRaises(AttributeError, t1.y.__iand__, {2, 9})
     self.assertRaises(AttributeError, t1.y.difference_update, {2, 9})
     self.assertRaises(AttributeError, t1.y.__isub__, {2, 9})
     self.assertRaises(AttributeError, t1.y.symmetric_difference_update,
                       {2, 9})
Exemple #2
0
 def test_converter(self):
     a = MultiValueAttribute(converter=str)
     Test = create_cls('Test', {'x': a})
     t = Test()
     t.x = {5, 7, 'abc'}
     self.assertEqual(t.x, {'5', '7', 'abc'})
     t.x = [int]
     self.assertEqual(t.x, {str(int)})
     a = MultiValueAttribute(converter=int)
     Test = create_cls('Test', {'x': a})
     t = Test()
     t.x = {5, '-9'}
     self.assertEqual(t.x, {-9, 5})
     self.assertRaises(ValueError, setattr, t, 'x', ('17', '12.090'))
     self.assertRaises(TypeError, setattr, t, 'x', [object()])
Exemple #3
0
 def test_repr(self):
     x = MultiValueAttribute(default={1})
     Test = create_cls('Test', {'x': x})
     t1 = Test()
     self.assertRegex(repr(t1.x), '<.*\.%s: \%s>' % (Test.x.name, t1.x))
     t1.x = {2, 7, 55}
     self.assertRegex(repr(t1.x), '<.*\.%s: \%s>' % (Test.x.name, t1.x))
Exemple #4
0
class Car(Entity):

    id = UniqueIdAttribute()
    make = Attribute(immutable=True)
    model = Attribute(immutable=True)
    wheels = QualifiedMultiValueAttribute(WheelPosition, default={})
    extras = MultiValueAttribute(default=set())
    registered = Attribute(default=False)

    def __init__(self,
                 make: str,
                 model: str,
                 *,
                 listener: StateChangedListener = None):
        super().__init__()
        if listener:
            # create notifyer and add listener
            StateChangedNotifyerExtension(self).add_listener(listener)
        self.make = make
        self.model = model

    def change_tire(self, wheel_pos: WheelPosition, tire: Tire) -> None:
        try:
            wheel = self.wheels[wheel_pos]
        except KeyError:
            raise ValueError(f"No {wheel_pos} wheel") from None
        wheel.tire = tire
        # setting attribute of nested entity doesn't trigger change
        # notification, so it has to be done explicitely
        self.state_changed()

    def __repr__(self):
        """repr(self)"""
        return f"<{self.__class__.__name__}: {self.id} "
Exemple #5
0
 def test_constraints(self):
     # single constraint
     a = MultiValueAttribute(constraints=is_number)
     Test = create_cls('Test', {'x': a})
     t = Test()
     t.x = {5}
     self.assertEqual(t.x, {5})
     self.assertRaises(ValueError, setattr, t, 'x', {'a'})
     # several constraints
     eq5 = lambda value: value == 5
     a = MultiValueAttribute(constraints=(is_number, non_negative,
                                          between(1, 7), eq5))
     Test = create_cls('Test', {'x': a})
     t = Test()
     t.x = {5}
     self.assertEqual(t.x, {5})
     self.assertRaises(ValueError, setattr, t, 'x', {'a'})
     self.assertRaises(ValueError, setattr, t, 'x', {-3})
     self.assertRaises(ValueError, setattr, t, 'x', {9})
     self.assertRaises(ValueError, setattr, t, 'x', {2})
Exemple #6
0
 def test_access(self):
     a1 = MultiValueAttribute()
     a2 = MultiValueAttribute(default={1})
     a3 = MultiValueAttribute(immutable=True)
     Test = create_cls('Test', {'x': a1, 'y': a2, 'z': a3})
     t1 = Test()
     self.assertRaises(AttributeError, getattr, t1, 'x')
     t1.x = (7, 33, 33)
     self.assertEqual(t1.x, {7, 33})
     del t1.x
     self.assertRaises(AttributeError, getattr, t1, 'x')
     self.assertIsNone(delattr(t1, 'x'))
     self.assertEqual(t1.y, {1})
     t1.y = {5}
     self.assertEqual(t1.y, {5})
     self.assertRaises(AttributeError, getattr, t1, 'z')
     t1.z = [7]
     self.assertEqual(t1.z, {7})
     self.assertRaises(AttributeError, setattr, t1, 'z', {9})
     self.assertRaises(AttributeError, delattr, t1, 'z')
     t2 = Test()
     self.assertRaises(AttributeError, getattr, t2, 'x')
     t2.x = (7, 33, 33)
     self.assertEqual(t2.x, {7, 33})
     del t2.x
     self.assertRaises(AttributeError, getattr, t2, 'x')
     self.assertIsNone(delattr(t2, 'x'))
     self.assertEqual(t2.y, {1})
     t2.y = {5}
     self.assertEqual(t2.y, {5})
     self.assertRaises(AttributeError, getattr, t2, 'z')
     t2.z = [7]
     self.assertEqual(t2.z, {7})
     self.assertRaises(AttributeError, setattr, t2, 'z', {9})
     self.assertRaises(AttributeError, delattr, t2, 'z')
     # immutable object
     a1 = MultiValueAttribute()
     a2 = MultiValueAttribute(default={1})
     a3 = MultiValueAttribute(immutable=True)
     Immu = immutable(create_cls('Immu', {'x': a1, 'y': a2, 'z': a3}))
     im1 = Immu()
     im1.x = ('a', )
     self.assertEqual(im1.x, {'a'})
     self.assertEqual(im1.y, {1})
     im1.y = ('b', )
     self.assertEqual(im1.y, {'b'})
     self.assertRaises(AttributeError, getattr, im1, 'z')
     im1.z = {'a', 'b', 'c'}
     self.assertEqual(im1.z, {'a', 'b', 'c'})
     for attr in ('x', 'y', 'z'):
         self.assertRaises(AttributeError, setattr, im1, attr, {3})
         self.assertRaises(AttributeError, delattr, im1, attr)
Exemple #7
0
 def test_constructor(self):
     a = MultiValueAttribute()
     self.assertTrue(a.immutable is False)
     self.assertTrue(a.default is _NODEFAULT)
     self.assertTrue(a.converter is None)
     self.assertTrue(a.constraints is None)
     self.assertEqual(a._bound_constraints, ())
     self.assertIsNone(a.__doc__)
     self.assertEqual(a.name, '<unnamed>')
     a = MultiValueAttribute(immutable=True,
                             default={'5'},
                             converter=int,
                             constraints=is_number,
                             doc='doc')
     a.__set_name__(None, 'a')
     self.assertTrue(a.immutable is True)
     self.assertEqual(a.default, {5})
     self.assertTrue(a.converter is int)
     self.assertTrue(a.constraints is is_number)
     self.assertTrue(type(a._bound_constraints) is tuple)
     self.assertTrue(all(callable(c) for c in a._bound_constraints))
     self.assertEqual(a.__doc__, 'doc')
     self.assertEqual(a.name, 'a')
     # default must be iterable
     self.assertRaises(TypeError, MultiValueAttribute, default=3)
     # items in default must be compatible to converter and must pass
     # constraints
     self.assertRaises(TypeError,
                       MultiValueAttribute,
                       converter=int,
                       default=[object()])
     self.assertRaises(ValueError,
                       MultiValueAttribute,
                       converter=int,
                       default=['1', 'a'])
     self.assertRaises(ValueError,
                       MultiValueAttribute,
                       constraints=(is_number, non_negative),
                       default=[5, 9, 'a'])
     self.assertRaises(ValueError,
                       MultiValueAttribute,
                       constraints=(is_number, non_negative),
                       default=[2, 3, 19, -7])
Exemple #8
0
class PMVATest:
    """Helper class to test pickling instances with a MultiValueAttribute"""

    x = MultiValueAttribute(constraints=(is_number, non_negative))
Exemple #9
0
 def test_default(self):
     double_x = lambda t: {2 * i for i in t.x}
     a1 = MultiValueAttribute(default={17})
     a2 = MultiValueAttribute(default=double_x)
     Test = create_cls('Test', {'x': a1, 'y': a2})
     t = Test()
     self.assertEqual(t.x, {17})
     self.assertEqual(t.y, {34})
     t.x = {4, 70}
     self.assertEqual(t.x, {4, 70})
     self.assertEqual(t.y, {8, 140})
     del t.x  # reset to default
     self.assertEqual(t.x, {17})
     self.assertEqual(t.y, {34})
     t.x.add(7)
     self.assertEqual(t.x, {7, 17})
     self.assertEqual(t.y, {14, 34})
     t.y = {3}
     self.assertEqual(t.y, {3})
     del t.x  # reset to default
     self.assertEqual(t.y, {3})
     del t.y  # reset to default
     self.assertEqual(t.x, {17})
     self.assertEqual(t.y, {34})
     t.x.discard(17)
     self.assertEqual(t.x, set())
     del t.x  # reset to default
     t.x.pop()
     self.assertEqual(t.x, set())
     del t.x  # reset to default
     t.x.clear()
     self.assertEqual(t.x, set())
     del t.x  # reset to default
     t.x.remove(17)
     self.assertEqual(t.x, set())
     del t.x  # reset to default
     t.x.update((2, 9))
     self.assertEqual(t.x, {2, 9, 17})
     del t.x  # reset to default
     t.x |= {2, 9}
     self.assertEqual(t.x, {2, 9, 17})
     del t.x  # reset to default
     t.x.intersection_update({2, 9})
     self.assertEqual(t.x, set())
     del t.x  # reset to default
     t.x &= {2, 9}
     self.assertEqual(t.x, set())
     del t.x  # reset to default
     t.x.difference_update({2, 9})
     self.assertEqual(t.x, {17})
     del t.x  # reset to default
     t.x -= {17}
     self.assertEqual(t.x, set())
     del t.x  # reset to default
     t.x.symmetric_difference_update({2, 9, 17})
     self.assertEqual(t.x, {2, 9})
     self.assertEqual(t.y, {4, 18})
     # callable default also linked to instance
     self.assertIs(t.y._instance, t.x._instance)
     # modifying default does fix the attribute value
     t.y.add(2)
     self.assertEqual(t.y, {2, 4, 18})
     t.x = set()
     self.assertEqual(t.y, {2, 4, 18})
     # deleting the attribute value restores the default
     del t.y
     self.assertEqual(t.y, set())