277 lines
8.1 KiB
Python
277 lines
8.1 KiB
Python
# Copyright 2020 Red Hat
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
# not use this file except in compliance with the License. You may obtain
|
|
# a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
# License for the specific language governing permissions and limitations
|
|
# under the License.
|
|
from __future__ import absolute_import
|
|
|
|
import typing # noqa
|
|
|
|
import tobiko
|
|
from tobiko.tests import unit
|
|
|
|
|
|
NOT_CALLED = object()
|
|
|
|
|
|
class TestCached(unit.TobikoUnitTest):
|
|
|
|
my_property = tobiko.cached(doc='some doc')
|
|
|
|
def test_init(self):
|
|
prop = type(self).my_property
|
|
self.assertIsNone(prop.fget)
|
|
self.assertIsNone(prop.fset)
|
|
self.assertIsNone(prop.fdel)
|
|
self.assertEqual('some doc', prop.__doc__)
|
|
self.assertTrue(prop.cached_id)
|
|
|
|
def test_get(self):
|
|
ex = self.assertRaises(AttributeError, lambda: self.my_property)
|
|
self.assertEqual("Cached property has no getter method", str(ex))
|
|
|
|
def test_set(self):
|
|
self.my_property = value = object()
|
|
self.assertIs(value, self.my_property)
|
|
|
|
def test_delete(self):
|
|
self.my_property = object()
|
|
del self.my_property
|
|
ex = self.assertRaises(AttributeError, lambda: self.my_property)
|
|
self.assertEqual("Cached property has no getter method", str(ex))
|
|
|
|
|
|
class TestCachedWithGetter(unit.TobikoUnitTest):
|
|
|
|
@tobiko.cached
|
|
def my_property(self):
|
|
return object()
|
|
|
|
def test_init(self):
|
|
# pylint: disable=no-member
|
|
prop = type(self).my_property
|
|
assert isinstance(prop, tobiko.CachedProperty)
|
|
self.assertTrue(callable(prop.fget))
|
|
self.assertIsNone(prop.fset)
|
|
self.assertIsNone(prop.fdel)
|
|
self.assertIs(prop.fget.__doc__, prop.__doc__)
|
|
self.assertTrue(prop.cached_id)
|
|
|
|
def test_get(self):
|
|
value = self.my_property
|
|
self.assertIs(value, self.my_property)
|
|
|
|
def test_set(self):
|
|
self.my_property = value = object()
|
|
self.assertIs(value, self.my_property)
|
|
|
|
def test_delete(self):
|
|
self.my_property = value = object()
|
|
del self.my_property
|
|
self.assertIsNot(value, self.my_property)
|
|
|
|
|
|
class TestCachedWithSetter(unit.TobikoUnitTest):
|
|
|
|
_set_value = None
|
|
|
|
def set_my_property(self, value):
|
|
self._set_value = value
|
|
|
|
my_property = tobiko.cached(fset=set_my_property)
|
|
|
|
def test_init(self):
|
|
prop = type(self).my_property
|
|
self.assertIsNone(prop.fget)
|
|
self.assertIs(type(self).set_my_property, prop.fset)
|
|
self.assertIsNone(prop.fdel)
|
|
self.assertIsNone(prop.__doc__)
|
|
self.assertTrue(prop.cached_id)
|
|
|
|
def test_get(self):
|
|
self.assertFalse(hasattr(self, 'my_property'))
|
|
self.assertIsNone(self._set_value)
|
|
|
|
def test_set(self):
|
|
self.my_property = value = object()
|
|
self.assertIs(value, self.my_property)
|
|
self.assertIs(value, self._set_value)
|
|
|
|
def test_delete(self):
|
|
self.my_property = object()
|
|
del self.my_property
|
|
self.assertFalse(hasattr(self, 'my_property'))
|
|
|
|
|
|
class TestCachedWithDeleter(unit.TobikoUnitTest):
|
|
|
|
_delete_value = None
|
|
|
|
def delete_my_property(self):
|
|
self._delete_value = object()
|
|
|
|
my_property = tobiko.cached(fdel=delete_my_property)
|
|
|
|
def test_init(self):
|
|
prop = type(self).my_property
|
|
self.assertIsNone(prop.fget)
|
|
self.assertIsNone(prop.fset)
|
|
self.assertIs(type(self).delete_my_property, prop.fdel)
|
|
self.assertIsNone(prop.__doc__)
|
|
self.assertTrue(prop.cached_id)
|
|
|
|
def test_get(self):
|
|
self.assertFalse(hasattr(self, 'my_property'))
|
|
self.assertIsNone(self._delete_value)
|
|
|
|
def test_set(self):
|
|
self.my_property = value = object()
|
|
self.assertIs(value, self.my_property)
|
|
self.assertIsNone(self._delete_value)
|
|
|
|
def test_delete(self):
|
|
self.my_property = object()
|
|
del self.my_property
|
|
self.assertFalse(hasattr(self, 'my_property'))
|
|
self.assertIsNotNone(self._delete_value)
|
|
|
|
|
|
class TestCachedWithDoc(unit.TobikoUnitTest):
|
|
|
|
my_doc = 'some doc'
|
|
|
|
my_property = tobiko.cached(doc=my_doc)
|
|
|
|
@my_property.getter
|
|
def get_my_property(self):
|
|
return object()
|
|
|
|
def test_init(self):
|
|
prop = type(self).my_property
|
|
self.assertTrue(callable(prop.fget))
|
|
self.assertIsNone(prop.fset)
|
|
self.assertIsNone(prop.fdel)
|
|
self.assertIs(self.my_doc, prop.__doc__)
|
|
self.assertTrue(prop.cached_id)
|
|
|
|
|
|
class TestCachedWithCachedId(unit.TobikoUnitTest):
|
|
|
|
cached_id = 'my_cached_id'
|
|
|
|
my_property = tobiko.cached(cached_id=cached_id)
|
|
|
|
@my_property.getter
|
|
def get_my_property(self):
|
|
return object()
|
|
|
|
def test_init(self):
|
|
prop = type(self).my_property
|
|
self.assertTrue(callable(prop.fget))
|
|
self.assertIsNone(prop.fset)
|
|
self.assertIsNone(prop.fdel)
|
|
self.assertIsNone(prop.__doc__)
|
|
self.assertEqual(self.cached_id, prop.cached_id)
|
|
self.assertFalse(hasattr(self, 'my_cached_id'))
|
|
|
|
def test_get(self):
|
|
# pylint: disable=no-member
|
|
value = self.my_property
|
|
self.assertIs(value, self.my_property)
|
|
self.assertIs(value, self.my_cached_id)
|
|
|
|
def test_set(self):
|
|
# pylint: disable=no-member
|
|
self.my_property = value = object()
|
|
self.assertIs(value, self.my_property)
|
|
self.assertIs(value, self.my_cached_id)
|
|
|
|
def test_delete(self):
|
|
# pylint: disable=no-member
|
|
self.my_property = value = object()
|
|
del self.my_property
|
|
self.assertIsNot(value, self.my_property)
|
|
self.assertIsNot(value, self.my_cached_id)
|
|
|
|
|
|
class TestCachedWithDecorators(unit.TobikoUnitTest):
|
|
|
|
my_property = tobiko.cached()
|
|
|
|
getter_called = 0
|
|
|
|
@my_property.getter
|
|
def getter(self):
|
|
"""Getter documentation"""
|
|
self.getter_called += 1
|
|
return object()
|
|
|
|
setter_called = tuple() # type: typing.Tuple
|
|
|
|
@my_property.setter
|
|
def setter(self, value):
|
|
self.setter_called += (value,)
|
|
|
|
deleter_called = 0
|
|
|
|
@my_property.deleter
|
|
def deleter(self):
|
|
self.deleter_called += 1
|
|
|
|
def test_init(self):
|
|
# self.my_property method not called yet
|
|
prop = type(self).my_property
|
|
self.assertIs(type(self).getter, prop.fget)
|
|
self.assertIs(type(self).setter, prop.fset)
|
|
self.assertIs(type(self).deleter, prop.fdel)
|
|
self.assertIs(self.getter.__doc__, prop.__doc__)
|
|
self.assertTrue(prop.cached_id)
|
|
|
|
def test_get(self):
|
|
# my_property method is called
|
|
prop = type(self).my_property
|
|
value = self.my_property
|
|
self.assertEqual(1, self.getter_called)
|
|
self.assertIs(value, getattr(self, prop.cached_id))
|
|
self.assertEqual((value,), self.setter_called)
|
|
return value
|
|
|
|
def test_get_twice(self):
|
|
# my_property method is not called again
|
|
value1 = self.test_get()
|
|
value2 = self.test_get()
|
|
self.assertIs(value1, value2)
|
|
|
|
def test_set(self):
|
|
# property value is stored into the object
|
|
prop = type(self).my_property
|
|
self.my_property = value = object()
|
|
self.assertIs(value, self.my_property)
|
|
self.assertEqual(0, self.getter_called)
|
|
self.assertEqual(value, self.setter_called[-1])
|
|
self.assertIs(value, getattr(self, prop.cached_id))
|
|
return value
|
|
|
|
def test_set_twice(self):
|
|
# stored value is got after setting
|
|
value1 = self.test_set()
|
|
value2 = self.test_set()
|
|
self.assertIsNot(value1, value2)
|
|
|
|
def test_delete(self):
|
|
# deleting remove stored value
|
|
prop = type(self).my_property
|
|
value = self.test_set()
|
|
del self.my_property
|
|
self.assertFalse(hasattr(self, prop.cached_id))
|
|
self.assertIsNot(value, self.my_property)
|
|
self.assertEqual(1, self.deleter_called)
|