This repository has been archived on 2024-12-22. You can view files and clone it, but cannot push or open issues or pull requests.
PyBitmessage-2024-12-22/mockenv/lib/python3.6/site-packages/kivy/tests/test_properties.py
2022-07-22 16:13:59 +05:30

822 lines
25 KiB
Python

'''
Test properties attached to a widget
'''
import unittest
import pytest
from kivy.event import EventDispatcher
from functools import partial
class _TestProperty(EventDispatcher):
pass
wid = _TestProperty()
class PropertiesTestCase(unittest.TestCase):
@pytest.fixture(autouse=True)
def set_clock(self, kivy_clock):
self.kivy_clock = kivy_clock
def test_base(self):
from kivy.properties import Property
a = Property(-1)
a.link(wid, 'a')
a.link_deps(wid, 'a')
self.assertEqual(a.get(wid), -1)
a.set(wid, 0)
self.assertEqual(a.get(wid), 0)
a.set(wid, 1)
self.assertEqual(a.get(wid), 1)
def test_observer(self):
from kivy.properties import Property
a = Property(-1)
a.link(wid, 'a')
a.link_deps(wid, 'a')
self.assertEqual(a.get(wid), -1)
global observe_called
observe_called = 0
def observe(obj, value):
global observe_called
observe_called = 1
a.bind(wid, observe)
a.set(wid, 0)
self.assertEqual(a.get(wid), 0)
self.assertEqual(observe_called, 1)
observe_called = 0
a.set(wid, 0)
self.assertEqual(a.get(wid), 0)
self.assertEqual(observe_called, 0)
a.set(wid, 1)
self.assertEqual(a.get(wid), 1)
self.assertEqual(observe_called, 1)
def test_objectcheck(self):
from kivy.properties import ObjectProperty
a = ObjectProperty(False)
a.link(wid, 'a')
a.link_deps(wid, 'a')
self.assertEqual(a.get(wid), False)
a.set(wid, True)
self.assertEqual(a.get(wid), True)
def test_stringcheck(self):
from kivy.properties import StringProperty
a = StringProperty()
a.link(wid, 'a')
a.link_deps(wid, 'a')
self.assertEqual(a.get(wid), '')
a.set(wid, 'hello')
self.assertEqual(a.get(wid), 'hello')
try:
a.set(wid, 88) # number shouldn't be accepted
self.fail('string accept number, fail.')
except ValueError:
pass
def test_numericcheck(self):
from kivy.properties import NumericProperty
a = NumericProperty()
a.link(wid, 'a')
a.link_deps(wid, 'a')
self.assertEqual(a.get(wid), 0)
a.set(wid, 99)
self.assertEqual(a.get(wid), 99)
# try:
# a.set(wid, '') # string shouldn't be accepted
# self.fail('number accept string, fail.')
# except ValueError:
# pass
def test_listcheck(self):
from kivy.properties import ListProperty
a = ListProperty()
a.link(wid, 'a')
a.link_deps(wid, 'a')
self.assertEqual(a.get(wid), [])
a.set(wid, [1, 2, 3])
self.assertEqual(a.get(wid), [1, 2, 3])
def test_dictcheck(self):
from kivy.properties import DictProperty
a = DictProperty()
a.link(wid, 'a')
a.link_deps(wid, 'a')
self.assertEqual(a.get(wid), {})
a.set(wid, {'foo': 'bar'})
self.assertEqual(a.get(wid), {'foo': 'bar'})
def test_propertynone(self):
from kivy.properties import NumericProperty
a = NumericProperty(0, allownone=True)
a.link(wid, 'a')
a.link_deps(wid, 'a')
self.assertEqual(a.get(wid), 0)
try:
a.set(wid, None)
self.assertEqual(a.get(wid), None)
except ValueError:
pass
a.set(wid, 1)
self.assertEqual(a.get(wid), 1)
def test_reference(self):
from kivy.properties import NumericProperty, ReferenceListProperty
x = NumericProperty(0)
x.link(wid, 'x')
x.link_deps(wid, 'x')
y = NumericProperty(0)
y.link(wid, 'y')
y.link_deps(wid, 'y')
pos = ReferenceListProperty(x, y)
pos.link(wid, 'pos')
pos.link_deps(wid, 'pos')
self.assertEqual(x.get(wid), 0)
self.assertEqual(y.get(wid), 0)
self.assertEqual(pos.get(wid), [0, 0])
x.set(wid, 50)
self.assertEqual(pos.get(wid), [50, 0])
y.set(wid, 50)
self.assertEqual(pos.get(wid), [50, 50])
pos.set(wid, [0, 0])
self.assertEqual(pos.get(wid), [0, 0])
self.assertEqual(x.get(wid), 0)
self.assertEqual(y.get(wid), 0)
# test observer
global observe_called
observe_called = 0
def observe(obj, value):
global observe_called
observe_called = 1
pos.bind(wid, observe)
self.assertEqual(observe_called, 0)
x.set(wid, 99)
self.assertEqual(observe_called, 1)
def test_reference_child_update(self):
from kivy.properties import NumericProperty, ReferenceListProperty
x = NumericProperty(0)
x.link(wid, 'x')
x.link_deps(wid, 'x')
y = NumericProperty(0)
y.link(wid, 'y')
y.link_deps(wid, 'y')
pos = ReferenceListProperty(x, y)
pos.link(wid, 'pos')
pos.link_deps(wid, 'pos')
pos.get(wid)[0] = 10
self.assertEqual(pos.get(wid), [10, 0])
pos.get(wid)[:] = (20, 30)
self.assertEqual(pos.get(wid), [20, 30])
def test_dict(self):
from kivy.properties import DictProperty
x = DictProperty()
x.link(wid, 'x')
x.link_deps(wid, 'x')
# test observer
global observe_called
observe_called = 0
def observe(obj, value):
global observe_called
observe_called = 1
x.bind(wid, observe)
observe_called = 0
x.get(wid)['toto'] = 1
self.assertEqual(observe_called, 1)
observe_called = 0
x.get(wid)['toto'] = 2
self.assertEqual(observe_called, 1)
observe_called = 0
x.get(wid)['youupi'] = 2
self.assertEqual(observe_called, 1)
observe_called = 0
del x.get(wid)['toto']
self.assertEqual(observe_called, 1)
observe_called = 0
x.get(wid).update({'bleh': 5})
self.assertEqual(observe_called, 1)
def test_bounded_numeric_property(self):
from kivy.properties import BoundedNumericProperty
bnp = BoundedNumericProperty(0.0, min=0.0, max=3.5)
bnp.link(wid, 'bnp')
bnp.set(wid, 1)
bnp.set(wid, 0.0)
bnp.set(wid, 3.1)
bnp.set(wid, 3.5)
self.assertRaises(ValueError, partial(bnp.set, wid, 3.6))
self.assertRaises(ValueError, partial(bnp.set, wid, -3))
def test_bounded_numeric_property_error_value(self):
from kivy.properties import BoundedNumericProperty
bnp = BoundedNumericProperty(0, min=-5, max=5, errorvalue=1)
bnp.link(wid, 'bnp')
bnp.set(wid, 1)
self.assertEqual(bnp.get(wid), 1)
bnp.set(wid, 5)
self.assertEqual(bnp.get(wid), 5)
bnp.set(wid, 6)
self.assertEqual(bnp.get(wid), 1)
bnp.set(wid, -5)
self.assertEqual(bnp.get(wid), -5)
bnp.set(wid, -6)
self.assertEqual(bnp.get(wid), 1)
def test_bounded_numeric_property_error_handler(self):
from kivy.properties import BoundedNumericProperty
bnp = BoundedNumericProperty(
0, min=-5, max=5,
errorhandler=lambda x: 5 if x > 5 else -5)
bnp.link(wid, 'bnp')
bnp.set(wid, 1)
self.assertEqual(bnp.get(wid), 1)
bnp.set(wid, 5)
self.assertEqual(bnp.get(wid), 5)
bnp.set(wid, 10)
self.assertEqual(bnp.get(wid), 5)
bnp.set(wid, -5)
self.assertEqual(bnp.get(wid), -5)
bnp.set(wid, -10)
self.assertEqual(bnp.get(wid), -5)
def test_numeric_string_with_units_check(self):
from kivy.properties import NumericProperty
a = NumericProperty()
a.link(wid, 'a')
a.link_deps(wid, 'a')
self.assertEqual(a.get(wid), 0)
a.set(wid, '55dp')
from kivy.core.window import Window
density = Window._density if hasattr(Window, '_density') else 1
self.assertEqual(a.get(wid), 55 * density)
self.assertEqual(a.get_format(wid), 'dp')
a.set(wid, u'55dp')
self.assertEqual(a.get(wid), 55 * density)
self.assertEqual(a.get_format(wid), 'dp')
a.set(wid, '99in')
self.assertEqual(a.get(wid), 9504.0 * density)
self.assertEqual(a.get_format(wid), 'in')
a.set(wid, u'99in')
self.assertEqual(a.get(wid), 9504.0 * density)
self.assertEqual(a.get_format(wid), 'in')
def test_numeric_string_without_units(self):
from kivy.properties import NumericProperty
a = NumericProperty()
a.link(wid, 'a')
a.link_deps(wid, 'a')
self.assertEqual(a.get(wid), 0)
a.set(wid, '2')
self.assertEqual(a.get(wid), 2)
def test_property_rebind(self):
from kivy.uix.label import Label
from kivy.uix.togglebutton import ToggleButton
from kivy.lang import Builder
from kivy.properties import ObjectProperty, DictProperty, AliasProperty
from kivy.clock import Clock
class ObjWidget(Label):
button = ObjectProperty(None, rebind=True, allownone=True)
class ObjWidgetRebindFalse(Label):
button = ObjectProperty(None, rebind=False, allownone=True)
class DictWidget(Label):
button = DictProperty({'button': None}, rebind=True,
allownone=True)
class DictWidgetFalse(Label):
button = DictProperty({'button': None}, rebind=False)
class AliasWidget(Label):
_button = None
def setter(self, value):
self._button = value
return True
def getter(self):
return self._button
button = AliasProperty(getter, setter, rebind=True)
Builder.load_string('''
<ObjWidget>:
text: self.button.state if self.button is not None else 'Unset'
<ObjWidgetRebindFalse>:
text: self.button.state if self.button is not None else 'Unset'
<AliasWidget>:
text: self.button.state if self.button is not None else 'Unset'
<DictWidget>:
text: self.button.button.state if self.button.button is not None\
else 'Unset'
<DictWidgetFalse>:
text: self.button.button.state if self.button.button is not None\
else 'Unset'
''')
obj = ObjWidget()
obj_false = ObjWidgetRebindFalse()
dict_rebind = DictWidget()
dict_false = DictWidgetFalse()
alias_rebind = AliasWidget()
button = ToggleButton()
Clock.tick()
self.assertEqual(obj.text, 'Unset')
self.assertEqual(obj_false.text, 'Unset')
self.assertEqual(dict_rebind.text, 'Unset')
self.assertEqual(dict_false.text, 'Unset')
self.assertEqual(alias_rebind.text, 'Unset')
obj.button = button
obj_false.button = button
dict_rebind.button.button = button
dict_false.button.button = button
alias_rebind.button = button
Clock.tick()
self.assertEqual(obj.text, 'normal')
self.assertEqual(obj_false.text, 'normal')
self.assertEqual(dict_rebind.text, 'normal')
self.assertEqual(dict_false.text, 'Unset')
self.assertEqual(alias_rebind.text, 'normal')
button.state = 'down'
Clock.tick()
self.assertEqual(obj.text, 'down')
self.assertEqual(obj_false.text, 'normal')
self.assertEqual(dict_rebind.text, 'down')
self.assertEqual(dict_false.text, 'Unset')
self.assertEqual(alias_rebind.text, 'down')
button.state = 'normal'
Clock.tick()
self.assertEqual(obj.text, 'normal')
self.assertEqual(obj_false.text, 'normal')
self.assertEqual(dict_rebind.text, 'normal')
self.assertEqual(dict_false.text, 'Unset')
self.assertEqual(alias_rebind.text, 'normal')
obj.button = None
obj_false.button = None
dict_rebind.button.button = None
dict_false.button.button = None
alias_rebind.button = None
Clock.tick()
self.assertEqual(obj.text, 'Unset')
self.assertEqual(obj_false.text, 'Unset')
self.assertEqual(dict_rebind.text, 'Unset')
self.assertEqual(dict_false.text, 'Unset')
self.assertEqual(alias_rebind.text, 'Unset')
def test_color_property(self):
from kivy.properties import ColorProperty
color = ColorProperty()
color.link(wid, 'color')
color.link_deps(wid, 'color')
self.assertEqual(color.get(wid), [1, 1, 1, 1])
color2 = ColorProperty()
color2.link(wid, 'color2')
color2.link_deps(wid, 'color2')
self.assertEqual(color2.get(wid), [1, 1, 1, 1])
color.set(wid, 'yellow')
self.assertEqual(color.get(wid), [1.0, 1.0, 0.0, 1.0])
color.set(wid, "#00ff00")
self.assertEqual(color.get(wid), [0, 1, 0, 1])
color.set(wid, "#7f7fff7f")
self.assertEqual(color.get(wid)[0], 127 / 255.)
self.assertEqual(color.get(wid)[1], 127 / 255.)
self.assertEqual(color.get(wid)[2], 1)
self.assertEqual(color.get(wid)[3], 127 / 255.)
color.set(wid, (1, 1, 0))
self.assertEqual(color.get(wid), [1, 1, 0, 1])
color.set(wid, (1, 1, 0, 0))
self.assertEqual(color.get(wid), [1, 1, 0, 0])
color.set(wid, [1, 1, 1, 1])
color_value = color.get(wid)
color_value[0] = 0.5
self.assertEqual(color.get(wid), [0.5, 1, 1, 1])
self.assertEqual(color2.get(wid), [1, 1, 1, 1])
color2.set(wid, color.get(wid))
self.assertEqual(color2.get(wid), [0.5, 1, 1, 1])
color.set(wid, [1, 1, 1, 1])
color_value = color.get(wid)
color_value[:] = [0, 1, 0, 1]
self.assertEqual(color.get(wid), [0, 1, 0, 1])
def test_alias_property_without_setter(self):
from kivy.properties import AliasProperty
expected_value = 5
class CustomAlias(EventDispatcher):
def _get_prop(self):
self.getter_called += 1
return expected_value
prop = AliasProperty(_get_prop, None)
def __init__(self, **kwargs):
super(CustomAlias, self).__init__(**kwargs)
self.getter_called = 0
# Initial checks
wid = CustomAlias()
self.assertEqual(wid.getter_called, 0)
# Get value, should call getter once
value = wid.prop
self.assertEqual(value, expected_value)
self.assertEqual(wid.getter_called, 1)
# Setter should raise an AttributeError
self.assertRaises(AttributeError, partial(setattr, wid, 'prop', 1))
def test_alias_property(self):
from kivy.properties import AliasProperty
class CustomAlias(EventDispatcher):
def _get_prop(self):
self.getter_called += 1
def _set_prop(self, value):
self.setter_called += 1
prop = AliasProperty(_get_prop, _set_prop)
def __init__(self, **kwargs):
super(CustomAlias, self).__init__(**kwargs)
self.getter_called = 0
self.setter_called = 0
self.callback_called = 0
def callback(widget, value):
widget.callback_called += 1
# Initial checks
wid = CustomAlias()
wid.bind(prop=callback)
self.assertEqual(wid.getter_called, 0)
self.assertEqual(wid.setter_called, 0)
self.assertEqual(wid.callback_called, 0)
# Set property, should call setter to set the value
# Getter and callback should not be called because `_set_prop` doesn't
# returns True
wid.prop = 1
self.assertEqual(wid.getter_called, 0)
self.assertEqual(wid.setter_called, 1)
self.assertEqual(wid.callback_called, 0)
# Set property to same value as before, should only call setter
wid.prop = 1
self.assertEqual(wid.getter_called, 0)
self.assertEqual(wid.setter_called, 2)
self.assertEqual(wid.callback_called, 0)
# Get value of the property, should call getter once
self.assertEqual(wid.prop, None)
self.assertEqual(wid.getter_called, 1)
self.assertEqual(wid.setter_called, 2)
self.assertEqual(wid.callback_called, 0)
def test_alias_property_cache_true(self):
from kivy.properties import AliasProperty
expected_value = 5
class CustomAlias(EventDispatcher):
def _get_prop(self):
self.getter_called += 1
return expected_value
def _set_prop(self, value):
self.setter_called += 1
return True
prop = AliasProperty(_get_prop, _set_prop, cache=True)
def __init__(self, **kwargs):
super(CustomAlias, self).__init__(**kwargs)
self.getter_called = 0
self.setter_called = 0
# Initial checks
wid = CustomAlias()
self.assertEqual(wid.getter_called, 0)
self.assertEqual(wid.setter_called, 0)
# Get value of the property, should call getter once
value = wid.prop
self.assertEqual(value, expected_value)
self.assertEqual(wid.getter_called, 1)
self.assertEqual(wid.setter_called, 0)
# Get value of the property, should return cached value
# Getter should not be called
value = wid.prop
self.assertEqual(value, expected_value)
self.assertEqual(wid.getter_called, 1)
self.assertEqual(wid.setter_called, 0)
# Set value of property, should call getter and setter
wid.prop = 10
value = wid.prop
self.assertEqual(value, expected_value)
self.assertEqual(wid.setter_called, 1)
self.assertEqual(wid.getter_called, 2)
def test_alias_property_with_bind(self):
from kivy.properties import NumericProperty, AliasProperty
class CustomAlias(EventDispatcher):
x = NumericProperty(0)
width = NumericProperty(100)
def get_right(self):
return self.x + self.width
def set_right(self, value):
self.x = value - self.width
right = AliasProperty(get_right, set_right, bind=('x', 'width'))
def __init__(self, **kwargs):
super(CustomAlias, self).__init__(**kwargs)
self.callback_called = 0
# Assert values when setting x, width or right properties
wid = CustomAlias()
self.assertEqual(wid.right, 100)
wid.x = 500
self.assertEqual(wid.right, 600)
wid.width = 50
self.assertEqual(wid.right, 550)
wid.right = 100
self.assertEqual(wid.width, 50)
self.assertEqual(wid.x, 50)
def callback(widget, value):
widget.callback_called += 1
wid.bind(right=callback)
# Callback should be called only when property changes
wid.x = 100
self.assertEqual(wid.callback_called, 1)
wid.x = 100
self.assertEqual(wid.callback_called, 1)
wid.width = 900
self.assertEqual(wid.callback_called, 2)
wid.right = 700
self.assertEqual(wid.callback_called, 3)
wid.right = 700
self.assertEqual(wid.callback_called, 3)
def test_alias_property_with_force_dispatch_true(self):
from kivy.properties import AliasProperty
class CustomAlias(EventDispatcher):
def _get_prop(self):
self.getter_called += 1
def _set_prop(self, value):
self.setter_called += 1
prop = AliasProperty(_get_prop, _set_prop, force_dispatch=True)
def __init__(self, **kwargs):
super(CustomAlias, self).__init__(**kwargs)
self.getter_called = 0
self.setter_called = 0
self.callback_called = 0
def callback(widget, value):
widget.callback_called += 1
# Initial checks
wid = CustomAlias()
wid.bind(prop=callback)
self.assertEqual(wid.getter_called, 0)
self.assertEqual(wid.setter_called, 0)
self.assertEqual(wid.callback_called, 0)
# Set property, should call setter to set the value and getter to
# to get the value for dispatch call
wid.prop = 1
self.assertEqual(wid.getter_called, 1)
self.assertEqual(wid.setter_called, 1)
self.assertEqual(wid.callback_called, 1)
# Set property to same value as before, setter and getter and callback
# are called
wid.prop = 1
self.assertEqual(wid.getter_called, 2)
self.assertEqual(wid.setter_called, 2)
self.assertEqual(wid.callback_called, 2)
def test_alias_property_cache_true_with_bind(self):
from kivy.properties import NumericProperty, AliasProperty
class CustomAlias(EventDispatcher):
base_value = NumericProperty(1)
def _get_prop(self):
self.getter_called += 1
return self.base_value * 2
def _set_prop(self, value):
self.base_value = value / 2
prop = AliasProperty(_get_prop, _set_prop,
bind=('base_value',),
cache=True)
def __init__(self, **kwargs):
super(CustomAlias, self).__init__(**kwargs)
self.getter_called = 0
# Initial checks
wid = CustomAlias()
self.assertEqual(wid.getter_called, 0)
self.assertEqual(wid.base_value, 1)
self.assertEqual(wid.getter_called, 0)
# Change the base value, should trigger an update for the cache
wid.base_value = 4
self.assertEqual(wid.getter_called, 1)
# Now read the value again, should use the cache
self.assertEqual(wid.prop, 8)
self.assertEqual(wid.getter_called, 1)
# Change the prop itself, should trigger an update for the cache
wid.prop = 4
self.assertEqual(wid.getter_called, 2)
self.assertEqual(wid.base_value, 2)
self.assertEqual(wid.prop, 4)
self.assertEqual(wid.getter_called, 2)
def test_alias_property_cache_true_force_dispatch_true(self):
from kivy.properties import AliasProperty
class CustomAlias(EventDispatcher):
def _get_prop(self):
self.getter_called += 1
return self.base_value * 2
def _set_prop(self, value):
self.setter_called += 1
self.base_value = value / 2
return True
prop = AliasProperty(_get_prop, _set_prop,
cache=True,
force_dispatch=True)
def __init__(self, **kwargs):
super(CustomAlias, self).__init__(**kwargs)
self.base_value = 1
self.getter_called = 0
self.setter_called = 0
self.callback_called = 0
def callback(widget, value):
widget.callback_called += 1
wid = CustomAlias()
wid.bind(prop=callback)
# Initial checks
self.assertEqual(wid.base_value, 1)
self.assertEqual(wid.getter_called, 0)
self.assertEqual(wid.setter_called, 0)
self.assertEqual(wid.callback_called, 0)
# Set alias property some value, should call setter and then getter to
# pass the value to callback
wid.prop = 16
self.assertEqual(wid.base_value, 8)
self.assertEqual(wid.getter_called, 1)
self.assertEqual(wid.setter_called, 1)
self.assertEqual(wid.callback_called, 1)
# Same as the step above, should call setter, getter and callback
wid.prop = 16
self.assertEqual(wid.base_value, 8)
self.assertEqual(wid.getter_called, 2)
self.assertEqual(wid.setter_called, 2)
self.assertEqual(wid.callback_called, 2)
# Get the value of property, should use cached value
value = wid.prop
self.assertEqual(value, 16)
self.assertEqual(wid.getter_called, 2)
self.assertEqual(wid.setter_called, 2)
self.assertEqual(wid.callback_called, 2)
def test_dictproperty_is_none():
from kivy.properties import DictProperty
d1 = DictProperty(None)
d1.link(wid, 'd1')
assert d1.get(wid) is None
d2 = DictProperty({'a': 1, 'b': 2}, allownone=True)
d2.link(wid, 'd2')
d2.set(wid, None)
assert d2.get(wid) is None
def test_listproperty_is_none():
from kivy.properties import ListProperty
l1 = ListProperty(None)
l1.link(wid, 'l1')
assert l1.get(wid) is None
l2 = ListProperty([1, 2, 3], allownone=True)
l2.link(wid, 'l2')
l2.set(wid, None)
assert l2.get(wid) is None