summaryrefslogtreecommitdiff
path: root/Cython/Tests/TestCythonUtils.py
diff options
context:
space:
mode:
Diffstat (limited to 'Cython/Tests/TestCythonUtils.py')
-rw-r--r--Cython/Tests/TestCythonUtils.py121
1 files changed, 119 insertions, 2 deletions
diff --git a/Cython/Tests/TestCythonUtils.py b/Cython/Tests/TestCythonUtils.py
index 2641900c0..402616101 100644
--- a/Cython/Tests/TestCythonUtils.py
+++ b/Cython/Tests/TestCythonUtils.py
@@ -1,11 +1,128 @@
import unittest
-from ..Utils import build_hex_version
+from Cython.Utils import (
+ _CACHE_NAME_PATTERN, _build_cache_name, _find_cache_attributes,
+ build_hex_version, cached_method, clear_method_caches, try_finally_contextmanager)
+
+METHOD_NAME = "cached_next"
+CACHE_NAME = _build_cache_name(METHOD_NAME)
+NAMES = CACHE_NAME, METHOD_NAME
+
+class Cached(object):
+ @cached_method
+ def cached_next(self, x):
+ return next(x)
+
class TestCythonUtils(unittest.TestCase):
def test_build_hex_version(self):
self.assertEqual('0x001D00A1', build_hex_version('0.29a1'))
- self.assertEqual('0x001D00A1', build_hex_version('0.29a1'))
self.assertEqual('0x001D03C4', build_hex_version('0.29.3rc4'))
self.assertEqual('0x001D00F0', build_hex_version('0.29'))
self.assertEqual('0x040000F0', build_hex_version('4.0'))
+
+ ############################## Cached Methods ##############################
+
+ def test_cache_method_name(self):
+ method_name = "foo"
+ cache_name = _build_cache_name(method_name)
+ match = _CACHE_NAME_PATTERN.match(cache_name)
+
+ self.assertIsNot(match, None)
+ self.assertEqual(match.group(1), method_name)
+
+ def test_requirements_for_Cached(self):
+ obj = Cached()
+
+ self.assertFalse(hasattr(obj, CACHE_NAME))
+ self.assertTrue(hasattr(obj, METHOD_NAME))
+ self.set_of_names_equal(obj, set())
+
+ def set_of_names_equal(self, obj, value):
+ self.assertEqual(set(_find_cache_attributes(obj)), value)
+
+ def test_find_cache_attributes(self):
+ obj = Cached()
+ method_name = "bar"
+ cache_name = _build_cache_name(method_name)
+
+ setattr(obj, CACHE_NAME, {})
+ setattr(obj, cache_name, {})
+
+ self.assertFalse(hasattr(obj, method_name))
+ self.set_of_names_equal(obj, {NAMES, (cache_name, method_name)})
+
+ def test_cached_method(self):
+ obj = Cached()
+ value = iter(range(3)) # iter for Py2
+ cache = {(value,): 0}
+
+ # cache args
+ self.assertEqual(obj.cached_next(value), 0)
+ self.set_of_names_equal(obj, {NAMES})
+ self.assertEqual(getattr(obj, CACHE_NAME), cache)
+
+ # use cache
+ self.assertEqual(obj.cached_next(value), 0)
+ self.set_of_names_equal(obj, {NAMES})
+ self.assertEqual(getattr(obj, CACHE_NAME), cache)
+
+ def test_clear_method_caches(self):
+ obj = Cached()
+ value = iter(range(3)) # iter for Py2
+ cache = {(value,): 1}
+
+ obj.cached_next(value) # cache args
+
+ clear_method_caches(obj)
+ self.set_of_names_equal(obj, set())
+
+ self.assertEqual(obj.cached_next(value), 1)
+ self.set_of_names_equal(obj, {NAMES})
+ self.assertEqual(getattr(obj, CACHE_NAME), cache)
+
+ def test_clear_method_caches_with_missing_method(self):
+ obj = Cached()
+ method_name = "bar"
+ cache_name = _build_cache_name(method_name)
+ names = cache_name, method_name
+
+ setattr(obj, cache_name, object())
+
+ self.assertFalse(hasattr(obj, method_name))
+ self.set_of_names_equal(obj, {names})
+
+ clear_method_caches(obj)
+ self.set_of_names_equal(obj, {names})
+
+ def test_try_finally_contextmanager(self):
+ states = []
+ @try_finally_contextmanager
+ def gen(*args, **kwargs):
+ states.append("enter")
+ yield (args, kwargs)
+ states.append("exit")
+
+ with gen(1, 2, 3, x=4) as call_args:
+ assert states == ["enter"]
+ self.assertEqual(call_args, ((1, 2, 3), {'x': 4}))
+ assert states == ["enter", "exit"]
+
+ class MyException(RuntimeError):
+ pass
+
+ del states[:]
+ with self.assertRaises(MyException):
+ with gen(1, 2, y=4) as call_args:
+ assert states == ["enter"]
+ self.assertEqual(call_args, ((1, 2), {'y': 4}))
+ raise MyException("FAIL INSIDE")
+ assert states == ["enter", "exit"]
+
+ del states[:]
+ with self.assertRaises(StopIteration):
+ with gen(1, 2, y=4) as call_args:
+ assert states == ["enter"]
+ self.assertEqual(call_args, ((1, 2), {'y': 4}))
+ raise StopIteration("STOP")
+ assert states == ["enter", "exit"]