Ejemplo n.º 1
0
    def test_wrapped_attribute(self):
        def function1(*args, **kwargs):
            return args, kwargs

        function2 = wrapt.ObjectProxy(function1)

        function2.variable = True

        self.assertTrue(hasattr(function1, 'variable'))
        self.assertTrue(hasattr(function2, 'variable'))

        self.assertEqual(function2.variable, True)

        del function2.variable

        self.assertFalse(hasattr(function1, 'variable'))
        self.assertFalse(hasattr(function2, 'variable'))

        self.assertEqual(getattr(function2, 'variable', None), None)
Ejemplo n.º 2
0
from threading import RLock
from typing import ContextManager

import wrapt
from decorator import contextmanager

from telemetry.api import Telemetry, TelemetryMixin, Attributes, Attribute, Label
from telemetry.api.decorator import trace, extract_args
from telemetry.api.metrics import Metrics
from telemetry.api.trace import Tracer, SpanKind, Span, AttributeValue

telemetry: Telemetry = wrapt.ObjectProxy(Telemetry())
tracer: Tracer = wrapt.ObjectProxy(telemetry.tracer)
metrics: Metrics = wrapt.ObjectProxy(telemetry.metrics)

_telemetry_lock = RLock()


def get_telemetry() -> Telemetry:
    return telemetry.__wrapped__


