diff --git a/test/tree/general/base.py b/test/tree/general/base.py index 7330c00f00..14189a5005 100644 --- a/test/tree/general/base.py +++ b/test/tree/general/base.py @@ -5,10 +5,11 @@ import numpy as np import pytest -from treevalue.tree import func_treelize, TreeValue, raw, mapping, delayed +from treevalue.tree import func_treelize, TreeValue, raw, mapping, delayed, FastTreeValue +from ..tree.base import get_treevalue_test -def get_tree_test(tree_value_clazz: Type[TreeValue]): +def get_fasttreevalue_test(treevalue_class: Type[FastTreeValue]): class Container: def __init__(self, value): self.__value = value @@ -36,18 +37,18 @@ def __repr__(self): # noinspection DuplicatedCode,PyMethodMayBeStatic @pytest.mark.unittest - class _TestClass: + class _TestClass(get_treevalue_test(treevalue_class)): def test_basic_methods(self): - t3 = tree_value_clazz({'a': 14, 'b': 26, 'x': {'c': 38, 'd': 11}}) + t3 = treevalue_class({'a': 14, 'b': 26, 'x': {'c': 38, 'd': 11}}) assert t3.json() == {'a': 14, 'b': 26, 'x': {'c': 38, 'd': 11}} t5 = t3.x.clone() - assert t5 == tree_value_clazz({'c': 38, 'd': 11}) + assert t5 == treevalue_class({'c': 38, 'd': 11}) def test_numeric_add(self): - t1 = tree_value_clazz({'a': 1, 'b': 2, 'x': {'c': 3, 'd': 4}}) - t2 = tree_value_clazz({'a': 11, 'b': 22, 'x': {'c': 33, 'd': 5}}) - assert (2 + t1 + t2) == tree_value_clazz({'a': 14, 'b': 26, 'x': {'c': 38, 'd': 11}}) + t1 = treevalue_class({'a': 1, 'b': 2, 'x': {'c': 3, 'd': 4}}) + t2 = treevalue_class({'a': 11, 'b': 22, 'x': {'c': 33, 'd': 5}}) + assert (2 + t1 + t2) == treevalue_class({'a': 14, 'b': 26, 'x': {'c': 38, 'd': 11}}) original_id = id(t1._detach()) original_id_x = id(t1.x._detach()) @@ -58,9 +59,9 @@ def test_numeric_add(self): assert id(t1.x._detach()) == original_id_x def test_numeric_sub(self): - t1 = tree_value_clazz({'a': 1, 'b': 2, 'x': {'c': 3, 'd': 4}}) - t2 = tree_value_clazz({'a': 11, 'b': 22, 'x': {'c': 33, 'd': 5}}) - assert (2 - t1 - t2) == tree_value_clazz({'a': -10, 'b': -22, 'x': {'c': -34, 'd': -7}}) + t1 = treevalue_class({'a': 1, 'b': 2, 'x': {'c': 3, 'd': 4}}) + t2 = treevalue_class({'a': 11, 'b': 22, 'x': {'c': 33, 'd': 5}}) + assert (2 - t1 - t2) == treevalue_class({'a': -10, 'b': -22, 'x': {'c': -34, 'd': -7}}) original_id = id(t1._detach()) original_id_x = id(t1.x._detach()) @@ -71,18 +72,18 @@ def test_numeric_sub(self): assert id(t1.x._detach()) == original_id_x def test_numeric_mul(self): - t1 = tree_value_clazz({'a': 1, 'b': 2, 'x': {'c': 3, 'd': 4}}) - t2 = tree_value_clazz({'a': 11, 'b': 22, 'x': {'c': 33, 'd': 5}}) - assert (2 * t1 * t2) == tree_value_clazz({'a': 22, 'b': 88, 'x': {'c': 198, 'd': 40}}) + t1 = treevalue_class({'a': 1, 'b': 2, 'x': {'c': 3, 'd': 4}}) + t2 = treevalue_class({'a': 11, 'b': 22, 'x': {'c': 33, 'd': 5}}) + assert (2 * t1 * t2) == treevalue_class({'a': 22, 'b': 88, 'x': {'c': 198, 'd': 40}}) i, j = 1, 1.0 assert i.__mul__(j) == NotImplemented assert j.__mul__(i) == 1.0 assert i * j == j.__mul__(i) - t3 = tree_value_clazz({'a': 11, 'b': 22, 'x': {'c': 33, 'd': 5.2}}) - assert (t1 * t3) == tree_value_clazz({'a': 11, 'b': 44, 'x': {'c': 99, 'd': 20.8}}) - assert (t3 * t1) == tree_value_clazz({'a': 11, 'b': 44, 'x': {'c': 99, 'd': 20.8}}) + t3 = treevalue_class({'a': 11, 'b': 22, 'x': {'c': 33, 'd': 5.2}}) + assert (t1 * t3) == treevalue_class({'a': 11, 'b': 44, 'x': {'c': 99, 'd': 20.8}}) + assert (t3 * t1) == treevalue_class({'a': 11, 'b': 44, 'x': {'c': 99, 'd': 20.8}}) original_id = id(t1._detach()) original_id_x = id(t1.x._detach()) @@ -93,7 +94,7 @@ def test_numeric_mul(self): assert id(t1.x._detach()) == original_id_x def test_numeric_matmul(self): - t1 = tree_value_clazz({ + t1 = treevalue_class({ 'a': np.array([[1, 2], [3, 4]]), 'b': np.array([[2, 3], [4, 5]]), 'x': { @@ -101,7 +102,7 @@ def test_numeric_matmul(self): 'd': np.array([[4, 5], [6, 7]]), } }) - t2 = tree_value_clazz({ + t2 = treevalue_class({ 'a': np.array([[4, 5], [6, 7]]), 'b': np.array([[3, 4], [5, 6]]), 'x': { @@ -110,15 +111,15 @@ def test_numeric_matmul(self): } }) - tnp_array_equal = func_treelize(return_type=tree_value_clazz)(np.array_equal) - assert tnp_array_equal((t1 @ t2), tree_value_clazz({ + tnp_array_equal = func_treelize(return_type=treevalue_class)(np.array_equal) + assert tnp_array_equal((t1 @ t2), treevalue_class({ 'a': np.array([[1, 2], [3, 4]]) @ np.array([[4, 5], [6, 7]]), 'b': np.array([[2, 3], [4, 5]]) @ np.array([[3, 4], [5, 6]]), 'x': { 'c': np.array([[3, 4], [5, 6]]) @ np.array([[2, 3], [4, 5]]), 'd': np.array([[4, 5], [6, 7]]) @ np.array([[1, 2], [3, 4]]), } - })) == tree_value_clazz({ + })) == treevalue_class({ 'a': True, 'b': True, 'x': { @@ -127,7 +128,7 @@ def test_numeric_matmul(self): } }) assert tnp_array_equal( - (t2.__rmatmul__(np.array([[1, 2], [3, 4]]))), tree_value_clazz({ + (t2.__rmatmul__(np.array([[1, 2], [3, 4]]))), treevalue_class({ 'a': np.array([[1, 2], [3, 4]]) @ np.array([[4, 5], [6, 7]]), 'b': np.array([[1, 2], [3, 4]]) @ np.array([[3, 4], [5, 6]]), 'x': { @@ -135,7 +136,7 @@ def test_numeric_matmul(self): 'd': np.array([[1, 2], [3, 4]]) @ np.array([[1, 2], [3, 4]]), } }) - ) == tree_value_clazz({ + ) == treevalue_class({ 'a': True, 'b': True, 'x': { @@ -180,10 +181,10 @@ def __imatmul__(self, other): assert id(tt1.x._detach()) == original_id_x def test_numeric_floordiv(self): - t1 = tree_value_clazz({'a': 1, 'b': 2, 'x': {'c': 3, 'd': 4}}) - t2 = tree_value_clazz({'a': 11, 'b': 22, 'x': {'c': 33, 'd': 5}}) - assert (t2 / t1) == tree_value_clazz({'a': 11.0, 'b': 11.0, 'x': {'c': 11.0, 'd': 1.25}}) - assert (6 / t1) == tree_value_clazz({'a': 6.0, 'b': 3.0, 'x': {'c': 2.0, 'd': 1.5}}) + t1 = treevalue_class({'a': 1, 'b': 2, 'x': {'c': 3, 'd': 4}}) + t2 = treevalue_class({'a': 11, 'b': 22, 'x': {'c': 33, 'd': 5}}) + assert (t2 / t1) == treevalue_class({'a': 11.0, 'b': 11.0, 'x': {'c': 11.0, 'd': 1.25}}) + assert (6 / t1) == treevalue_class({'a': 6.0, 'b': 3.0, 'x': {'c': 2.0, 'd': 1.5}}) original_id = id(t1._detach()) original_id_x = id(t1.x._detach()) @@ -194,10 +195,10 @@ def test_numeric_floordiv(self): assert id(t1.x._detach()) == original_id_x def test_numeric_truediv(self): - t1 = tree_value_clazz({'a': 1, 'b': 2, 'x': {'c': 3, 'd': 4}}) - t2 = tree_value_clazz({'a': 11, 'b': 22, 'x': {'c': 33, 'd': 5}}) - assert (t2 // t1) == tree_value_clazz({'a': 11, 'b': 11, 'x': {'c': 11, 'd': 1}}) - assert (6 // t1) == tree_value_clazz({'a': 6, 'b': 3, 'x': {'c': 2, 'd': 1}}) + t1 = treevalue_class({'a': 1, 'b': 2, 'x': {'c': 3, 'd': 4}}) + t2 = treevalue_class({'a': 11, 'b': 22, 'x': {'c': 33, 'd': 5}}) + assert (t2 // t1) == treevalue_class({'a': 11, 'b': 11, 'x': {'c': 11, 'd': 1}}) + assert (6 // t1) == treevalue_class({'a': 6, 'b': 3, 'x': {'c': 2, 'd': 1}}) original_id = id(t1._detach()) original_id_x = id(t1.x._detach()) @@ -208,10 +209,10 @@ def test_numeric_truediv(self): assert id(t1.x._detach()) == original_id_x def test_numeric_mod(self): - t1 = tree_value_clazz({'a': 1, 'b': 2, 'x': {'c': 3, 'd': 4}}) - t2 = tree_value_clazz({'a': 11, 'b': 22, 'x': {'c': 33, 'd': 5}}) - assert (t2 % t1) == tree_value_clazz({'a': 0, 'b': 0, 'x': {'c': 0, 'd': 1}}) - assert (6 % t1) == tree_value_clazz({'a': 0, 'b': 0, 'x': {'c': 0, 'd': 2}}) + t1 = treevalue_class({'a': 1, 'b': 2, 'x': {'c': 3, 'd': 4}}) + t2 = treevalue_class({'a': 11, 'b': 22, 'x': {'c': 33, 'd': 5}}) + assert (t2 % t1) == treevalue_class({'a': 0, 'b': 0, 'x': {'c': 0, 'd': 1}}) + assert (6 % t1) == treevalue_class({'a': 0, 'b': 0, 'x': {'c': 0, 'd': 2}}) original_id = id(t2._detach()) original_id_x = id(t2.x._detach()) @@ -222,9 +223,9 @@ def test_numeric_mod(self): assert id(t2.x._detach()) == original_id_x def test_numeric_power(self): - t1 = tree_value_clazz({'a': 1, 'b': 2, 'x': {'c': 3, 'd': 4}}) - assert (t1 ** t1) == tree_value_clazz({'a': 1, 'b': 4, 'x': {'c': 27, 'd': 256}}) - assert (2 ** t1) == tree_value_clazz({'a': 2, 'b': 4, 'x': {'c': 8, 'd': 16}}) + t1 = treevalue_class({'a': 1, 'b': 2, 'x': {'c': 3, 'd': 4}}) + assert (t1 ** t1) == treevalue_class({'a': 1, 'b': 4, 'x': {'c': 27, 'd': 256}}) + assert (2 ** t1) == treevalue_class({'a': 2, 'b': 4, 'x': {'c': 8, 'd': 16}}) original_id = id(t1._detach()) original_id_x = id(t1.x._detach()) @@ -235,10 +236,10 @@ def test_numeric_power(self): assert id(t1.x._detach()) == original_id_x def test_numeric_and(self): - t1 = tree_value_clazz({'a': 1, 'b': 2, 'x': {'c': 3, 'd': 4}}) - t2 = tree_value_clazz({'a': 11, 'b': 22, 'x': {'c': 33, 'd': 5}}) - assert (t1 & t2) == tree_value_clazz({'a': 1, 'b': 2, 'x': {'c': 1, 'd': 4}}) - assert (7 & t2) == tree_value_clazz({'a': 3, 'b': 6, 'x': {'c': 1, 'd': 5}}) + t1 = treevalue_class({'a': 1, 'b': 2, 'x': {'c': 3, 'd': 4}}) + t2 = treevalue_class({'a': 11, 'b': 22, 'x': {'c': 33, 'd': 5}}) + assert (t1 & t2) == treevalue_class({'a': 1, 'b': 2, 'x': {'c': 1, 'd': 4}}) + assert (7 & t2) == treevalue_class({'a': 3, 'b': 6, 'x': {'c': 1, 'd': 5}}) original_id = id(t1._detach()) original_id_x = id(t1.x._detach()) @@ -249,10 +250,10 @@ def test_numeric_and(self): assert id(t1.x._detach()) == original_id_x def test_numeric_or(self): - t1 = tree_value_clazz({'a': 1, 'b': 2, 'x': {'c': 3, 'd': 4}}) - t2 = tree_value_clazz({'a': 11, 'b': 22, 'x': {'c': 33, 'd': 5}}) - assert (t1 | t2) == tree_value_clazz({'a': 11, 'b': 22, 'x': {'c': 35, 'd': 5}}) - assert (7 | t2) == tree_value_clazz({'a': 15, 'b': 23, 'x': {'c': 39, 'd': 7}}) + t1 = treevalue_class({'a': 1, 'b': 2, 'x': {'c': 3, 'd': 4}}) + t2 = treevalue_class({'a': 11, 'b': 22, 'x': {'c': 33, 'd': 5}}) + assert (t1 | t2) == treevalue_class({'a': 11, 'b': 22, 'x': {'c': 35, 'd': 5}}) + assert (7 | t2) == treevalue_class({'a': 15, 'b': 23, 'x': {'c': 39, 'd': 7}}) original_id = id(t1._detach()) original_id_x = id(t1.x._detach()) @@ -263,10 +264,10 @@ def test_numeric_or(self): assert id(t1.x._detach()) == original_id_x def test_numeric_xor(self): - t1 = tree_value_clazz({'a': 1, 'b': 2, 'x': {'c': 3, 'd': 4}}) - t2 = tree_value_clazz({'a': 11, 'b': 22, 'x': {'c': 33, 'd': 5}}) - assert (t1 ^ t2) == tree_value_clazz({'a': 10, 'b': 20, 'x': {'c': 34, 'd': 1}}) - assert (7 ^ t2) == tree_value_clazz({'a': 12, 'b': 17, 'x': {'c': 38, 'd': 2}}) + t1 = treevalue_class({'a': 1, 'b': 2, 'x': {'c': 3, 'd': 4}}) + t2 = treevalue_class({'a': 11, 'b': 22, 'x': {'c': 33, 'd': 5}}) + assert (t1 ^ t2) == treevalue_class({'a': 10, 'b': 20, 'x': {'c': 34, 'd': 1}}) + assert (7 ^ t2) == treevalue_class({'a': 12, 'b': 17, 'x': {'c': 38, 'd': 2}}) original_id = id(t1._detach()) original_id_x = id(t1.x._detach()) @@ -277,10 +278,10 @@ def test_numeric_xor(self): assert id(t1.x._detach()) == original_id_x def test_numeric_lshift(self): - t1 = tree_value_clazz({'a': 1, 'b': 2, 'x': {'c': 3, 'd': 4}}) - t2 = tree_value_clazz({'a': 11, 'b': 22, 'x': {'c': 33, 'd': 5}}) - assert (t2 << t1) == tree_value_clazz({'a': 22, 'b': 88, 'x': {'c': 264, 'd': 80}}) - assert (3 << t1) == tree_value_clazz({'a': 6, 'b': 12, 'x': {'c': 24, 'd': 48}}) + t1 = treevalue_class({'a': 1, 'b': 2, 'x': {'c': 3, 'd': 4}}) + t2 = treevalue_class({'a': 11, 'b': 22, 'x': {'c': 33, 'd': 5}}) + assert (t2 << t1) == treevalue_class({'a': 22, 'b': 88, 'x': {'c': 264, 'd': 80}}) + assert (3 << t1) == treevalue_class({'a': 6, 'b': 12, 'x': {'c': 24, 'd': 48}}) original_id = id(t2._detach()) original_id_x = id(t2.x._detach()) @@ -291,10 +292,10 @@ def test_numeric_lshift(self): assert id(t2.x._detach()) == original_id_x def test_numeric_rshift(self): - t1 = tree_value_clazz({'a': 1, 'b': 2, 'x': {'c': 3, 'd': 4}}) - t2 = tree_value_clazz({'a': 11, 'b': 22, 'x': {'c': 33, 'd': 5}}) - assert (t2 >> t1) == tree_value_clazz({'a': 5, 'b': 5, 'x': {'c': 4, 'd': 0}}) - assert (32 >> t1) == tree_value_clazz({'a': 16, 'b': 8, 'x': {'c': 4, 'd': 2}}) + t1 = treevalue_class({'a': 1, 'b': 2, 'x': {'c': 3, 'd': 4}}) + t2 = treevalue_class({'a': 11, 'b': 22, 'x': {'c': 33, 'd': 5}}) + assert (t2 >> t1) == treevalue_class({'a': 5, 'b': 5, 'x': {'c': 4, 'd': 0}}) + assert (32 >> t1) == treevalue_class({'a': 16, 'b': 8, 'x': {'c': 4, 'd': 2}}) original_id = id(t2._detach()) original_id_x = id(t2.x._detach()) @@ -305,30 +306,30 @@ def test_numeric_rshift(self): assert id(t2.x._detach()) == original_id_x def test_numeric_pos(self): - t1 = tree_value_clazz({'a': 1, 'b': 2, 'x': {'c': 3, 'd': 4}}) - assert +t1 == tree_value_clazz({'a': 1, 'b': 2, 'x': {'c': 3, 'd': 4}}) + t1 = treevalue_class({'a': 1, 'b': 2, 'x': {'c': 3, 'd': 4}}) + assert +t1 == treevalue_class({'a': 1, 'b': 2, 'x': {'c': 3, 'd': 4}}) def test_numeric_neg(self): - t1 = tree_value_clazz({'a': 1, 'b': 2, 'x': {'c': 3, 'd': 4}}) - assert -t1 == tree_value_clazz({'a': -1, 'b': -2, 'x': {'c': -3, 'd': -4}}) + t1 = treevalue_class({'a': 1, 'b': 2, 'x': {'c': 3, 'd': 4}}) + assert -t1 == treevalue_class({'a': -1, 'b': -2, 'x': {'c': -3, 'd': -4}}) def test_numeric_invert(self): - t1 = tree_value_clazz({'a': 1, 'b': 2, 'x': {'c': 3, 'd': 4}}) - assert ~t1 == tree_value_clazz({'a': -2, 'b': -3, 'x': {'c': -4, 'd': -5}}) + t1 = treevalue_class({'a': 1, 'b': 2, 'x': {'c': 3, 'd': 4}}) + assert ~t1 == treevalue_class({'a': -2, 'b': -3, 'x': {'c': -4, 'd': -5}}) def test_getitem(self): - t1 = tree_value_clazz({'a': 1, 'b': 2, 'x': {'c': 3, 'd': 4}}) - t2 = tree_value_clazz({'a': [2, 3, 5, 7], 'b': [11, 13, 17, 19], - 'x': {'c': [23, 29, 31, 37], 'd': [41, 43, 47, 53]}}) + t1 = treevalue_class({'a': 1, 'b': 2, 'x': {'c': 3, 'd': 4}}) + t2 = treevalue_class({'a': [2, 3, 5, 7], 'b': [11, 13, 17, 19], + 'x': {'c': [23, 29, 31, 37], 'd': [41, 43, 47, 53]}}) - assert t2[t1 - 1] == tree_value_clazz({'a': 2, 'b': 13, 'x': {'c': 31, 'd': 53}}) + assert t2[t1 - 1] == treevalue_class({'a': 2, 'b': 13, 'x': {'c': 31, 'd': 53}}) assert t2['a'] == [2, 3, 5, 7] - assert t2['x'] == tree_value_clazz({'c': [23, 29, 31, 37], 'd': [41, 43, 47, 53]}) + assert t2['x'] == treevalue_class({'c': [23, 29, 31, 37], 'd': [41, 43, 47, 53]}) assert t2['x']['c'] == [23, 29, 31, 37] m1 = np.random.random((3, 4)) m2 = np.random.random((3, 5)) - a = tree_value_clazz({'a': m1, 'b': m2}) + a = treevalue_class({'a': m1, 'b': m2}) assert np.allclose(a['a'], m1) assert np.allclose(a['b'], m2) @@ -340,68 +341,68 @@ def test_getitem(self): assert np.allclose(a_35['a'], m1[:, 3:5]) assert np.allclose(a_35['b'], m2[:, 3:5]) - b = tree_value_clazz({'': m1, '1': m2}) + b = treevalue_class({'': m1, '1': m2}) assert np.allclose(b[''], m1) assert np.allclose(b['1'], m2) - t3 = tree_value_clazz({ + t3 = treevalue_class({ 'a': raw({'a': 1, 'y': 2}), 'c': {'x': raw({'a': 3, 'y': 4})}, }) assert t3['a'] == {'a': 1, 'y': 2} - assert t3['c'] == tree_value_clazz({'x': raw({'a': 3, 'y': 4})}) + assert t3['c'] == treevalue_class({'x': raw({'a': 3, 'y': 4})}) assert t3['c']['x'] == {'a': 3, 'y': 4} with pytest.raises(KeyError): _ = t3['y'] - assert t3[['a']] == tree_value_clazz({'a': 1, 'c': {'x': 3}}) - assert t3[['y']] == tree_value_clazz({'a': 2, 'c': {'x': 4}}) + assert t3[['a']] == treevalue_class({'a': 1, 'c': {'x': 3}}) + assert t3[['y']] == treevalue_class({'a': 2, 'c': {'x': 4}}) def test_setitem(self): - t1 = tree_value_clazz({'a': 1, 'b': 2, 'x': {'c': 3, 'd': 4}}) - t2 = tree_value_clazz({'a': [2, 3, 5, 7], 'b': [11, 13, 17, 19], - 'x': {'c': [23, 29, 31, 37], 'd': [41, 43, 47, 53]}}) + t1 = treevalue_class({'a': 1, 'b': 2, 'x': {'c': 3, 'd': 4}}) + t2 = treevalue_class({'a': [2, 3, 5, 7], 'b': [11, 13, 17, 19], + 'x': {'c': [23, 29, 31, 37], 'd': [41, 43, 47, 53]}}) t2[t1 - 1] = t1 - assert t2 == tree_value_clazz({'a': [1, 3, 5, 7], 'b': [11, 2, 17, 19], - 'x': {'c': [23, 29, 3, 37], 'd': [41, 43, 47, 4]}}) + assert t2 == treevalue_class({'a': [1, 3, 5, 7], 'b': [11, 2, 17, 19], + 'x': {'c': [23, 29, 3, 37], 'd': [41, 43, 47, 4]}}) - t3 = tree_value_clazz({ + t3 = treevalue_class({ 'a': raw({'a': 1, 'y': 2}), 'c': {'x': raw({'a': 3, 'y': 4})}, }) t3['a'] = {'a': 11, 'y': 22} - assert t3 == tree_value_clazz({ + assert t3 == treevalue_class({ 'a': raw({'a': 11, 'y': 22}), 'c': {'x': raw({'a': 3, 'y': 4})}, }) t3[['a']] = 33 - assert t3 == tree_value_clazz({ + assert t3 == treevalue_class({ 'a': raw({'a': 33, 'y': 22}), 'c': {'x': raw({'a': 33, 'y': 4})}, }) t3[['y']] = 55 - assert t3 == tree_value_clazz({ + assert t3 == treevalue_class({ 'a': raw({'a': 33, 'y': 55}), 'c': {'x': raw({'a': 33, 'y': 55})}, }) def test_delitem(self): - t1 = tree_value_clazz({'a': 1, 'b': 2, 'x': {'c': 3, 'd': 4}}) - t2 = tree_value_clazz({'a': [2, 3, 5, 7], 'b': [11, 13, 17, 19], - 'x': {'c': [23, 29, 31, 37], 'd': [41, 43, 47, 53]}}) + t1 = treevalue_class({'a': 1, 'b': 2, 'x': {'c': 3, 'd': 4}}) + t2 = treevalue_class({'a': [2, 3, 5, 7], 'b': [11, 13, 17, 19], + 'x': {'c': [23, 29, 31, 37], 'd': [41, 43, 47, 53]}}) del t2[t1 - 1] - assert t2 == tree_value_clazz({'a': [3, 5, 7], 'b': [11, 17, 19], - 'x': {'c': [23, 29, 37], 'd': [41, 43, 47]}}) + assert t2 == treevalue_class({'a': [3, 5, 7], 'b': [11, 17, 19], + 'x': {'c': [23, 29, 37], 'd': [41, 43, 47]}}) - t3 = tree_value_clazz({ + t3 = treevalue_class({ 'a': raw({'a': 1, 'y': 2}), 'c': {'x': raw({'a': 3, 'y': 4})}, 'g': 2, }) del t3['g'] - assert t3 == tree_value_clazz({ + assert t3 == treevalue_class({ 'a': raw({'a': 1, 'y': 2}), 'c': {'x': raw({'a': 3, 'y': 4})}, }) @@ -410,41 +411,41 @@ def test_delitem(self): del t3[['g']] del t3[['a']] - assert t3 == tree_value_clazz({ + assert t3 == treevalue_class({ 'a': raw({'y': 2}), 'c': {'x': raw({'y': 4})}, }) del t3['a'] - assert t3 == tree_value_clazz({ + assert t3 == treevalue_class({ 'c': {'x': raw({'y': 4})}, }) def test_attr(self): - t1 = tree_value_clazz({'a': 1, 'b': 2, 'x': {'c': 3, 'd': 4}}) - t2 = func_treelize(return_type=tree_value_clazz)(Container)(t1) - assert t2 == tree_value_clazz( + t1 = treevalue_class({'a': 1, 'b': 2, 'x': {'c': 3, 'd': 4}}) + t2 = func_treelize(return_type=treevalue_class)(Container)(t1) + assert t2 == treevalue_class( {'a': Container(1), 'b': Container(2), 'x': {'c': Container(3), 'd': Container(4)}}) assert t2.value == t1 assert t1.a == 1 - assert t1.x == tree_value_clazz({'c': 3, 'd': 4}) + assert t1.x == treevalue_class({'c': 3, 'd': 4}) m1 = np.random.random((3, 4)) m2 = np.random.random((3, 5)) - a = tree_value_clazz({'a': m1, 'b': m2}) + a = treevalue_class({'a': m1, 'b': m2}) assert np.allclose(a.a, m1) assert np.allclose(a.b, m2) - assert a.shape == tree_value_clazz({ + assert a.shape == treevalue_class({ 'a': (3, 4), 'b': (3, 5), }) def test_call(self): - t1 = tree_value_clazz({'a': 1, 'b': 2, 'x': {'c': 3, 'd': 4}}) - t2 = func_treelize(return_type=tree_value_clazz)(Container)(t1) - assert t2.add(10) == tree_value_clazz({'a': 11, 'b': 12, 'x': {'c': 13, 'd': 14}}) - assert t2.add(x=10) == tree_value_clazz({'a': 11, 'b': 12, 'x': {'c': 13, 'd': 14}}) - assert t2.add(t1) == tree_value_clazz({'a': 2, 'b': 4, 'x': {'c': 6, 'd': 8}}) + t1 = treevalue_class({'a': 1, 'b': 2, 'x': {'c': 3, 'd': 4}}) + t2 = func_treelize(return_type=treevalue_class)(Container)(t1) + assert t2.add(10) == treevalue_class({'a': 11, 'b': 12, 'x': {'c': 13, 'd': 14}}) + assert t2.add(x=10) == treevalue_class({'a': 11, 'b': 12, 'x': {'c': 13, 'd': 14}}) + assert t2.add(t1) == treevalue_class({'a': 2, 'b': 4, 'x': {'c': 6, 'd': 8}}) def test_map(self): cnt = 0 @@ -454,14 +455,14 @@ def f(x): cnt += 1 return x + 2 - t1 = tree_value_clazz({'a': 1, 'b': 2, 'x': {'c': 3, 'd': 4}}) + t1 = treevalue_class({'a': 1, 'b': 2, 'x': {'c': 3, 'd': 4}}) assert cnt == 0 t2 = t1.map(f) assert cnt == 4 - assert t2 == tree_value_clazz({'a': 3, 'b': 4, 'x': {'c': 5, 'd': 6}}) + assert t2 == treevalue_class({'a': 3, 'b': 4, 'x': {'c': 5, 'd': 6}}) cnt = 0 - t3 = tree_value_clazz({ + t3 = treevalue_class({ 'a': delayed(lambda: t1.a), 'b': delayed(lambda: t1.b), 'x': delayed(lambda: t1.x), @@ -474,48 +475,48 @@ def f(x): assert t4.a == 3 assert cnt == 1 - assert t4 == tree_value_clazz({'a': 3, 'b': 4, 'x': {'c': 5, 'd': 6}}) + assert t4 == treevalue_class({'a': 3, 'b': 4, 'x': {'c': 5, 'd': 6}}) assert cnt == 4 assert t4.a == 3 assert cnt == 4 def test_type(self): - t1 = tree_value_clazz({'a': 1, 'b': 2, 'x': {'c': 3, 'd': 4}}) + t1 = treevalue_class({'a': 1, 'b': 2, 'x': {'c': 3, 'd': 4}}) assert t1.type(TreeValue) == TreeValue({'a': 1, 'b': 2, 'x': {'c': 3, 'd': 4}}) - assert t1.type(TreeValue) != tree_value_clazz({'a': 1, 'b': 2, 'x': {'c': 3, 'd': 4}}) + assert t1.type(TreeValue) != treevalue_class({'a': 1, 'b': 2, 'x': {'c': 3, 'd': 4}}) def test_filter(self): - t1 = tree_value_clazz({'a': 1, 'b': 2, 'x': {'c': 3, 'd': 4}}) - assert t1.filter(lambda x: x % 2 == 1) == tree_value_clazz({'a': 1, 'x': {'c': 3}}) - assert t1.filter(lambda x: x < 3) == tree_value_clazz({'a': 1, 'b': 2, }) - assert t1.filter(lambda x: x < 3, False) == tree_value_clazz({'a': 1, 'b': 2, 'x': {}}) + t1 = treevalue_class({'a': 1, 'b': 2, 'x': {'c': 3, 'd': 4}}) + assert t1.filter(lambda x: x % 2 == 1) == treevalue_class({'a': 1, 'x': {'c': 3}}) + assert t1.filter(lambda x: x < 3) == treevalue_class({'a': 1, 'b': 2, }) + assert t1.filter(lambda x: x < 3, False) == treevalue_class({'a': 1, 'b': 2, 'x': {}}) def test_mask(self): - t1 = tree_value_clazz({'a': 13, 'b': 27, 'x': {'c': 39, 'd': 45}}) - t2 = tree_value_clazz({'a': 1, 'b': 2, 'x': {'c': 3, 'd': 4}}) - t3 = tree_value_clazz({'a': 1, 'b': 2, 'x': {'c': 7, 'd': 4}}) + t1 = treevalue_class({'a': 13, 'b': 27, 'x': {'c': 39, 'd': 45}}) + t2 = treevalue_class({'a': 1, 'b': 2, 'x': {'c': 3, 'd': 4}}) + t3 = treevalue_class({'a': 1, 'b': 2, 'x': {'c': 7, 'd': 4}}) mask1 = t2.map(lambda x: (lambda v: v % x == 0))(t1) - assert t1.mask(mask1) == tree_value_clazz({'a': 13, 'x': {'c': 39}}) + assert t1.mask(mask1) == treevalue_class({'a': 13, 'x': {'c': 39}}) mask2 = t3.map(lambda x: (lambda v: v % x == 0))(t1) - assert t1.mask(mask2) == tree_value_clazz({'a': 13}) - assert t1.mask(mask2, False) == tree_value_clazz({'a': 13, 'x': {}}) + assert t1.mask(mask2) == treevalue_class({'a': 13}) + assert t1.mask(mask2, False) == treevalue_class({'a': 13, 'x': {}}) def test_reduce(self): - t1 = tree_value_clazz({'a': 13, 'b': 27, 'x': {'c': 39, 'd': 45}}) - t2 = tree_value_clazz({'a': 1, 'b': 2, 'x': {'c': 3, 'd': 4}}) + t1 = treevalue_class({'a': 13, 'b': 27, 'x': {'c': 39, 'd': 45}}) + t2 = treevalue_class({'a': 1, 'b': 2, 'x': {'c': 3, 'd': 4}}) assert t1.reduce(lambda **kwargs: sum(kwargs.values())) == 124 assert t2.reduce(lambda **kwargs: reduce(__mul__, kwargs.values())) == 24 def test_union(self): - t1 = tree_value_clazz({'a': 13, 'b': 27, 'x': {'c': 39, 'd': 45}}) - t2 = tree_value_clazz({'a': 1, 'b': 2, 'x': {'c': 3, 'd': 4}}) - t3 = tree_value_clazz({'a': 1, 'b': 2, 'x': {'c': 7, 'd': 4}}) + t1 = treevalue_class({'a': 13, 'b': 27, 'x': {'c': 39, 'd': 45}}) + t2 = treevalue_class({'a': 1, 'b': 2, 'x': {'c': 3, 'd': 4}}) + t3 = treevalue_class({'a': 1, 'b': 2, 'x': {'c': 7, 'd': 4}}) - assert tree_value_clazz.union(t1, t2, t3) == tree_value_clazz({ + assert treevalue_class.union(t1, t2, t3) == treevalue_class({ 'a': (13, 1, 1), 'b': (27, 2, 2), 'x': { @@ -524,7 +525,7 @@ def test_union(self): } }) - assert tree_value_clazz.union(t1, t2, t3, return_type=TreeValue) == TreeValue({ + assert treevalue_class.union(t1, t2, t3, return_type=TreeValue) == TreeValue({ 'a': (13, 1, 1), 'b': (27, 2, 2), 'x': { @@ -546,11 +547,11 @@ def test_subside(self): 'k': '233' } - assert tree_value_clazz.subside(data) == tree_value_clazz({ + assert treevalue_class.subside(data) == treevalue_class({ 'a': raw({'a': 1, 'k': '233', 'x': {'c': 3, 'd': [5, 7]}}), 'b': raw({'a': 2, 'k': '233', 'x': {'c': 4, 'd': [6, 8]}}), }) - assert tree_value_clazz.subside(data, return_type=TreeValue) == TreeValue({ + assert treevalue_class.subside(data, return_type=TreeValue) == TreeValue({ 'a': raw({'a': 1, 'k': '233', 'x': {'c': 3, 'd': [5, 7]}}), 'b': raw({'a': 2, 'k': '233', 'x': {'c': 4, 'd': [6, 8]}}), }) @@ -568,21 +569,21 @@ def test_rise(self): 'k': '233' } - t1 = tree_value_clazz.subside(data) + t1 = treevalue_class.subside(data) assert t1.rise() == { - 'a': tree_value_clazz({'a': 1, 'b': 2}), + 'a': treevalue_class({'a': 1, 'b': 2}), 'x': { - 'c': tree_value_clazz({'a': 3, 'b': 4}), + 'c': treevalue_class({'a': 3, 'b': 4}), 'd': [ - tree_value_clazz({'a': 5, 'b': 6}), - tree_value_clazz({'a': 7, 'b': 8}), + treevalue_class({'a': 5, 'b': 6}), + treevalue_class({'a': 7, 'b': 8}), ] }, - 'k': tree_value_clazz({'a': '233', 'b': '233'}), + 'k': treevalue_class({'a': '233', 'b': '233'}), } def test_deep_clone(self): - t = tree_value_clazz({ + t = treevalue_class({ 'a': raw({'a': 1, 'b': 2}), 'b': raw({'a': 3, 'b': 4}), 'x': { @@ -606,7 +607,7 @@ def test_deep_clone(self): assert t2.x.d is not t.x.d def test_graph(self): - t = tree_value_clazz({ + t = treevalue_class({ 'a': [4, 3, 2, 1], 'b': np.array([[5, 6], [7, 8]]), 'x': { @@ -619,7 +620,7 @@ def test_graph(self): assert len(graph.source) <= 2290 def test_graphics(self): - t = tree_value_clazz({ + t = treevalue_class({ 'a': [4, 3, 2, 1], 'b': np.array([[5, 6], [7, 8]]), 'x': { @@ -628,7 +629,7 @@ def test_graphics(self): 'e': np.array([[1, 2], [3, 4]]) }, }) - t1 = tree_value_clazz({ + t1 = treevalue_class({ 'aa': t.a, 'bb': np.array([[5, 6], [7, 8]]), 'xx': { @@ -638,45 +639,45 @@ def test_graphics(self): }, }) - graph_1 = tree_value_clazz.graphics( + graph_1 = treevalue_class.graphics( (t, 't'), (t1, 't1'), - (tree_value_clazz({'a': t, 'b': t1, 'c': [1, 2], 'd': t1.xx}), 't2'), + (treevalue_class({'a': t, 'b': t1, 'c': [1, 2], 'd': t1.xx}), 't2'), dup_value=(np.ndarray, list), title="This is a demo of 2 trees with dup value.", cfg={'bgcolor': '#ffffffff'}, ) assert len(graph_1.source) <= 4960 - graph_2 = tree_value_clazz.graphics( + graph_2 = treevalue_class.graphics( (t, 't'), (t1, 't1'), - (tree_value_clazz({'a': t, 'b': t1, 'c': [1, 2], 'd': t1.xx}), 't2'), + (treevalue_class({'a': t, 'b': t1, 'c': [1, 2], 'd': t1.xx}), 't2'), dup_value=False, title="This is a demo of 2 trees with dup value.", cfg={'bgcolor': '#ffffffff'}, ) assert len(graph_2.source) <= 5480 - graph_3 = tree_value_clazz.graphics( + graph_3 = treevalue_class.graphics( (t, 't'), (t1, 't1'), - (tree_value_clazz({'a': t, 'b': t1, 'c': [1, 2], 'd': t1.xx}), 't2'), + (treevalue_class({'a': t, 'b': t1, 'c': [1, 2], 'd': t1.xx}), 't2'), dup_value=lambda x: id(x), title="This is a demo of 2 trees with dup value.", cfg={'bgcolor': '#ffffffff'}, ) assert len(graph_3.source) <= 4760 - graph_4 = tree_value_clazz.graphics( + graph_4 = treevalue_class.graphics( (t, 't'), (t1, 't1'), - (tree_value_clazz({'a': t, 'b': t1, 'c': [1, 2], 'd': t1.xx}), 't2'), + (treevalue_class({'a': t, 'b': t1, 'c': [1, 2], 'd': t1.xx}), 't2'), dup_value=lambda x: type(x).__name__, title="This is a demo of 2 trees with dup value.", cfg={'bgcolor': '#ffffffff'}, ) assert len(graph_4.source) <= 3780 - graph_6 = tree_value_clazz.graphics( + graph_6 = treevalue_class.graphics( (t, 't'), (t1, 't1'), - (tree_value_clazz({'a': t, 'b': t1, 'c': [1, 2], 'd': t1.xx}), 't2'), + (treevalue_class({'a': t, 'b': t1, 'c': [1, 2], 'd': t1.xx}), 't2'), dup_value=True, title="This is a demo of 2 trees with dup value.", cfg={'bgcolor': '#ffffffff'}, @@ -684,18 +685,18 @@ def test_graphics(self): assert len(graph_6.source) <= 4760 def test_func(self): - t1 = tree_value_clazz({'a': 1, 'b': 2, 'x': {'c': 3, 'd': 4}}) - t2 = tree_value_clazz({'a': 11, 'b': 20, 'x': {'c': 33, 'd': 48}}) + t1 = treevalue_class({'a': 1, 'b': 2, 'x': {'c': 3, 'd': 4}}) + t2 = treevalue_class({'a': 11, 'b': 20, 'x': {'c': 33, 'd': 48}}) - @tree_value_clazz.func() + @treevalue_class.func() def ssum(x, y): return x + y - assert ssum(t1, t2) == tree_value_clazz({'a': 12, 'b': 22, 'x': {'c': 36, 'd': 52}}) + assert ssum(t1, t2) == treevalue_class({'a': 12, 'b': 22, 'x': {'c': 36, 'd': 52}}) cnt_1 = 0 - @tree_value_clazz.func(delayed=True) + @treevalue_class.func(delayed=True) def ssumx(x, y): nonlocal cnt_1 cnt_1 += 1 @@ -707,20 +708,83 @@ def ssumx(x, y): assert t3.a == 12 assert cnt_1 == 1 - assert t3.x == tree_value_clazz({'c': 36, 'd': 52}) + assert t3.x == treevalue_class({'c': 36, 'd': 52}) assert cnt_1 == 3 - assert t3 == tree_value_clazz({'a': 12, 'b': 22, 'x': {'c': 36, 'd': 52}}) + assert t3 == treevalue_class({'a': 12, 'b': 22, 'x': {'c': 36, 'd': 52}}) assert cnt_1 == 4 def test_walk(self): - tv1 = tree_value_clazz({'a': 1, 'b': 'dks', 'c': {'x': 2, 'y': 3}}) + tv1 = treevalue_class({'a': 1, 'b': 'dks', 'c': {'x': 2, 'y': 3}}) assert dict(tv1.walk()) == { - (): tree_value_clazz({'a': 1, 'b': 'dks', 'c': {'x': 2, 'y': 3}}), + (): treevalue_class({'a': 1, 'b': 'dks', 'c': {'x': 2, 'y': 3}}), ('a',): 1, ('b',): 'dks', - ('c',): tree_value_clazz({'x': 2, 'y': 3}), + ('c',): treevalue_class({'x': 2, 'y': 3}), ('c', 'x'): 2, ('c', 'y'): 3, } + def test_tree_value_operate_with_item(self): + tv1 = treevalue_class({'a': 1, 'b': 2, 'c': {'x': 2, 'y': 3}}) + tv2 = treevalue_class(tv1) + tv3 = treevalue_class({'a': tv1, 'b': tv2, 'c': tv1}) + tv4 = treevalue_class({'a': raw({'a': 1, 'y': 2}), 'c': {'x': raw({'a': 3, 'y': 4}), }}) + + tv1['a'] = 3 + assert tv1.a == 3 + assert tv2.a == 3 + assert tv3.a.a == 3 + assert tv3.b.a == 3 + assert tv3.c.a == 3 + + assert tv4['a'] == {'a': 1, 'y': 2} + assert tv4['c'] == treevalue_class({'x': raw({'a': 3, 'y': 4})}) + with pytest.raises(KeyError): + _ = tv4['y'] + with pytest.raises(KeyError): + _ = tv4[['c']] + + tv1['f'] = 333 + assert tv1.f == 333 + assert tv1['f'] == 333 + assert 'f' in tv1 + + with pytest.raises(TypeError): + tv1[0] = 3 + with pytest.raises(TypeError): + tv1[['c']] = 3 + + del tv1['b'] + assert 'b' not in tv1 + assert 'b' not in tv2 + assert 'b' not in tv3.a + assert 'b' not in tv3.b + assert 'b' not in tv3.c + + with pytest.raises(KeyError): + del tv1['g'] + with pytest.raises(TypeError): + del tv1[['c']] + with pytest.raises(TypeError): + del tv1[0] + + def test_tree_value_init_with_item(self): + tv1 = treevalue_class({'a': 1, 'b': 2, 'c': {'x': 2, 'y': 3}}) + assert tv1['a'] == 1 + assert tv1['b'] == 2 + + tv2 = treevalue_class(tv1) + assert tv2['a'] == 1 + assert tv2['b'] == 2 + + tv3 = treevalue_class({'a': tv1, 'b': tv2, 'c': tv1}) + assert tv3['a']['a'] == 1 + assert tv3['b']['a'] == 1 + assert tv3['c']['a'] == 1 + + with pytest.raises(KeyError): + _ = tv3['g'] + with pytest.raises(TypeError): + _ = tv3[0] + return _TestClass diff --git a/test/tree/general/test_fast.py b/test/tree/general/test_fast.py index 9b87a61cb2..8e1eb18122 100644 --- a/test/tree/general/test_fast.py +++ b/test/tree/general/test_fast.py @@ -1,7 +1,7 @@ import pytest from treevalue.tree import FastTreeValue, method_treelize -from .base import get_tree_test +from .base import get_fasttreevalue_test class MyFastTreeValue(FastTreeValue): @@ -15,7 +15,7 @@ def __radd(self, other): @pytest.mark.unittest -class TestTreeGeneralFast(get_tree_test(FastTreeValue)): +class TestTreeGeneralFast(get_fasttreevalue_test(FastTreeValue)): def test_my_fast_tree_value(self): t1 = MyFastTreeValue({'a': 1, 'b': 2, 'x': {'c': 3, 'd': 4, 'e': 7}}) t2 = MyFastTreeValue({'a': 11, 'b': 22, 'c': 4, 'x': {'c': 33, 'd': 5}}) diff --git a/test/tree/general/test_general.py b/test/tree/general/test_general.py index 1bf2954fc4..ca147872d3 100644 --- a/test/tree/general/test_general.py +++ b/test/tree/general/test_general.py @@ -1,7 +1,7 @@ import pytest from treevalue.tree import general_tree_value, method_treelize -from .base import get_tree_test +from .base import get_fasttreevalue_test class TreeNumber(general_tree_value()): @@ -34,7 +34,7 @@ class BanAndOverrideTreeNumber(general_tree_value(methods=dict( @pytest.mark.unittest -class TestTreeGeneralGeneral(get_tree_test(TreeNumber)): +class TestTreeGeneralGeneral(get_fasttreevalue_test(TreeNumber)): def test_numeric_append(self): t1 = TreeNumber({'a': 1, 'b': 2, 'x': {'c': 3, 'd': 4}}) t2 = TreeNumber({'a': 11, 'b': 22, 'x': {'c': 33, 'd': 5}}) diff --git a/test/tree/general/test_meta.py b/test/tree/general/test_meta.py new file mode 100644 index 0000000000..2e2bb94cce --- /dev/null +++ b/test/tree/general/test_meta.py @@ -0,0 +1,17 @@ +import pytest +from .base import get_fasttreevalue_test +from treevalue.tree import FastTreeValue + + + +class _MyMetaClass(type): + pass + + +class MyMetaTreeValue(FastTreeValue, metaclass=_MyMetaClass): + pass + + +@pytest.mark.unittest +class TestTreeGeneralMeta(get_fasttreevalue_test(MyMetaTreeValue)): + pass diff --git a/test/tree/tree/base.py b/test/tree/tree/base.py new file mode 100644 index 0000000000..c622a19f52 --- /dev/null +++ b/test/tree/tree/base.py @@ -0,0 +1,524 @@ +import pickle +import re +from typing import Type + +import pytest + +from treevalue import raw, TreeValue, delayed +from treevalue.tree.common import create_storage + +try: + _ = reversed({}.keys()) +except TypeError: + _reversible = False +else: + _reversible = True + + +class _Container: + def __init__(self, value): + self.__value = value + + @property + def value(self): + return self.__value + + def __repr__(self): + return '<{cls} {id} value: {value}>'.format( + cls=self.__class__.__name__, id=hex(id(self)), value=repr(self.__value)) + + def __eq__(self, other): + if other is self: + return True + elif type(other) == _Container: + return other.__value == self.value + else: + return False + + def __hash__(self): + return hash((self.__value,)) + + +def get_treevalue_test(treevalue_class: Type[TreeValue]): + # noinspection DuplicatedCode,PyMethodMayBeStatic + @pytest.mark.unittest + class _TestClass: + def test_tree_value_init(self): + tv1 = treevalue_class({'a': 1, 'b': 2, 'c': {'x': 2, 'y': 3}}) + assert tv1.a == 1 + assert tv1.b == 2 + assert tv1.c == treevalue_class({'x': 2, 'y': 3}) + + tv2 = treevalue_class(tv1) + assert tv2.a == 1 + assert tv2.b == 2 + + tv3 = treevalue_class({'a': tv1, 'b': tv2, 'c': tv1}) + assert tv3.a.a == 1 + assert tv3.b.a == 1 + assert tv3.c.a == 1 + + # with usage of raw function + tv4 = treevalue_class({'a': 1, 'b': 2, 'c': {'x': 2, 'y': 3}, 'd': raw({'x': 2, 'y': 3})}) + assert tv4.a == 1 + assert tv4.b == 2 + assert tv4.c == treevalue_class({'x': 2, 'y': 3}) + assert tv4.c.x == 2 + assert tv4.c.y == 3 + assert tv4.d == {'x': 2, 'y': 3} + with pytest.raises(AttributeError): # error, tv4.d is a dict + _ = tv4.d.x + with pytest.raises(AttributeError): # error, tv4.d is a dict + _ = tv4.d.y + + with pytest.raises(TypeError): + treevalue_class(1) + + class MyTreeValue(treevalue_class): + pass + + tv4 = MyTreeValue({'a': tv1.c, 'x': {'b': tv1, 'c': tv2.c}}) + assert isinstance(tv4.a, MyTreeValue) + assert isinstance(tv4.x, MyTreeValue) + assert isinstance(tv4.x.b, MyTreeValue) + assert isinstance(tv4.x.c, MyTreeValue) + + tv5 = MyTreeValue({'a': tv1.c, 'x': {'b': tv1._detach(), 'c': tv2.c}}) + assert isinstance(tv5.a, MyTreeValue) + assert isinstance(tv5.x, MyTreeValue) + assert isinstance(tv5.x.b, MyTreeValue) + assert isinstance(tv5.x.c, MyTreeValue) + + def test_tree_value_init_with_item(self): + tv1 = treevalue_class({'a': 1, 'b': 2, 'c': {'x': 2, 'y': 3}}) + assert tv1['a'] == 1 + assert tv1['b'] == 2 + + tv2 = treevalue_class(tv1) + assert tv2['a'] == 1 + assert tv2['b'] == 2 + + tv3 = treevalue_class({'a': tv1, 'b': tv2, 'c': tv1}) + assert tv3['a']['a'] == 1 + assert tv3['b']['a'] == 1 + assert tv3['c']['a'] == 1 + + with pytest.raises(KeyError): + _ = tv3['g'] + with pytest.raises(KeyError): + _ = tv3[0] + + def test_tree_value_operate(self): + tv1 = treevalue_class({'a': 1, 'b': 2, 'c': {'x': 2, 'y': 3}}) + tv2 = treevalue_class(tv1) + tv3 = treevalue_class({'a': tv1, 'b': tv2, 'c': tv1}) + + tv1.a = 3 + assert tv1.a == 3 + assert tv2.a == 3 + assert tv3.a.a == 3 + assert tv3.b.a == 3 + assert tv3.c.a == 3 + + del tv1.b + assert 'b' not in tv1 + assert 'b' not in tv2 + assert 'b' not in tv3.a + assert 'b' not in tv3.b + assert 'b' not in tv3.c + + with pytest.raises(AttributeError): + _ = tv1.dd + + tv1.a = treevalue_class({'a1': 1, 'a2': 2}) + assert tv1.a.a1 == 1 + assert tv2.a.a1 == 1 + assert tv3.a.a.a1 == 1 + + tv1.a = treevalue_class({'a1': 2, 'a2': 1}) + assert tv1.a.a1 == 2 + assert tv2.a.a1 == 2 + assert tv3.a.a.a1 == 2 + + with pytest.raises(AttributeError): + del tv1._property__data + + tv1.ff = raw(1) + assert tv1.ff == 1 + tv1.fff = raw({'x': 1, 'y': 2}) + assert isinstance(tv1.fff, dict) + assert tv1.fff == {'x': 1, 'y': 2} + + # noinspection PyTypeChecker + def test_setdefault(self): + t = treevalue_class({}) + assert t.setdefault('a', 1) == 1 + assert t == treevalue_class({'a': 1}) + assert t.setdefault('a', 100) == 1 + assert t == treevalue_class({'a': 1}) + + assert t.setdefault('f', {'a': 1, 'b': 2}) == {'a': 1, 'b': 2} + assert t == treevalue_class({'a': 1, 'f': raw({'a': 1, 'b': 2})}) + assert t.setdefault('f', {'y': 1, 'z': 2}) == {'a': 1, 'b': 2} + assert t == treevalue_class({'a': 1, 'f': raw({'a': 1, 'b': 2})}) + + assert t.setdefault('c', treevalue_class({'a': 1, 'b': 2})) == treevalue_class({'a': 1, 'b': 2}) + assert t == treevalue_class({'a': 1, 'f': raw({'a': 1, 'b': 2}), 'c': {'a': 1, 'b': 2}}) + assert t.setdefault('c', treevalue_class({'aa': 1, 'bb': 2})) == treevalue_class({'a': 1, 'b': 2}) + assert t == treevalue_class({'a': 1, 'f': raw({'a': 1, 'b': 2}), 'c': {'a': 1, 'b': 2}}) + + d = delayed(lambda: 1) + assert t.setdefault('g', delayed(lambda x: x + 1, d)) == 2 + assert t == treevalue_class({'a': 1, 'f': raw({'a': 1, 'b': 2}), 'c': {'a': 1, 'b': 2}, 'g': 2}) + assert t.setdefault('g', delayed(lambda x: x + 100, d)) == 2 + assert t == treevalue_class({'a': 1, 'f': raw({'a': 1, 'b': 2}), 'c': {'a': 1, 'b': 2}, 'g': 2}) + + def test_tree_value_operate_with_item(self): + tv1 = treevalue_class({'a': 1, 'b': 2, 'c': {'x': 2, 'y': 3}}) + tv2 = treevalue_class(tv1) + tv3 = treevalue_class({'a': tv1, 'b': tv2, 'c': tv1}) + tv4 = treevalue_class({'a': raw({'a': 1, 'y': 2}), 'c': {'x': raw({'a': 3, 'y': 4}), }}) + + tv1['a'] = 3 + assert tv1.a == 3 + assert tv2.a == 3 + assert tv3.a.a == 3 + assert tv3.b.a == 3 + assert tv3.c.a == 3 + + assert tv4['a'] == {'a': 1, 'y': 2} + assert tv4['c'] == treevalue_class({'x': raw({'a': 3, 'y': 4})}) + with pytest.raises(KeyError): + _ = tv4['y'] + with pytest.raises(KeyError): + _ = tv4[['c']] + + tv1['f'] = 333 + assert tv1.f == 333 + assert tv1['f'] == 333 + assert 'f' in tv1 + + with pytest.raises(NotImplementedError): + tv1[0] = 3 + with pytest.raises(NotImplementedError): + tv1[['c']] = 3 + + del tv1['b'] + assert 'b' not in tv1 + assert 'b' not in tv2 + assert 'b' not in tv3.a + assert 'b' not in tv3.b + assert 'b' not in tv3.c + + with pytest.raises(KeyError): + del tv1['g'] + with pytest.raises(KeyError): + del tv1[['c']] + with pytest.raises(KeyError): + del tv1[0] + + def test_tree_value_repr(self): + tv1 = treevalue_class({'a': 1, 'b': 2, 'c': {'x': 2, 'y': 3}}) + + assert re.match(rf"<{treevalue_class.__name__} 0x[0-9a-f]+>", repr(tv1)) + assert re.match(rf"<{treevalue_class.__name__} 0x[0-9a-f]+>", repr(tv1.c)) + assert f"'a' --> 1" in str(tv1) + assert f"'b' --> 2" in str(tv1) + assert f"'x' --> 2" in str(tv1) + assert f"'y' --> 3" in str(tv1) + assert f"'c' --> <{treevalue_class.__name__}" in str(tv1) + + tv2 = treevalue_class({'a': 1, 'b': 2, 'c': {'x': 2, 'y': 3}}) + tv2.c.z = tv2 + assert re.match(rf"<{treevalue_class.__name__} 0x[0-9a-f]+>", repr(tv2)) + assert re.match(rf"<{treevalue_class.__name__} 0x[0-9a-f]+>", repr(tv2.c)) + assert f"'a' --> 1" in repr(tv2) + assert f"'b' --> 2" in repr(tv2) + assert f"'x' --> 2" in repr(tv2) + assert f"'y' --> 3" in repr(tv2) + assert f"'c' --> <{treevalue_class.__name__}" in repr(tv2) + assert "(The same address as )" in repr(tv2) + + tv3 = treevalue_class({ + 'a': delayed(lambda: tv1.a), + 'b': delayed(lambda: tv1.b), + 'c': delayed(lambda: tv1.c), + }) + + assert re.match(rf"<{treevalue_class.__name__} 0x[0-9a-f]+>", repr(tv3)) + assert re.match(rf"<{treevalue_class.__name__} 0x[0-9a-f]+>", repr(tv3.c)) + assert f"'a' --> 1" in str(tv3) + assert f"'b' --> 2" in str(tv3) + assert f"'x' --> 2" in str(tv3) + assert f"'y' --> 3" in str(tv3) + assert f"'c' --> <{treevalue_class.__name__}" in str(tv3) + + def test_tree_value_iter(self): + # Attention: dict(tv1) is not supported in python 3.7+ + tv1 = treevalue_class({'a': 1, 'b': 2, 'c': {'x': 2, 'y': 3}}) + assert sorted(list(tv1)) == ['a', 'b', 'c'] + assert sorted(list(tv1.c)) == ['x', 'y'] + + def test_tree_value_reversed(self): + tv1 = treevalue_class({'a': 1, 'b': 2, 'c': {'x': 2, 'y': 3}}) + if _reversible: + assert list(reversed(tv1)) == list(iter(tv1))[::-1] + assert list(reversed(tv1.c)) == list(iter(tv1.c))[::-1] + else: + with pytest.raises(TypeError): + reversed(tv1) + with pytest.raises(TypeError): + reversed(tv1.c) + + def test_tree_value_len(self): + tv1 = treevalue_class({'a': 1, 'b': 2, 'c': {'x': 2, 'y': 3}}) + tv2 = treevalue_class({'a': 1, 'b': 2, 'c': {}, 'd': 4}) + + assert len(tv1) == 3 + assert len(tv1.c) == 2 + assert len(tv2) == 4 + assert len(tv2.c) == 0 + + def test_tree_value_bool(self): + tv1 = treevalue_class({'a': 1, 'b': 2, 'c': {'x': 2, 'y': 3}}) + tv2 = treevalue_class({'a': 1, 'b': 2, 'c': {}, 'd': 4}) + + assert tv1 + assert tv1.c + assert tv2 + assert not tv2.c + + def test_tree_value_hash_equal(self): + tv1 = treevalue_class({'a': 1, 'b': 2, 'c': {'x': 2, 'y': 3}}) + assert tv1 == tv1 + assert not tv1 == 2 + assert tv1 == treevalue_class({'a': 1, 'b': 2, 'c': {'x': 2, 'y': 3}}) + assert tv1 != treevalue_class({'a': 1, 'b': 2, 'c': {'x': 2, 'y': 4}}) + assert tv1.c == treevalue_class({'x': 2, 'y': 3}) + assert tv1.c != treevalue_class({'x': 2, 'y': 3, 'z': 4}) + + d = { + tv1: 1, + tv1.c: 2 + } + assert d[tv1] == 1 + assert d[treevalue_class({'a': 1, 'b': 2, 'c': {'x': 2, 'y': 3}})] == 1 + assert d[treevalue_class({'x': 2, 'y': 3})] == 2 + + def test_serialize_support(self): + tv1 = treevalue_class({'a': 1, 'b': 2, 'c': {'x': 2, 'y': 3}}) + bt1 = pickle.dumps(tv1) + assert pickle.loads(bt1) == tv1 + + tv2 = treevalue_class({ + 'a': _Container(1), + 'b': _Container(2), + 'x': { + 'c': _Container(3), + 'd': _Container(4), + } + }) + bt2 = pickle.dumps(tv2) + assert pickle.loads(bt2) == tv2 + + # noinspection PyTypeChecker + def test_get(self): + tv1 = treevalue_class({'a': 1, 'b': 2, 'c': {'x': 2, 'y': 3}, 'd': raw({'x': 2, 'y': 3})}) + + assert tv1.get('a') == 1 + assert tv1.get('b') == 2 + assert tv1.get('c') == treevalue_class({'x': 2, 'y': 3}) + assert tv1.get('d') == {'x': 2, 'y': 3} + assert tv1.get('e') is None + assert tv1.get('e', 233) == 233 + + tv1 = treevalue_class({'a': 1, 'b': 2, 'c': {'x': 2, 'y': 3}, 'd': raw({'x': 2, 'y': 3})}) + tv2 = treevalue_class({ + 'a': delayed(lambda: tv1.a), + 'b': delayed(lambda: tv1.b), + 'c': delayed(lambda: tv1.c), + }) + assert tv2.get('a') == 1 + assert tv2.get('b') == 2 + assert tv2.get('c') == treevalue_class({'x': 2, 'y': 3}) + + # noinspection PyTypeChecker + def test_pop(self): + tv1 = treevalue_class({'a': 1, 'b': 2, 'c': {'x': 2, 'y': 3}, 'd': raw({'x': 2, 'y': 3})}) + + assert tv1.pop('a') == 1 + with pytest.raises(KeyError): + _ = tv1.pop('a') + assert tv1.pop('a', 233) == 233 + + assert tv1.pop('b') == 2 + assert tv1.pop('c') == treevalue_class({'x': 2, 'y': 3}) + assert tv1.pop('d') == {'x': 2, 'y': 3} + with pytest.raises(KeyError): + _ = tv1.pop('e') + assert tv1.pop('e', 233) == 233 + + tv1 = treevalue_class({'a': 1, 'b': 2, 'c': {'x': 2, 'y': 3}, 'd': raw({'x': 2, 'y': 3})}) + tv2 = treevalue_class({ + 'a': delayed(lambda: tv1.a), + 'b': delayed(lambda: tv1.b), + 'c': delayed(lambda: tv1.c), + }) + assert tv2.pop('a') == 1 + assert tv2.pop('b') == 2 + assert tv2.pop('c') == treevalue_class({'x': 2, 'y': 3}) + + tv1 = treevalue_class({'a': 1, 'b': 2, 'c': {'x': 2, 'y': 3}, 'd': raw({'x': 2, 'y': 3})}) + tv3 = treevalue_class({'a': 233, 'b': tv1, 'c': tv1}) + assert tv3.pop('b') == tv1 + assert tv3.pop('c') == tv1 + with pytest.raises(KeyError): + tv3.pop('b') + with pytest.raises(KeyError): + tv3.pop('c') + assert tv3.pop('b', 345) == 345 + assert tv3.pop('c', 345) == 345 + + def test_popitem(self): + tv1 = treevalue_class({'a': 1, 'b': 2, 'c': {'x': 2, 'y': 3}, 'd': raw({'x': 2, 'y': 3})}) + assert sorted([tv1.popitem() for _ in range(len(tv1))]) == [ + ('a', 1), ('b', 2), + ('c', treevalue_class({'x': 2, 'y': 3})), + ('d', {'x': 2, 'y': 3}), + ] + with pytest.raises(KeyError): + tv1.popitem() + + d1 = delayed(lambda: 1) + d2 = delayed(lambda x: x + 1, d1) + tv2 = treevalue_class({'a': d1, 'b': d2, 'c': d1, 'd': 100}) + assert sorted([tv2.popitem() for _ in range(len(tv2))]) == [ + ('a', 1), ('b', 2), ('c', 1), ('d', 100), + ] + with pytest.raises(KeyError): + tv2.popitem() + + def test_clear(self): + tv1 = treevalue_class({'a': 1, 'b': 2, 'c': {'x': 2, 'y': 3}, 'd': raw({'x': 2, 'y': 3})}) + assert tv1.clear() is None + assert not tv1 + + # noinspection DuplicatedCode + def test_update(self): + tv1 = treevalue_class({'a': 1, 'b': 2, 'c': {'x': 2, 'y': 3}, 'd': raw({'x': 2, 'y': 3})}) + tv1.update({'a': 3, 'c': treevalue_class({'x': 3, 'y': 4}), 'd': {'x': 200, 'y': 300}}) + assert tv1 == treevalue_class({ + 'a': 3, 'b': 2, + 'c': {'x': 3, 'y': 4}, + 'd': raw({'x': 200, 'y': 300}), + }) + + tv2 = treevalue_class({'a': 1, 'b': 2, 'c': {'x': 2, 'y': 3}, 'd': raw({'x': 2, 'y': 3})}) + tv2.update(a=3, c=treevalue_class({'x': 3, 'y': 4}), d={'x': 200, 'y': 300}) + assert tv2 == treevalue_class({ + 'a': 3, 'b': 2, + 'c': {'x': 3, 'y': 4}, + 'd': raw({'x': 200, 'y': 300}), + }) + + tv3 = treevalue_class({'a': 1, 'b': 2, 'c': {'x': 2, 'y': 3}, 'd': raw({'x': 2, 'y': 3})}) + tv3.update(treevalue_class({'a': 3, 'c': {'x': 3, 'y': 4}, 'd': raw({'x': 200, 'y': 300})})) + assert tv3 == treevalue_class({ + 'a': 3, 'b': 2, + 'c': {'x': 3, 'y': 4}, + 'd': raw({'x': 200, 'y': 300}), + }) + + tv4 = treevalue_class({'a': 1, 'b': 2, 'c': {'x': 2, 'y': 3}, 'd': raw({'x': 2, 'y': 3})}) + # noinspection PyTypeChecker + tv4.update(create_storage({'a': 3, 'c': {'x': 3, 'y': 4}, 'd': raw({'x': 200, 'y': 300})})) + assert tv4 == treevalue_class({ + 'a': 3, 'b': 2, + 'c': {'x': 3, 'y': 4}, + 'd': raw({'x': 200, 'y': 300}), + }) + + tv5 = treevalue_class({'a': 1, 'b': 2, 'c': {'x': 2, 'y': 3}, 'd': raw({'x': 2, 'y': 3})}) + with pytest.raises(TypeError): + tv5.update('sdklfj') + with pytest.raises(TypeError): + tv5.update(123) + + tv6 = treevalue_class({'a': 1, 'b': 2, 'c': {'x': 2, 'y': 3}, 'd': raw({'x': 2, 'y': 3})}) + tv6.update({'a': 3, 'c': treevalue_class({'x': 3, 'y': 4}), 'd': {'x': 200, 'y': 300}}, a=50, f='dfkl') + assert tv6 == treevalue_class({ + 'a': 50, 'b': 2, 'f': 'dfkl', + 'c': {'x': 3, 'y': 4}, + 'd': raw({'x': 200, 'y': 300}), + }) + + def test_keys(self): + tv1 = treevalue_class({'a': 1, 'b': 2, 'c': {'x': 2, 'y': 3}, 'd': raw({'x': 2, 'y': 3})}) + assert len(tv1.keys()) == 4 + assert set(tv1.keys()) == {'a', 'b', 'c', 'd'} + assert 'a' in tv1.keys() + assert 'b' in tv1.keys() + assert 'c' in tv1.keys() + assert 'd' in tv1.keys() + assert 'e' not in tv1.keys() + + assert repr(tv1.keys()) == "treevalue_keys(['a', 'b', 'c', 'd'])" + if _reversible: + assert list(reversed(tv1.keys())) == list(tv1.keys())[::-1] + else: + with pytest.raises(TypeError): + reversed(tv1.keys()) + + def test_values(self): + tv1 = treevalue_class({'a': 1, 'b': 2, 'c': {'x': 2, 'y': 3}}) + assert len(tv1.values()) == 3 + assert set(tv1.c.values()) == {2, 3} + assert 1 in tv1.values() + assert 2 in tv1.values() + assert 3 not in tv1.values() + assert treevalue_class({'x': 2, 'y': 3}) in tv1.values() + assert treevalue_class({'x': 2, 'y': 4}) not in tv1.values() + + assert repr(treevalue_class({'a': 1, 'b': 2}).values()) == 'treevalue_values([1, 2])' + if _reversible: + assert list(reversed(tv1.values())) == list(tv1.values())[::-1] + else: + with pytest.raises(TypeError): + reversed(tv1.values()) + + def test_items(self): + tv1 = treevalue_class({'a': 1, 'b': 2, 'c': {'x': 2, 'y': 3}, 'd': raw({'x': 2, 'y': 3})}) + assert len(tv1.items()) == 4 + assert sorted(tv1.items()) == [ + ('a', 1), + ('b', 2), + ('c', treevalue_class({'x': 2, 'y': 3})), + ('d', {'x': 2, 'y': 3}), + ] + assert ('a', 1) in tv1.items() + assert ('b', 2) in tv1.items() + assert ('a', 2) not in tv1.items() + assert ('c', treevalue_class({'x': 2, 'y': 3})) in tv1.items() + assert ('c', treevalue_class({'x': 2, 'y': 4})) not in tv1.items() + assert ('d', {'x': 2, 'y': 3}) in tv1.items() + assert ('d', {'x': 2, 'y': 4}) not in tv1.items() + + assert repr(treevalue_class({'a': 1, 'b': 2}).items()) == "treevalue_items([('a', 1), ('b', 2)])" + if _reversible: + assert list(reversed(tv1.items())) == list(tv1.items())[::-1] + else: + with pytest.raises(TypeError): + reversed(tv1.items()) + + class MyTreeValue(treevalue_class): + pass + + tv2 = MyTreeValue({'a': 1, 'b': 2, 'c': {'x': 2, 'y': 3}, 'd': raw({'x': 2, 'y': 3})}) + assert sorted(tv2.items()) == [ + ('a', 1), + ('b', 2), + ('c', MyTreeValue({'x': 2, 'y': 3})), + ('d', {'x': 2, 'y': 3}), + ] + + return _TestClass diff --git a/test/tree/tree/test_tree.py b/test/tree/tree/test_tree.py index a67bc4b233..d4b5c96acb 100644 --- a/test/tree/tree/test_tree.py +++ b/test/tree/tree/test_tree.py @@ -1,515 +1,9 @@ -import pickle -import re - import pytest -from treevalue import raw, TreeValue, delayed -from treevalue.tree.common import create_storage - -try: - _ = reversed({}.keys()) -except TypeError: - _reversible = False -else: - _reversible = True - - -class _Container: - def __init__(self, value): - self.__value = value - - @property - def value(self): - return self.__value - - def __repr__(self): - return '<{cls} {id} value: {value}>'.format( - cls=self.__class__.__name__, id=hex(id(self)), value=repr(self.__value)) - - def __eq__(self, other): - if other is self: - return True - elif type(other) == _Container: - return other.__value == self.value - else: - return False - - def __hash__(self): - return hash((self.__value,)) +from treevalue import TreeValue +from .base import get_treevalue_test @pytest.mark.unittest -class TestTreeTreeTree: - def test_tree_value_init(self): - tv1 = TreeValue({'a': 1, 'b': 2, 'c': {'x': 2, 'y': 3}}) - assert tv1.a == 1 - assert tv1.b == 2 - assert tv1.c == TreeValue({'x': 2, 'y': 3}) - - tv2 = TreeValue(tv1) - assert tv2.a == 1 - assert tv2.b == 2 - - tv3 = TreeValue({'a': tv1, 'b': tv2, 'c': tv1}) - assert tv3.a.a == 1 - assert tv3.b.a == 1 - assert tv3.c.a == 1 - - # with usage of raw function - tv4 = TreeValue({'a': 1, 'b': 2, 'c': {'x': 2, 'y': 3}, 'd': raw({'x': 2, 'y': 3})}) - assert tv4.a == 1 - assert tv4.b == 2 - assert tv4.c == TreeValue({'x': 2, 'y': 3}) - assert tv4.c.x == 2 - assert tv4.c.y == 3 - assert tv4.d == {'x': 2, 'y': 3} - with pytest.raises(AttributeError): # error, tv4.d is a dict - _ = tv4.d.x - with pytest.raises(AttributeError): # error, tv4.d is a dict - _ = tv4.d.y - - with pytest.raises(TypeError): - TreeValue(1) - - class MyTreeValue(TreeValue): - pass - - tv4 = MyTreeValue({'a': tv1.c, 'x': {'b': tv1, 'c': tv2.c}}) - assert isinstance(tv4.a, MyTreeValue) - assert isinstance(tv4.x, MyTreeValue) - assert isinstance(tv4.x.b, MyTreeValue) - assert isinstance(tv4.x.c, MyTreeValue) - - tv5 = MyTreeValue({'a': tv1.c, 'x': {'b': tv1._detach(), 'c': tv2.c}}) - assert isinstance(tv5.a, MyTreeValue) - assert isinstance(tv5.x, MyTreeValue) - assert isinstance(tv5.x.b, MyTreeValue) - assert isinstance(tv5.x.c, MyTreeValue) - - def test_tree_value_init_with_item(self): - tv1 = TreeValue({'a': 1, 'b': 2, 'c': {'x': 2, 'y': 3}}) - assert tv1['a'] == 1 - assert tv1['b'] == 2 - - tv2 = TreeValue(tv1) - assert tv2['a'] == 1 - assert tv2['b'] == 2 - - tv3 = TreeValue({'a': tv1, 'b': tv2, 'c': tv1}) - assert tv3['a']['a'] == 1 - assert tv3['b']['a'] == 1 - assert tv3['c']['a'] == 1 - - with pytest.raises(KeyError): - _ = tv3['g'] - with pytest.raises(KeyError): - _ = tv3[0] - - def test_tree_value_operate(self): - tv1 = TreeValue({'a': 1, 'b': 2, 'c': {'x': 2, 'y': 3}}) - tv2 = TreeValue(tv1) - tv3 = TreeValue({'a': tv1, 'b': tv2, 'c': tv1}) - - tv1.a = 3 - assert tv1.a == 3 - assert tv2.a == 3 - assert tv3.a.a == 3 - assert tv3.b.a == 3 - assert tv3.c.a == 3 - - del tv1.b - assert 'b' not in tv1 - assert 'b' not in tv2 - assert 'b' not in tv3.a - assert 'b' not in tv3.b - assert 'b' not in tv3.c - - with pytest.raises(AttributeError): - _ = tv1.dd - - tv1.a = TreeValue({'a1': 1, 'a2': 2}) - assert tv1.a.a1 == 1 - assert tv2.a.a1 == 1 - assert tv3.a.a.a1 == 1 - - tv1.a = TreeValue({'a1': 2, 'a2': 1}) - assert tv1.a.a1 == 2 - assert tv2.a.a1 == 2 - assert tv3.a.a.a1 == 2 - - with pytest.raises(AttributeError): - del tv1._property__data - - tv1.ff = raw(1) - assert tv1.ff == 1 - tv1.fff = raw({'x': 1, 'y': 2}) - assert isinstance(tv1.fff, dict) - assert tv1.fff == {'x': 1, 'y': 2} - - def test_setdefault(self): - t = TreeValue({}) - assert t.setdefault('a', 1) == 1 - assert t == TreeValue({'a': 1}) - assert t.setdefault('a', 100) == 1 - assert t == TreeValue({'a': 1}) - - assert t.setdefault('f', {'a': 1, 'b': 2}) == {'a': 1, 'b': 2} - assert t == TreeValue({'a': 1, 'f': raw({'a': 1, 'b': 2})}) - assert t.setdefault('f', {'y': 1, 'z': 2}) == {'a': 1, 'b': 2} - assert t == TreeValue({'a': 1, 'f': raw({'a': 1, 'b': 2})}) - - assert t.setdefault('c', TreeValue({'a': 1, 'b': 2})) == TreeValue({'a': 1, 'b': 2}) - assert t == TreeValue({'a': 1, 'f': raw({'a': 1, 'b': 2}), 'c': {'a': 1, 'b': 2}}) - assert t.setdefault('c', TreeValue({'aa': 1, 'bb': 2})) == TreeValue({'a': 1, 'b': 2}) - assert t == TreeValue({'a': 1, 'f': raw({'a': 1, 'b': 2}), 'c': {'a': 1, 'b': 2}}) - - d = delayed(lambda: 1) - assert t.setdefault('g', delayed(lambda x: x + 1, d)) == 2 - assert t == TreeValue({'a': 1, 'f': raw({'a': 1, 'b': 2}), 'c': {'a': 1, 'b': 2}, 'g': 2}) - assert t.setdefault('g', delayed(lambda x: x + 100, d)) == 2 - assert t == TreeValue({'a': 1, 'f': raw({'a': 1, 'b': 2}), 'c': {'a': 1, 'b': 2}, 'g': 2}) - - def test_tree_value_operate_with_item(self): - tv1 = TreeValue({'a': 1, 'b': 2, 'c': {'x': 2, 'y': 3}}) - tv2 = TreeValue(tv1) - tv3 = TreeValue({'a': tv1, 'b': tv2, 'c': tv1}) - tv4 = TreeValue({'a': raw({'a': 1, 'y': 2}), 'c': {'x': raw({'a': 3, 'y': 4}), }}) - - tv1['a'] = 3 - assert tv1.a == 3 - assert tv2.a == 3 - assert tv3.a.a == 3 - assert tv3.b.a == 3 - assert tv3.c.a == 3 - - assert tv4['a'] == {'a': 1, 'y': 2} - assert tv4['c'] == TreeValue({'x': raw({'a': 3, 'y': 4})}) - with pytest.raises(KeyError): - _ = tv4['y'] - with pytest.raises(KeyError): - _ = tv4[['c']] - - tv1['f'] = 333 - assert tv1.f == 333 - assert tv1['f'] == 333 - assert 'f' in tv1 - - with pytest.raises(NotImplementedError): - tv1[0] = 3 - with pytest.raises(NotImplementedError): - tv1[['c']] = 3 - - del tv1['b'] - assert 'b' not in tv1 - assert 'b' not in tv2 - assert 'b' not in tv3.a - assert 'b' not in tv3.b - assert 'b' not in tv3.c - - with pytest.raises(KeyError): - del tv1['g'] - with pytest.raises(KeyError): - del tv1[['c']] - with pytest.raises(KeyError): - del tv1[0] - - def test_tree_value_repr(self): - tv1 = TreeValue({'a': 1, 'b': 2, 'c': {'x': 2, 'y': 3}}) - - assert re.match(r"", repr(tv1)) - assert re.match(r"", repr(tv1.c)) - assert "'a' --> 1" in str(tv1) - assert "'b' --> 2" in str(tv1) - assert "'x' --> 2" in str(tv1) - assert "'y' --> 3" in str(tv1) - assert "'c' --> ", repr(tv2)) - assert re.match(r"", repr(tv2.c)) - assert "'a' --> 1" in repr(tv2) - assert "'b' --> 2" in repr(tv2) - assert "'x' --> 2" in repr(tv2) - assert "'y' --> 3" in repr(tv2) - assert "'c' --> )" in repr(tv2) - - tv3 = TreeValue({ - 'a': delayed(lambda: tv1.a), - 'b': delayed(lambda: tv1.b), - 'c': delayed(lambda: tv1.c), - }) - - assert re.match(r"", repr(tv3)) - assert re.match(r"", repr(tv3.c)) - assert "'a' --> 1" in str(tv3) - assert "'b' --> 2" in str(tv3) - assert "'x' --> 2" in str(tv3) - assert "'y' --> 3" in str(tv3) - assert "'c' -->