def set_telemetry(instance: Telemetry):
    """
    UNIT TEST ONLY!

    Replace current telemetry instance with a new instance.

    TODO: Add "test only" check to this method
    TODO: use a read-write lock instead
Ejemplo n.º 3
0
    def test_float(self):
        one = wrapt.ObjectProxy(1)

        self.assertEqual(float(one), 1.0)
Ejemplo n.º 4
0
    def test_str_format(self):
        instance = 'abcd'

        proxy = wrapt.ObjectProxy(instance)

        self.assertEqual(format(instance, 's'), format(proxy, 's'))
Ejemplo n.º 5
0
    def test_proxy_getattr_call(self):
        proxy = wrapt.ObjectProxy(None)

        self.assertEqual(getattr(proxy, '__call__', None), None)
Ejemplo n.º 6
0
    def test_repr(self):
        number = 10
        value = wrapt.ObjectProxy(number)

        self.assertNotEqual(repr(value).find('ObjectProxy at'), -1)
Ejemplo n.º 7
0
    def test_contains(self):
        value = wrapt.ObjectProxy(dict.fromkeys(range(3), False))

        self.assertTrue(2 in value)
        self.assertFalse(-2 in value)
Ejemplo n.º 8
0
    def test_setslice(self):
        value = wrapt.ObjectProxy(list(range(5)))

        value[1:4] = reversed(value[1:4])

        self.assertEqual(value[1:4], [3, 2, 1])
Ejemplo n.º 9
0
    def test_pos(self):
        value = wrapt.ObjectProxy(1)

        self.assertEqual(+value, 1)
Ejemplo n.º 10
0
    def test_neg(self):
        value = wrapt.ObjectProxy(1)

        self.assertEqual(-value, -1)
    def test_object_hash(self):
        def function1(*args, **kwargs):
            return args, kwargs
        function2 = wrapt.ObjectProxy(function1)

        self.assertEqual(hash(function2), hash(function1))
    def test_attributes(self):
        def function1(*args, **kwargs):
            return args, kwargs
        function2 = wrapt.ObjectProxy(function1)

        self.assertEqual(function2.__wrapped__, function1)
Ejemplo n.º 13
0
class NestTest(parameterized.TestCase):
    def assertAllEquals(self, a, b):
        self.assertTrue((np.asarray(a) == b).all())

    def testAttrsFlattenAndUnflatten(self):
        class BadAttr(object):
            """Class that has a non-iterable __attrs_attrs__."""
            __attrs_attrs__ = None

        @attr.s
        class SampleAttr(object):
            field1 = attr.ib()
            field2 = attr.ib()

        field_values = [1, 2]
        sample_attr = SampleAttr(*field_values)
        self.assertFalse(tree._is_attrs(field_values))
        self.assertTrue(tree._is_attrs(sample_attr))
        flat = tree.flatten(sample_attr)
        self.assertEqual(field_values, flat)
        restructured_from_flat = tree.unflatten_as(sample_attr, flat)
        self.assertIsInstance(restructured_from_flat, SampleAttr)
        self.assertEqual(restructured_from_flat, sample_attr)

        # Check that flatten fails if attributes are not iterable
        with self.assertRaisesRegex(TypeError, "object is not iterable"):
            flat = tree.flatten(BadAttr())

    @parameterized.parameters([
        (1, 2, 3), ({
            "B": 10,
            "A": 20
        }, [1, 2], 3), ((1, 2), [3, 4], 5),
        (collections.namedtuple("Point", ["x", "y"])(1, 2), 3, 4),
        wrapt.ObjectProxy((collections.namedtuple("Point",
                                                  ["x", "y"])(1, 2), 3, 4))
    ])
    def testAttrsMapStructure(self, *field_values):
        @attr.s
        class SampleAttr(object):
            field3 = attr.ib()
            field1 = attr.ib()
            field2 = attr.ib()

        structure = SampleAttr(*field_values)
        new_structure = tree.map_structure(lambda x: x, structure)
        self.assertEqual(structure, new_structure)

    def testFlattenAndUnflatten(self):
        structure = ((3, 4), 5, (6, 7, (9, 10), 8))
        flat = ["a", "b", "c", "d", "e", "f", "g", "h"]
        self.assertEqual(tree.flatten(structure), [3, 4, 5, 6, 7, 9, 10, 8])
        self.assertEqual(tree.unflatten_as(structure, flat),
                         (("a", "b"), "c", ("d", "e", ("f", "g"), "h")))
        point = collections.namedtuple("Point", ["x", "y"])
        structure = (point(x=4, y=2), ((point(x=1, y=0), ), ))
        flat = [4, 2, 1, 0]
        self.assertEqual(tree.flatten(structure), flat)
        restructured_from_flat = tree.unflatten_as(structure, flat)
        self.assertEqual(restructured_from_flat, structure)
        self.assertEqual(restructured_from_flat[0].x, 4)
        self.assertEqual(restructured_from_flat[0].y, 2)
        self.assertEqual(restructured_from_flat[1][0][0].x, 1)
        self.assertEqual(restructured_from_flat[1][0][0].y, 0)

        self.assertEqual([5], tree.flatten(5))
        self.assertEqual([np.array([5])], tree.flatten(np.array([5])))

        self.assertEqual("a", tree.unflatten_as(5, ["a"]))
        self.assertEqual(np.array([5]),
                         tree.unflatten_as("scalar", [np.array([5])]))

        with self.assertRaisesRegex(ValueError, "Structure is a scalar"):
            tree.unflatten_as("scalar", [4, 5])

        with self.assertRaisesRegex(TypeError, "flat_sequence"):
            tree.unflatten_as([4, 5], "bad_sequence")

        with self.assertRaises(ValueError):
            tree.unflatten_as([5, 6, [7, 8]], ["a", "b", "c"])

    def testFlattenDictOrder(self):
        ordered = collections.OrderedDict([("d", 3), ("b", 1), ("a", 0),
                                           ("c", 2)])
        plain = {"d": 3, "b": 1, "a": 0, "c": 2}
        ordered_flat = tree.flatten(ordered)
        plain_flat = tree.flatten(plain)
        self.assertEqual([0, 1, 2, 3], ordered_flat)
        self.assertEqual([0, 1, 2, 3], plain_flat)

    def testUnflattenDictOrder(self):
        ordered = collections.OrderedDict([("d", 0), ("b", 0), ("a", 0),
                                           ("c", 0)])
        plain = {"d": 0, "b": 0, "a": 0, "c": 0}
        seq = [0, 1, 2, 3]
        ordered_reconstruction = tree.unflatten_as(ordered, seq)
        plain_reconstruction = tree.unflatten_as(plain, seq)
        self.assertEqual(
            collections.OrderedDict([("d", 3), ("b", 1), ("a", 0), ("c", 2)]),
            ordered_reconstruction)
        self.assertEqual({
            "d": 3,
            "b": 1,
            "a": 0,
            "c": 2
        }, plain_reconstruction)

    def testFlattenAndUnflatten_withDicts(self):
        # A nice messy mix of tuples, lists, dicts, and `OrderedDict`s.
        named_tuple = collections.namedtuple("A", ("b", "c"))
        mess = [
            "z",
            named_tuple(3, 4), {
                "c": [
                    1,
                    collections.OrderedDict([
                        ("b", 3),
                        ("a", 2),
                    ]),
                ],
                "b": 5
            }, 17
        ]

        flattened = tree.flatten(mess)
        self.assertEqual(flattened, ["z", 3, 4, 5, 1, 2, 3, 17])

        structure_of_mess = [
            14,
            named_tuple("a", True),
            {
                "c": [
                    0,
                    collections.OrderedDict([
                        ("b", 9),
                        ("a", 8),
                    ]),
                ],
                "b": 3
            },
            "hi everybody",
        ]

        self.assertEqual(mess, tree.unflatten_as(structure_of_mess, flattened))

        # Check also that the OrderedDict was created, with the correct key order.
        unflattened_ordered_dict = tree.unflatten_as(structure_of_mess,
                                                     flattened)[2]["c"][1]
        self.assertIsInstance(unflattened_ordered_dict,
                              collections.OrderedDict)
        self.assertEqual(list(unflattened_ordered_dict.keys()), ["b", "a"])

    def testFlatten_numpyIsNotFlattened(self):
        structure = np.array([1, 2, 3])
        flattened = tree.flatten(structure)
        self.assertLen(flattened, 1)

    def testFlatten_stringIsNotFlattened(self):
        structure = "lots of letters"
        flattened = tree.flatten(structure)
        self.assertLen(flattened, 1)
        self.assertEqual(structure, tree.unflatten_as("goodbye", flattened))

    def testFlatten_bytearrayIsNotFlattened(self):
        structure = bytearray("bytes in an array", "ascii")
        flattened = tree.flatten(structure)
        self.assertLen(flattened, 1)
        self.assertEqual(flattened, [structure])
        self.assertEqual(
            structure, tree.unflatten_as(bytearray("hello", "ascii"),
                                         flattened))

    def testUnflattenSequenceAs_notIterableError(self):
        with self.assertRaisesRegex(TypeError,
                                    "flat_sequence must be a sequence"):
            tree.unflatten_as("hi", "bye")

    def testUnflattenSequenceAs_wrongLengthsError(self):
        with self.assertRaisesRegex(
                ValueError,
                "Structure had 2 elements, but flat_sequence had 3 elements."):
            tree.unflatten_as(["hello", "world"], ["and", "goodbye", "again"])

    def testUnflattenSequenceAs_defaultdict(self):
        structure = collections.defaultdict(list, [("a", [None]),
                                                   ("b", [None, None])])
        sequence = [1, 2, 3]
        expected = collections.defaultdict(list, [("a", [1]), ("b", [2, 3])])
        self.assertEqual(expected, tree.unflatten_as(structure, sequence))

    def testIsSequence(self):
        self.assertFalse(tree.is_nested("1234"))
        self.assertFalse(tree.is_nested(b"1234"))
        self.assertFalse(tree.is_nested(u"1234"))
        self.assertFalse(tree.is_nested(bytearray("1234", "ascii")))
        self.assertTrue(tree.is_nested([1, 3, [4, 5]]))
        self.assertTrue(tree.is_nested(((7, 8), (5, 6))))
        self.assertTrue(tree.is_nested([]))
        self.assertTrue(tree.is_nested({"a": 1, "b": 2}))
        self.assertFalse(tree.is_nested(set([1, 2])))
        ones = np.ones([2, 3])
        self.assertFalse(tree.is_nested(ones))
        self.assertFalse(tree.is_nested(np.tanh(ones)))
        self.assertFalse(tree.is_nested(np.ones((4, 5))))

    # pylint does not correctly recognize these as class names and
    # suggests to use variable style under_score naming.
    # pylint: disable=invalid-name
    Named0ab = collections.namedtuple("named_0", ("a", "b"))
    Named1ab = collections.namedtuple("named_1", ("a", "b"))
    SameNameab = collections.namedtuple("same_name", ("a", "b"))
    SameNameab2 = collections.namedtuple("same_name", ("a", "b"))
    SameNamexy = collections.namedtuple("same_name", ("x", "y"))
    SameName1xy = collections.namedtuple("same_name_1", ("x", "y"))
    SameName1xy2 = collections.namedtuple("same_name_1", ("x", "y"))
    NotSameName = collections.namedtuple("not_same_name", ("a", "b"))

    # pylint: enable=invalid-name

    class SameNamedType1(SameNameab):
        pass

    # pylint: disable=g-error-prone-assert-raises
    def testAssertSameStructure(self):
        tree.assert_same_structure(STRUCTURE1, STRUCTURE2)
        tree.assert_same_structure("abc", 1.0)
        tree.assert_same_structure(b"abc", 1.0)
        tree.assert_same_structure(u"abc", 1.0)
        tree.assert_same_structure(bytearray("abc", "ascii"), 1.0)
        tree.assert_same_structure("abc", np.array([0, 1]))

    def testAssertSameStructure_differentNumElements(self):
        with self.assertRaisesRegex(
                ValueError,
            ("The two structures don't have the same nested structure\\.\n\n"
             "First structure:.*?\n\n"
             "Second structure:.*\n\n"
             "More specifically: Substructure "
             r'"type=tuple str=\(\(1, 2\), 3\)" is a sequence, while '
             'substructure "type=str str=spam" is not\n'
             "Entire first structure:\n"
             r"\(\(\(\., \.\), \.\), \., \(\., \.\)\)\n"
             "Entire second structure:\n"
             r"\(\., \.\)")):
            tree.assert_same_structure(STRUCTURE1,
                                       STRUCTURE_DIFFERENT_NUM_ELEMENTS)

    def testAssertSameStructure_listVsNdArray(self):
        with self.assertRaisesRegex(
                ValueError,
            ("The two structures don't have the same nested structure\\.\n\n"
             "First structure:.*?\n\n"
             "Second structure:.*\n\n"
             r'More specifically: Substructure "type=list str=\[0, 1\]" '
             r'is a sequence, while substructure "type=ndarray str=\[0 1\]" '
             "is not")):
            tree.assert_same_structure([0, 1], np.array([0, 1]))

    def testAssertSameStructure_intVsList(self):
        with self.assertRaisesRegex(
                ValueError,
            ("The two structures don't have the same nested structure\\.\n\n"
             "First structure:.*?\n\n"
             "Second structure:.*\n\n"
             r'More specifically: Substructure "type=list str=\[0, 1\]" '
             'is a sequence, while substructure "type=int str=0" '
             "is not")):
            tree.assert_same_structure(0, [0, 1])

    def testAssertSameStructure_tupleVsList(self):
        self.assertRaises(TypeError, tree.assert_same_structure, (0, 1),
                          [0, 1])

    def testAssertSameStructure_differentNesting(self):
        with self.assertRaisesRegex(
                ValueError, ("don't have the same nested structure\\.\n\n"
                             "First structure: .*?\n\nSecond structure: ")):
            tree.assert_same_structure(STRUCTURE1, STRUCTURE_DIFFERENT_NESTING)

    def testAssertSameStructure_tupleVsNamedTuple(self):
        self.assertRaises(TypeError, tree.assert_same_structure, (0, 1),
                          NestTest.Named0ab("a", "b"))

    def testAssertSameStructure_sameNamedTupleDifferentContents(self):
        tree.assert_same_structure(NestTest.Named0ab(3, 4),
                                   NestTest.Named0ab("a", "b"))

    def testAssertSameStructure_differentNamedTuples(self):
        self.assertRaises(TypeError, tree.assert_same_structure,
                          NestTest.Named0ab(3, 4), NestTest.Named1ab(3, 4))

    def testAssertSameStructure_sameNamedTupleDifferentStructuredContents(
            self):
        with self.assertRaisesRegex(
                ValueError, ("don't have the same nested structure\\.\n\n"
                             "First structure: .*?\n\nSecond structure: ")):
            tree.assert_same_structure(NestTest.Named0ab(3, 4),
                                       NestTest.Named0ab([3], 4))

    def testAssertSameStructure_differentlyNestedLists(self):
        with self.assertRaisesRegex(
                ValueError, ("don't have the same nested structure\\.\n\n"
                             "First structure: .*?\n\nSecond structure: ")):
            tree.assert_same_structure([[3], 4], [3, [4]])

    def testAssertSameStructure_listStructureWithAndWithoutTypes(self):
        structure1_list = [[[1, 2], 3], 4, [5, 6]]
        with self.assertRaisesRegex(TypeError,
                                    "don't have the same sequence type"):
            tree.assert_same_structure(STRUCTURE1, structure1_list)
        tree.assert_same_structure(STRUCTURE1, STRUCTURE2, check_types=False)
        tree.assert_same_structure(STRUCTURE1,
                                   structure1_list,
                                   check_types=False)

    def testAssertSameStructure_dictionaryDifferentKeys(self):
        with self.assertRaisesRegex(ValueError,
                                    "don't have the same set of keys"):
            tree.assert_same_structure({"a": 1}, {"b": 1})

    def testAssertSameStructure_sameNameNamedTuples(self):
        tree.assert_same_structure(NestTest.SameNameab(0, 1),
                                   NestTest.SameNameab2(2, 3))

    def testAssertSameStructure_sameNameNamedTuplesNested(self):
        # This assertion is expected to pass: two namedtuples with the same
        # name and field names are considered to be identical.
        tree.assert_same_structure(
            NestTest.SameNameab(NestTest.SameName1xy(0, 1), 2),
            NestTest.SameNameab2(NestTest.SameName1xy2(2, 3), 4))

    def testAssertSameStructure_sameNameNamedTuplesDifferentStructure(self):
        expected_message = "The two structures don't have the same.*"
        with self.assertRaisesRegex(ValueError, expected_message):
            tree.assert_same_structure(
                NestTest.SameNameab(0, NestTest.SameNameab2(1, 2)),
                NestTest.SameNameab2(NestTest.SameNameab(0, 1), 2))

    def testAssertSameStructure_differentNameNamedStructures(self):
        self.assertRaises(TypeError, tree.assert_same_structure,
                          NestTest.SameNameab(0, 1),
                          NestTest.NotSameName(2, 3))

    def testAssertSameStructure_sameNameDifferentFieldNames(self):
        self.assertRaises(TypeError, tree.assert_same_structure,
                          NestTest.SameNameab(0, 1), NestTest.SameNamexy(2, 3))

    def testAssertSameStructure_classWrappingNamedTuple(self):
        self.assertRaises(TypeError, tree.assert_same_structure,
                          NestTest.SameNameab(0, 1),
                          NestTest.SameNamedType1(2, 3))

    # pylint: enable=g-error-prone-assert-raises

    def testMapStructure(self):
        structure2 = (((7, 8), 9), 10, (11, 12))
        structure1_plus1 = tree.map_structure(lambda x: x + 1, STRUCTURE1)
        tree.assert_same_structure(STRUCTURE1, structure1_plus1)
        self.assertAllEquals([2, 3, 4, 5, 6, 7],
                             tree.flatten(structure1_plus1))
        structure1_plus_structure2 = tree.map_structure(
            lambda x, y: x + y, STRUCTURE1, structure2)
        self.assertEqual((((1 + 7, 2 + 8), 3 + 9), 4 + 10, (5 + 11, 6 + 12)),
                         structure1_plus_structure2)

        self.assertEqual(3, tree.map_structure(lambda x: x - 1, 4))

        self.assertEqual(7, tree.map_structure(lambda x, y: x + y, 3, 4))

        # Empty structures
        self.assertEqual((), tree.map_structure(lambda x: x + 1, ()))
        self.assertEqual([], tree.map_structure(lambda x: x + 1, []))
        self.assertEqual({}, tree.map_structure(lambda x: x + 1, {}))
        empty_nt = collections.namedtuple("empty_nt", "")
        self.assertEqual(empty_nt(),
                         tree.map_structure(lambda x: x + 1, empty_nt()))

        # This is checking actual equality of types, empty list != empty tuple
        self.assertNotEqual((), tree.map_structure(lambda x: x + 1, []))

        with self.assertRaisesRegex(TypeError, "callable"):
            tree.map_structure("bad", structure1_plus1)

        with self.assertRaisesRegex(ValueError, "at least one structure"):
            tree.map_structure(lambda x: x)

        with self.assertRaisesRegex(ValueError, "same number of elements"):
            tree.map_structure(lambda x, y: None, (3, 4), (3, 4, 5))

        with self.assertRaisesRegex(ValueError, "same nested structure"):
            tree.map_structure(lambda x, y: None, 3, (3, ))

        with self.assertRaisesRegex(TypeError, "same sequence type"):
            tree.map_structure(lambda x, y: None, ((3, 4), 5), [(3, 4), 5])

        with self.assertRaisesRegex(ValueError, "same nested structure"):
            tree.map_structure(lambda x, y: None, ((3, 4), 5), (3, (4, 5)))

        structure1_list = [[[1, 2], 3], 4, [5, 6]]
        with self.assertRaisesRegex(TypeError, "same sequence type"):
            tree.map_structure(lambda x, y: None, STRUCTURE1, structure1_list)

        tree.map_structure(lambda x, y: None,
                           STRUCTURE1,
                           structure1_list,
                           check_types=False)

        with self.assertRaisesRegex(ValueError, "same nested structure"):
            tree.map_structure(lambda x, y: None, ((3, 4), 5), (3, (4, 5)),
                               check_types=False)

        with self.assertRaisesRegex(ValueError,
                                    "Only valid keyword argument.*foo"):
            tree.map_structure(lambda x: None, STRUCTURE1, foo="a")

        with self.assertRaisesRegex(ValueError,
                                    "Only valid keyword argument.*foo"):
            tree.map_structure(lambda x: None,
                               STRUCTURE1,
                               check_types=False,
                               foo="a")

    def testMapStructureWithStrings(self):
        ab_tuple = collections.namedtuple("ab_tuple", "a, b")
        inp_a = ab_tuple(a="foo", b=("bar", "baz"))
        inp_b = ab_tuple(a=2, b=(1, 3))
        out = tree.map_structure(lambda string, repeats: string * repeats,
                                 inp_a, inp_b)
        self.assertEqual("foofoo", out.a)
        self.assertEqual("bar", out.b[0])
        self.assertEqual("bazbazbaz", out.b[1])

        nt = ab_tuple(a=("something", "something_else"), b="yet another thing")
        rev_nt = tree.map_structure(lambda x: x[::-1], nt)
        # Check the output is the correct structure, and all strings are reversed.
        tree.assert_same_structure(nt, rev_nt)
        self.assertEqual(nt.a[0][::-1], rev_nt.a[0])
        self.assertEqual(nt.a[1][::-1], rev_nt.a[1])
        self.assertEqual(nt.b[::-1], rev_nt.b)

    def testAssertShallowStructure(self):
        inp_ab = ["a", "b"]
        inp_abc = ["a", "b", "c"]
        with self.assertRaisesRegex(
                ValueError,
                tree._STRUCTURES_HAVE_MISMATCHING_LENGTHS.format(
                    input_length=len(inp_ab), shallow_length=len(inp_abc))):
            tree._assert_shallow_structure(inp_abc, inp_ab)

        inp_ab1 = [(1, 1), (2, 2)]
        inp_ab2 = [[1, 1], [2, 2]]
        with self.assertRaisesWithLiteralMatch(
                TypeError,
                tree._STRUCTURES_HAVE_MISMATCHING_TYPES.format(
                    shallow_type=type(inp_ab2[0]),
                    input_type=type(inp_ab1[0]))):
            tree._assert_shallow_structure(shallow_tree=inp_ab2,
                                           input_tree=inp_ab1)

        tree._assert_shallow_structure(inp_ab2, inp_ab1, check_types=False)

        inp_ab1 = {"a": (1, 1), "b": {"c": (2, 2)}}
        inp_ab2 = {"a": (1, 1), "b": {"d": (2, 2)}}

        with self.assertRaisesWithLiteralMatch(
                ValueError, tree._SHALLOW_TREE_HAS_INVALID_KEYS.format(["d"])):
            tree._assert_shallow_structure(inp_ab2, inp_ab1)

        inp_ab = collections.OrderedDict([("a", 1), ("b", (2, 3))])
        inp_ba = collections.OrderedDict([("b", (2, 3)), ("a", 1)])
        tree._assert_shallow_structure(inp_ab, inp_ba)

        # regression test for b/130633904
        tree._assert_shallow_structure({0: "foo"}, ["foo"], check_types=False)

    def testFlattenUpTo(self):
        # Shallow tree ends at scalar.
        input_tree = [[[2, 2], [3, 3]], [[4, 9], [5, 5]]]
        shallow_tree = [[True, True], [False, True]]
        flattened_input_tree = tree.flatten_up_to(shallow_tree, input_tree)
        flattened_shallow_tree = tree.flatten_up_to(shallow_tree, shallow_tree)
        self.assertEqual(flattened_input_tree,
                         [[2, 2], [3, 3], [4, 9], [5, 5]])
        self.assertEqual(flattened_shallow_tree, [True, True, False, True])

        # Shallow tree ends at string.
        input_tree = [[("a", 1), [("b", 2), [("c", 3), [("d", 4)]]]]]
        shallow_tree = [["level_1", ["level_2", ["level_3", ["level_4"]]]]]
        input_tree_flattened_as_shallow_tree = tree.flatten_up_to(
            shallow_tree, input_tree)
        input_tree_flattened = tree.flatten(input_tree)
        self.assertEqual(input_tree_flattened_as_shallow_tree, [("a", 1),
                                                                ("b", 2),
                                                                ("c", 3),
                                                                ("d", 4)])
        self.assertEqual(input_tree_flattened,
                         ["a", 1, "b", 2, "c", 3, "d", 4])

        # Make sure dicts are correctly flattened, yielding values, not keys.
        input_tree = {"a": 1, "b": {"c": 2}, "d": [3, (4, 5)]}
        shallow_tree = {"a": 0, "b": 0, "d": [0, 0]}
        input_tree_flattened_as_shallow_tree = tree.flatten_up_to(
            shallow_tree, input_tree)
        self.assertEqual(input_tree_flattened_as_shallow_tree,
                         [1, {
                             "c": 2
                         }, 3, (4, 5)])

        # Namedtuples.
        ab_tuple = collections.namedtuple("ab_tuple", "a, b")
        input_tree = ab_tuple(a=[0, 1], b=2)
        shallow_tree = ab_tuple(a=0, b=1)
        input_tree_flattened_as_shallow_tree = tree.flatten_up_to(
            shallow_tree, input_tree)
        self.assertEqual(input_tree_flattened_as_shallow_tree, [[0, 1], 2])

        # Attrs.
        @attr.s
        class ABAttr(object):
            a = attr.ib()
            b = attr.ib()

        input_tree = ABAttr(a=[0, 1], b=2)
        shallow_tree = ABAttr(a=0, b=1)
        input_tree_flattened_as_shallow_tree = tree.flatten_up_to(
            shallow_tree, input_tree)
        self.assertEqual(input_tree_flattened_as_shallow_tree, [[0, 1], 2])

        # Nested dicts, OrderedDicts and namedtuples.
        input_tree = collections.OrderedDict([
            ("a", ab_tuple(a=[0, {
                "b": 1
            }], b=2)), ("c", {
                "d": 3,
                "e": collections.OrderedDict([("f", 4)])
            })
        ])
        shallow_tree = input_tree
        input_tree_flattened_as_shallow_tree = tree.flatten_up_to(
            shallow_tree, input_tree)
        self.assertEqual(input_tree_flattened_as_shallow_tree, [0, 1, 2, 3, 4])
        shallow_tree = collections.OrderedDict([("a", 0),
                                                ("c", {
                                                    "d": 3,
                                                    "e": 1
                                                })])
        input_tree_flattened_as_shallow_tree = tree.flatten_up_to(
            shallow_tree, input_tree)
        self.assertEqual(input_tree_flattened_as_shallow_tree, [
            ab_tuple(a=[0, {
                "b": 1
            }], b=2), 3,
            collections.OrderedDict([("f", 4)])
        ])
        shallow_tree = collections.OrderedDict([("a", 0), ("c", 0)])
        input_tree_flattened_as_shallow_tree = tree.flatten_up_to(
            shallow_tree, input_tree)
        self.assertEqual(input_tree_flattened_as_shallow_tree, [
            ab_tuple(a=[0, {
                "b": 1
            }], b=2), {
                "d": 3,
                "e": collections.OrderedDict([("f", 4)])
            }
        ])

        ## Shallow non-list edge-case.
        # Using iterable elements.
        input_tree = ["input_tree"]
        shallow_tree = "shallow_tree"
        flattened_input_tree = tree.flatten_up_to(shallow_tree, input_tree)
        flattened_shallow_tree = tree.flatten_up_to(shallow_tree, shallow_tree)
        self.assertEqual(flattened_input_tree, [input_tree])
        self.assertEqual(flattened_shallow_tree, [shallow_tree])

        input_tree = ["input_tree_0", "input_tree_1"]
        shallow_tree = "shallow_tree"
        flattened_input_tree = tree.flatten_up_to(shallow_tree, input_tree)
        flattened_shallow_tree = tree.flatten_up_to(shallow_tree, shallow_tree)
        self.assertEqual(flattened_input_tree, [input_tree])
        self.assertEqual(flattened_shallow_tree, [shallow_tree])

        # Using non-iterable elements.
        input_tree = [0]
        shallow_tree = 9
        flattened_input_tree = tree.flatten_up_to(shallow_tree, input_tree)
        flattened_shallow_tree = tree.flatten_up_to(shallow_tree, shallow_tree)
        self.assertEqual(flattened_input_tree, [input_tree])
        self.assertEqual(flattened_shallow_tree, [shallow_tree])

        input_tree = [0, 1]
        shallow_tree = 9
        flattened_input_tree = tree.flatten_up_to(shallow_tree, input_tree)
        flattened_shallow_tree = tree.flatten_up_to(shallow_tree, shallow_tree)
        self.assertEqual(flattened_input_tree, [input_tree])
        self.assertEqual(flattened_shallow_tree, [shallow_tree])

        ## Both non-list edge-case.
        # Using iterable elements.
        input_tree = "input_tree"
        shallow_tree = "shallow_tree"
        flattened_input_tree = tree.flatten_up_to(shallow_tree, input_tree)
        flattened_shallow_tree = tree.flatten_up_to(shallow_tree, shallow_tree)
        self.assertEqual(flattened_input_tree, [input_tree])
        self.assertEqual(flattened_shallow_tree, [shallow_tree])

        # Using non-iterable elements.
        input_tree = 0
        shallow_tree = 0
        flattened_input_tree = tree.flatten_up_to(shallow_tree, input_tree)
        flattened_shallow_tree = tree.flatten_up_to(shallow_tree, shallow_tree)
        self.assertEqual(flattened_input_tree, [input_tree])
        self.assertEqual(flattened_shallow_tree, [shallow_tree])

        ## Input non-list edge-case.
        # Using iterable elements.
        input_tree = "input_tree"
        shallow_tree = ["shallow_tree"]
        with self.assertRaisesWithLiteralMatch(
                TypeError,
                tree._IF_SHALLOW_IS_SEQ_INPUT_MUST_BE_SEQ.format(
                    type(input_tree))):
            flattened_input_tree = tree.flatten_up_to(shallow_tree, input_tree)
        flattened_shallow_tree = tree.flatten_up_to(shallow_tree, shallow_tree)
        self.assertEqual(flattened_shallow_tree, shallow_tree)

        input_tree = "input_tree"
        shallow_tree = ["shallow_tree_9", "shallow_tree_8"]
        with self.assertRaisesWithLiteralMatch(
                TypeError,
                tree._IF_SHALLOW_IS_SEQ_INPUT_MUST_BE_SEQ.format(
                    type(input_tree))):
            flattened_input_tree = tree.flatten_up_to(shallow_tree, input_tree)
        flattened_shallow_tree = tree.flatten_up_to(shallow_tree, shallow_tree)
        self.assertEqual(flattened_shallow_tree, shallow_tree)

        # Using non-iterable elements.
        input_tree = 0
        shallow_tree = [9]
        with self.assertRaisesWithLiteralMatch(
                TypeError,
                tree._IF_SHALLOW_IS_SEQ_INPUT_MUST_BE_SEQ.format(
                    type(input_tree))):
            flattened_input_tree = tree.flatten_up_to(shallow_tree, input_tree)
        flattened_shallow_tree = tree.flatten_up_to(shallow_tree, shallow_tree)
        self.assertEqual(flattened_shallow_tree, shallow_tree)

        input_tree = 0
        shallow_tree = [9, 8]
        with self.assertRaisesWithLiteralMatch(
                TypeError,
                tree._IF_SHALLOW_IS_SEQ_INPUT_MUST_BE_SEQ.format(
                    type(input_tree))):
            flattened_input_tree = tree.flatten_up_to(shallow_tree, input_tree)
        flattened_shallow_tree = tree.flatten_up_to(shallow_tree, shallow_tree)
        self.assertEqual(flattened_shallow_tree, shallow_tree)

    def testByteStringsNotTreatedAsIterable(self):
        structure = [u"unicode string", b"byte string"]
        flattened_structure = tree.flatten_up_to(structure, structure)
        self.assertEqual(structure, flattened_structure)

    def testFlattenWithPathUpTo(self):
        def get_paths_and_values(shallow_tree, input_tree):
            path_value_pairs = tree.flatten_with_path_up_to(
                shallow_tree, input_tree)
            paths = [p for p, _ in path_value_pairs]
            values = [v for _, v in path_value_pairs]
            return paths, values

        # Shallow tree ends at scalar.
        input_tree = [[[2, 2], [3, 3]], [[4, 9], [5, 5]]]
        shallow_tree = [[True, True], [False, True]]
        (flattened_input_tree_paths,
         flattened_input_tree) = get_paths_and_values(shallow_tree, input_tree)
        (flattened_shallow_tree_paths,
         flattened_shallow_tree) = get_paths_and_values(
             shallow_tree, shallow_tree)
        self.assertEqual(flattened_input_tree_paths, [(0, 0), (0, 1), (1, 0),
                                                      (1, 1)])
        self.assertEqual(flattened_input_tree,
                         [[2, 2], [3, 3], [4, 9], [5, 5]])
        self.assertEqual(flattened_shallow_tree_paths, [(0, 0), (0, 1), (1, 0),
                                                        (1, 1)])
        self.assertEqual(flattened_shallow_tree, [True, True, False, True])

        # Shallow tree ends at string.
        input_tree = [[("a", 1), [("b", 2), [("c", 3), [("d", 4)]]]]]
        shallow_tree = [["level_1", ["level_2", ["level_3", ["level_4"]]]]]
        (input_tree_flattened_as_shallow_tree_paths,
         input_tree_flattened_as_shallow_tree) = get_paths_and_values(
             shallow_tree, input_tree)
        input_tree_flattened_paths = [
            p for p, _ in tree.flatten_with_path(input_tree)
        ]
        input_tree_flattened = tree.flatten(input_tree)
        self.assertEqual(input_tree_flattened_as_shallow_tree_paths,
                         [(0, 0), (0, 1, 0), (0, 1, 1, 0), (0, 1, 1, 1, 0)])
        self.assertEqual(input_tree_flattened_as_shallow_tree, [("a", 1),
                                                                ("b", 2),
                                                                ("c", 3),
                                                                ("d", 4)])

        self.assertEqual(input_tree_flattened_paths, [(0, 0, 0), (0, 0, 1),
                                                      (0, 1, 0, 0),
                                                      (0, 1, 0, 1),
                                                      (0, 1, 1, 0, 0),
                                                      (0, 1, 1, 0, 1),
                                                      (0, 1, 1, 1, 0, 0),
                                                      (0, 1, 1, 1, 0, 1)])
        self.assertEqual(input_tree_flattened,
                         ["a", 1, "b", 2, "c", 3, "d", 4])

        # Make sure dicts are correctly flattened, yielding values, not keys.
        input_tree = {"a": 1, "b": {"c": 2}, "d": [3, (4, 5)]}
        shallow_tree = {"a": 0, "b": 0, "d": [0, 0]}
        (input_tree_flattened_as_shallow_tree_paths,
         input_tree_flattened_as_shallow_tree) = get_paths_and_values(
             shallow_tree, input_tree)
        self.assertEqual(input_tree_flattened_as_shallow_tree_paths,
                         [("a", ), ("b", ), ("d", 0), ("d", 1)])
        self.assertEqual(input_tree_flattened_as_shallow_tree,
                         [1, {
                             "c": 2
                         }, 3, (4, 5)])

        # Namedtuples.
        ab_tuple = collections.namedtuple("ab_tuple", "a, b")
        input_tree = ab_tuple(a=[0, 1], b=2)
        shallow_tree = ab_tuple(a=0, b=1)
        (input_tree_flattened_as_shallow_tree_paths,
         input_tree_flattened_as_shallow_tree) = get_paths_and_values(
             shallow_tree, input_tree)
        self.assertEqual(input_tree_flattened_as_shallow_tree_paths, [("a", ),
                                                                      ("b", )])
        self.assertEqual(input_tree_flattened_as_shallow_tree, [[0, 1], 2])

        # Nested dicts, OrderedDicts and namedtuples.
        input_tree = collections.OrderedDict([
            ("a", ab_tuple(a=[0, {
                "b": 1
            }], b=2)), ("c", {
                "d": 3,
                "e": collections.OrderedDict([("f", 4)])
            })
        ])
        shallow_tree = input_tree
        (input_tree_flattened_as_shallow_tree_paths,
         input_tree_flattened_as_shallow_tree) = get_paths_and_values(
             shallow_tree, input_tree)
        self.assertEqual(input_tree_flattened_as_shallow_tree_paths,
                         [("a", "a", 0), ("a", "a", 1, "b"), ("a", "b"),
                          ("c", "d"), ("c", "e", "f")])
        self.assertEqual(input_tree_flattened_as_shallow_tree, [0, 1, 2, 3, 4])
        shallow_tree = collections.OrderedDict([("a", 0),
                                                ("c", {
                                                    "d": 3,
                                                    "e": 1
                                                })])
        (input_tree_flattened_as_shallow_tree_paths,
         input_tree_flattened_as_shallow_tree) = get_paths_and_values(
             shallow_tree, input_tree)
        self.assertEqual(input_tree_flattened_as_shallow_tree_paths,
                         [("a", ), ("c", "d"), ("c", "e")])
        self.assertEqual(input_tree_flattened_as_shallow_tree, [
            ab_tuple(a=[0, {
                "b": 1
            }], b=2), 3,
            collections.OrderedDict([("f", 4)])
        ])
        shallow_tree = collections.OrderedDict([("a", 0), ("c", 0)])
        (input_tree_flattened_as_shallow_tree_paths,
         input_tree_flattened_as_shallow_tree) = get_paths_and_values(
             shallow_tree, input_tree)
        self.assertEqual(input_tree_flattened_as_shallow_tree_paths, [("a", ),
                                                                      ("c", )])
        self.assertEqual(input_tree_flattened_as_shallow_tree, [
            ab_tuple(a=[0, {
                "b": 1
            }], b=2), {
                "d": 3,
                "e": collections.OrderedDict([("f", 4)])
            }
        ])

        ## Shallow non-list edge-case.
        # Using iterable elements.
        input_tree = ["input_tree"]
        shallow_tree = "shallow_tree"
        (flattened_input_tree_paths,
         flattened_input_tree) = get_paths_and_values(shallow_tree, input_tree)
        (flattened_shallow_tree_paths,
         flattened_shallow_tree) = get_paths_and_values(
             shallow_tree, shallow_tree)
        self.assertEqual(flattened_input_tree_paths, [()])
        self.assertEqual(flattened_input_tree, [input_tree])
        self.assertEqual(flattened_shallow_tree_paths, [()])
        self.assertEqual(flattened_shallow_tree, [shallow_tree])

        input_tree = ["input_tree_0", "input_tree_1"]
        shallow_tree = "shallow_tree"
        (flattened_input_tree_paths,
         flattened_input_tree) = get_paths_and_values(shallow_tree, input_tree)
        (flattened_shallow_tree_paths,
         flattened_shallow_tree) = get_paths_and_values(
             shallow_tree, shallow_tree)
        self.assertEqual(flattened_input_tree_paths, [()])
        self.assertEqual(flattened_input_tree, [input_tree])
        self.assertEqual(flattened_shallow_tree_paths, [()])
        self.assertEqual(flattened_shallow_tree, [shallow_tree])

        # Test case where len(shallow_tree) < len(input_tree)
        input_tree = {"a": "A", "b": "B", "c": "C"}
        shallow_tree = {"a": 1, "c": 2}

        with self.assertRaisesWithLiteralMatch(  # pylint: disable=g-error-prone-assert-raises
                ValueError,
                tree._STRUCTURES_HAVE_MISMATCHING_LENGTHS.format(
                    input_length=len(input_tree),
                    shallow_length=len(shallow_tree))):
            get_paths_and_values(shallow_tree, input_tree)

        # Using non-iterable elements.
        input_tree = [0]
        shallow_tree = 9
        (flattened_input_tree_paths,
         flattened_input_tree) = get_paths_and_values(shallow_tree, input_tree)
        (flattened_shallow_tree_paths,
         flattened_shallow_tree) = get_paths_and_values(
             shallow_tree, shallow_tree)
        self.assertEqual(flattened_input_tree_paths, [()])
        self.assertEqual(flattened_input_tree, [input_tree])
        self.assertEqual(flattened_shallow_tree_paths, [()])
        self.assertEqual(flattened_shallow_tree, [shallow_tree])

        input_tree = [0, 1]
        shallow_tree = 9
        (flattened_input_tree_paths,
         flattened_input_tree) = get_paths_and_values(shallow_tree, input_tree)
        (flattened_shallow_tree_paths,
         flattened_shallow_tree) = get_paths_and_values(
             shallow_tree, shallow_tree)
        self.assertEqual(flattened_input_tree_paths, [()])
        self.assertEqual(flattened_input_tree, [input_tree])
        self.assertEqual(flattened_shallow_tree_paths, [()])
        self.assertEqual(flattened_shallow_tree, [shallow_tree])

        ## Both non-list edge-case.
        # Using iterable elements.
        input_tree = "input_tree"
        shallow_tree = "shallow_tree"
        (flattened_input_tree_paths,
         flattened_input_tree) = get_paths_and_values(shallow_tree, input_tree)
        (flattened_shallow_tree_paths,
         flattened_shallow_tree) = get_paths_and_values(
             shallow_tree, shallow_tree)
        self.assertEqual(flattened_input_tree_paths, [()])
        self.assertEqual(flattened_input_tree, [input_tree])
        self.assertEqual(flattened_shallow_tree_paths, [()])
        self.assertEqual(flattened_shallow_tree, [shallow_tree])

        # Using non-iterable elements.
        input_tree = 0
        shallow_tree = 0
        (flattened_input_tree_paths,
         flattened_input_tree) = get_paths_and_values(shallow_tree, input_tree)
        (flattened_shallow_tree_paths,
         flattened_shallow_tree) = get_paths_and_values(
             shallow_tree, shallow_tree)
        self.assertEqual(flattened_input_tree_paths, [()])
        self.assertEqual(flattened_input_tree, [input_tree])
        self.assertEqual(flattened_shallow_tree_paths, [()])
        self.assertEqual(flattened_shallow_tree, [shallow_tree])

        ## Input non-list edge-case.
        # Using iterable elements.
        input_tree = "input_tree"
        shallow_tree = ["shallow_tree"]
        with self.assertRaisesWithLiteralMatch(
                TypeError,
                tree._IF_SHALLOW_IS_SEQ_INPUT_MUST_BE_SEQ.format(
                    type(input_tree))):
            (flattened_input_tree_paths,
             flattened_input_tree) = get_paths_and_values(
                 shallow_tree, input_tree)
        (flattened_shallow_tree_paths,
         flattened_shallow_tree) = get_paths_and_values(
             shallow_tree, shallow_tree)
        self.assertEqual(flattened_shallow_tree_paths, [(0, )])
        self.assertEqual(flattened_shallow_tree, shallow_tree)

        input_tree = "input_tree"
        shallow_tree = ["shallow_tree_9", "shallow_tree_8"]
        with self.assertRaisesWithLiteralMatch(
                TypeError,
                tree._IF_SHALLOW_IS_SEQ_INPUT_MUST_BE_SEQ.format(
                    type(input_tree))):
            (flattened_input_tree_paths,
             flattened_input_tree) = get_paths_and_values(
                 shallow_tree, input_tree)
        (flattened_shallow_tree_paths,
         flattened_shallow_tree) = get_paths_and_values(
             shallow_tree, shallow_tree)
        self.assertEqual(flattened_shallow_tree_paths, [(0, ), (1, )])
        self.assertEqual(flattened_shallow_tree, shallow_tree)

        # Using non-iterable elements.
        input_tree = 0
        shallow_tree = [9]
        with self.assertRaisesWithLiteralMatch(
                TypeError,
                tree._IF_SHALLOW_IS_SEQ_INPUT_MUST_BE_SEQ.format(
                    type(input_tree))):
            (flattened_input_tree_paths,
             flattened_input_tree) = get_paths_and_values(
                 shallow_tree, input_tree)
        (flattened_shallow_tree_paths,
         flattened_shallow_tree) = get_paths_and_values(
             shallow_tree, shallow_tree)
        self.assertEqual(flattened_shallow_tree_paths, [(0, )])
        self.assertEqual(flattened_shallow_tree, shallow_tree)

        input_tree = 0
        shallow_tree = [9, 8]
        with self.assertRaisesWithLiteralMatch(
                TypeError,
                tree._IF_SHALLOW_IS_SEQ_INPUT_MUST_BE_SEQ.format(
                    type(input_tree))):
            (flattened_input_tree_paths,
             flattened_input_tree) = get_paths_and_values(
                 shallow_tree, input_tree)
        (flattened_shallow_tree_paths,
         flattened_shallow_tree) = get_paths_and_values(
             shallow_tree, shallow_tree)
        self.assertEqual(flattened_shallow_tree_paths, [(0, ), (1, )])
        self.assertEqual(flattened_shallow_tree, shallow_tree)

    def testMapStructureUpTo(self):
        # Named tuples.
        ab_tuple = collections.namedtuple("ab_tuple", "a, b")
        op_tuple = collections.namedtuple("op_tuple", "add, mul")
        inp_val = ab_tuple(a=2, b=3)
        inp_ops = ab_tuple(a=op_tuple(add=1, mul=2), b=op_tuple(add=2, mul=3))
        out = tree.map_structure_up_to(inp_val,
                                       lambda val, ops:
                                       (val + ops.add) * ops.mul,
                                       inp_val,
                                       inp_ops,
                                       check_types=False)
        self.assertEqual(out.a, 6)
        self.assertEqual(out.b, 15)

        # Lists.
        data_list = [[2, 4, 6, 8], [[1, 3, 5, 7, 9], [3, 5, 7]]]
        name_list = ["evens", ["odds", "primes"]]
        out = tree.map_structure_up_to(
            name_list, lambda name, sec: "first_{}_{}".format(len(sec), name),
            name_list, data_list)
        self.assertEqual(out,
                         ["first_4_evens", ["first_5_odds", "first_3_primes"]])

    # We cannot define namedtuples within @parameterized argument lists.
    # pylint: disable=invalid-name
    Foo = collections.namedtuple("Foo", ["a", "b"])
    Bar = collections.namedtuple("Bar", ["c", "d"])
    # pylint: enable=invalid-name

    @parameterized.parameters([
        dict(inputs=[], expected=[]),
        dict(inputs=[23, "42"], expected=[((0, ), 23), ((1, ), "42")]),
        dict(inputs=[[[[108]]]], expected=[((0, 0, 0, 0), 108)]),
        dict(inputs=Foo(a=3, b=Bar(c=23, d=42)),
             expected=[(("a", ), 3), (("b", "c"), 23), (("b", "d"), 42)]),
        dict(inputs=Foo(a=Bar(c=23, d=42), b=Bar(c=0, d="thing")),
             expected=[(("a", "c"), 23), (("a", "d"), 42), (("b", "c"), 0),
                       (("b", "d"), "thing")]),
        dict(inputs=Bar(c=42, d=43), expected=[(("c", ), 42), (("d", ), 43)]),
        dict(inputs=Bar(c=[42], d=43),
             expected=[(("c", 0), 42), (("d", ), 43)]),
        dict(inputs=wrapt.ObjectProxy(Bar(c=[42], d=43)),
             expected=[(("c", 0), 42), (("d", ), 43)]),
    ])
    def testFlattenWithPath(self, inputs, expected):
        self.assertEqual(tree.flatten_with_path(inputs), expected)

    @parameterized.named_parameters([
        dict(testcase_name="Tuples",
             s1=(1, 2),
             s2=(3, 4),
             check_types=True,
             expected=(((0, ), 4), ((1, ), 6))),
        dict(testcase_name="Dicts",
             s1={
                 "a": 1,
                 "b": 2
             },
             s2={
                 "b": 4,
                 "a": 3
             },
             check_types=True,
             expected={
                 "a": (("a", ), 4),
                 "b": (("b", ), 6)
             }),
        dict(testcase_name="Mixed",
             s1=(1, 2),
             s2=[3, 4],
             check_types=False,
             expected=(((0, ), 4), ((1, ), 6))),
        dict(testcase_name="Nested",
             s1={
                 "a": [2, 3],
                 "b": [1, 2, 3]
             },
             s2={
                 "b": [5, 6, 7],
                 "a": [8, 9]
             },
             check_types=True,
             expected={
                 "a": [(("a", 0), 10), (("a", 1), 12)],
                 "b": [(("b", 0), 6), (("b", 1), 8), (("b", 2), 10)]
             }),
    ])
    def testMapWithPathCompatibleStructures(self, s1, s2, check_types,
                                            expected):
        def path_and_sum(path, *values):
            return path, sum(values)

        result = tree.map_structure_with_path(path_and_sum,
                                              s1,
                                              s2,
                                              check_types=check_types)
        self.assertEqual(expected, result)

    @parameterized.named_parameters([
        dict(testcase_name="Tuples",
             s1=(1, 2, 3),
             s2=(4, 5),
             error_type=ValueError),
        dict(testcase_name="Dicts",
             s1={"a": 1},
             s2={"b": 2},
             error_type=ValueError),
        dict(testcase_name="Mixed", s1=(1, 2), s2=[3, 4],
             error_type=TypeError),
        dict(testcase_name="Nested",
             s1={
                 "a": [2, 3, 4],
                 "b": [1, 3]
             },
             s2={
                 "b": [5, 6],
                 "a": [8, 9]
             },
             error_type=ValueError)
    ])
    def testMapWithPathIncompatibleStructures(self, s1, s2, error_type):
        with self.assertRaises(error_type):
            tree.map_structure_with_path(lambda path, *s: 0, s1, s2)

    def testMappingProxyType(self):
        if six.PY2:
            self.skipTest("Python 2 does not support mapping proxy type.")

        structure = types.MappingProxyType({"a": 1, "b": (2, 3)})
        expected = types.MappingProxyType({"a": 4, "b": (5, 6)})
        self.assertEqual(tree.flatten(structure), [1, 2, 3])
        self.assertEqual(tree.unflatten_as(structure, [4, 5, 6]), expected)
        self.assertEqual(tree.map_structure(lambda v: v + 3, structure),
                         expected)

    def testTraverseListsToTuples(self):
        structure = [(1, 2), [3], {"a": [4]}]
        self.assertEqual(((1, 2), (3, ), {
            "a": (4, )
        }),
                         tree.traverse(lambda x: tuple(x)
                                       if isinstance(x, list) else x,
                                       structure,
                                       top_down=False))

    def testTraverseEarlyTermination(self):
        structure = [(1, [2]), [3, (4, 5, 6)]]
        visited = []

        def visit(x):
            visited.append(x)
            return "X" if isinstance(x, tuple) and len(x) > 2 else None

        output = tree.traverse(visit, structure)
        self.assertEqual([(1, [2]), [3, "X"]], output)
        self.assertEqual([[(1, [2]), [3, (4, 5, 6)]],
                          (1, [2]), 1, [2], 2, [3, (4, 5, 6)], 3, (4, 5, 6)],
                         visited)
Ejemplo n.º 14
0
    def test_complex(self):
        instance = 1.0 + 2j

        proxy = wrapt.ObjectProxy(instance)

        self.assertEqual(complex(instance), complex(proxy))
Ejemplo n.º 15
0
    def test_setitem(self):
        value = wrapt.ObjectProxy(list(range(3)))
        value[1] = -1

        self.assertEqual(value[1], -1)
Ejemplo n.º 16
0
    def test_abs(self):
        value = wrapt.ObjectProxy(-1)

        self.assertEqual(abs(value), 1)
Ejemplo n.º 17
0
    def test_getslice(self):
        value = wrapt.ObjectProxy(list(range(5)))

        self.assertEqual(value[1:4], [1, 2, 3])
Ejemplo n.º 18
0
    def test_invert(self):
        value = wrapt.ObjectProxy(1)

        self.assertEqual(~value, ~1)
Ejemplo n.º 19
0
    def test_length(self):
        value = wrapt.ObjectProxy(dict.fromkeys(range(3), False))

        self.assertEqual(len(value), 3)
Ejemplo n.º 20
0
    def test_oct(self):
        value = wrapt.ObjectProxy(20)

        self.assertEqual(oct(value), oct(20))
Ejemplo n.º 21
0
    def test_setitem(self):
        value = wrapt.ObjectProxy(dict.fromkeys(range(3), False))
        value[1] = True

        self.assertEqual(value[1], True)
Ejemplo n.º 22
0
    def test_hex(self):
        value = wrapt.ObjectProxy(20)

        self.assertEqual(hex(value), hex(20))
Ejemplo n.º 23
0
    def test_proxy_hasattr_call(self):
        proxy = wrapt.ObjectProxy(None)

        self.assertFalse(hasattr(proxy, '__call__'))
Ejemplo n.º 24
0
    def test_length(self):
        value = wrapt.ObjectProxy(list(range(3)))

        self.assertEqual(len(value), 3)
Ejemplo n.º 25
0
    def test_proxy_is_callable(self):
        proxy = wrapt.ObjectProxy(None)

        self.assertFalse(callable(proxy))
Ejemplo n.º 26
0
    def test_contains(self):
        value = wrapt.ObjectProxy(list(range(3)))

        self.assertTrue(2 in value)
        self.assertFalse(-2 in value)
Ejemplo n.º 27
0
    def test_list_reversed(self):
        instance = [1, 2]

        proxy = wrapt.ObjectProxy(instance)

        self.assertEqual(list(reversed(instance)), list(reversed(proxy)))
Ejemplo n.º 28
0
    def test_getitem(self):
        value = wrapt.ObjectProxy(list(range(3)))

        self.assertEqual(value[1], 1)
Ejemplo n.º 29
0
 def testObjectProxy(self):
     nt_type = collections.namedtuple("A", ["x", "y"])
     proxied = wrapt.ObjectProxy(nt_type(1, 2))
     proxied_spec = structure.type_spec_from_value(proxied)
     self.assertEqual(structure.type_spec_from_value(nt_type(1, 2)),
                      proxied_spec)
Ejemplo n.º 30
0
            self._handlers[scheme] = translator
            logger.debug(f"Registered path handler for scheme {scheme}")
            return translator

        return decorator

    def __enter__(self):
        self._previous_path_managers.append(PathManager.__wrapped__)
        PathManager.__wrapped__ = self

    def __exit__(self, exc_type, exc_val, exc_tb):
        PathManager.__wrapped__ = self._previous_path_managers.pop()


#: The public path manager instance.
PathManager: PathManagerBase = wrapt.ObjectProxy(PathManagerBase())


class URI(_URIBase):
    """A class representing a recap URI that is lazily evaluated to a local path when it is used.

    It is fully compatible with :class:`pathlib.Path`.
    """
    def _init(self, *args, **kwargs):
        self._local_path = PathManager.resolve(self)
        super()._init()

    def __str__(self) -> str:
        return str(self._local_path)

    def is_absolute(self) -> bool: