def test_schema_attrs(): obj = SchemaTest([1, 2.3], [1, [2.3]], 5) obj2 = SchemaTest([1, 2.3], [1, [2.4]], 5) assert is_hashable(hashable(obj)) assert find_ne(obj, obj) is None assert find_ne(obj, obj2) == DiffersAtAttribute(obj, obj2, 'b') e1 = eval(estr(obj)) assert_equivalent(e1, obj) assert list(visit(obj)) == [('a', [1, 2.3]), ('b', [1, [2.3]]), ('c', 5)] assert rstr(obj) == "SchemaTest(a = [1, 2.3], b = [1, [2.3]], c = 5)" sval = deserialize(serialize(obj)) assert_equivalent(sval, obj) assert deep_feq(sval, obj) val = generate(SchemaTest) assert type(val) is SchemaTest assert_raises(TypeError, SchemaTest, [1], [2.3], 5) assert_raises(TypeError, SchemaTest, [11, 2.3], [1, [2.3]], 5) assert_raises(TypeError, SchemaTest, [1, 2.3], [1, [2.3]], 9)
def test_dependency(): assert depd.DEPENDENCY_KEYS == dict(apt = Apt, pip = Pip, yatr = Yatr) assert depd.DEPENDENCY_ORDERS == dict(apt = Apt.order, pip = Pip.order, yatr = Yatr.order) dep = Dependency('foo') assert dep.name == 'foo' assert not dep.installed() assert not dep.check() assert_raises(NotImplementedError, dep.satisfy) assert_equivalent(Dependency.from_conf('foo'), dep) assert_raises(TypeError, Dependency.from_conf, []) assert_raises(TypeError, Dependency.from_conf, dict(a = 1, b = 2)) class Foo(Dependency): _attrs = dict(a = Attr(int), b = Attr(int)) assert_equivalent(Foo.from_conf(dict(foo = dict(a = 1, b = 2))), Foo('foo', a = 1, b = 2)) f = Foo('bar', a = 1, b = 2, order=5) assert is_hashable(f)
def test_sequence_conversion(): seq = [1, 2.3, 'abc'] seq2 = seq + ['def'] assert ConvTest._dict_from_sequence(seq) == dict(a = 1, b = 2.3, c = 'abc') ct1 = ConvTest(1, 2.3, 'abc') assert_equivalent(ConvTest.from_sequence(seq), ct1) assert_raises(ValueError, ConvTest.from_sequence, seq2)
def test_sequence_conversion(): seq = [1, 2.3, 'abc'] seq2 = seq + ['def'] assert ConvTest._dict_from_sequence(seq) == dict(a=1, b=2.3, c='abc') ct1 = ConvTest(1, 2.3, 'abc') assert_equivalent(ConvTest.from_sequence(seq), ct1) assert_raises(ValueError, ConvTest.from_sequence, seq2)
def test_base_str(): obj = StrTest(a=[1, 2], b=1.2, c='abc') assert str(obj) == "StrTest(a = [1, 2], c = 'abc')" pretty_str = '''StrTest(a = [1, 2], c = 'abc')''' assert obj.pretty() == pretty_str assert_equivalent(eval(obj.pretty()), obj)
def test_base_str(): obj = StrTest(a = [1, 2], b = 1.2, c = 'abc') assert str(obj) == "StrTest(a = [1, 2], c = 'abc')" pretty_str = '''StrTest(a = [1, 2], c = 'abc')''' assert obj.pretty() == pretty_str assert_equivalent(eval(obj.pretty()), obj)
def test_sequence(): l = [1, 2.3, 'abc'] t = Type.dispatch(l) assert isinstance(t, Sequence) assert type(t) is List if PY2: assert set(hashable(l)) == set(t.hashable()) == \ {'__builtin__.list', 1, 2.3, 'abc'} else: assert set(hashable(l)) == set(t.hashable()) == \ {'builtins.list', 1, 2.3, 'abc'} assert not is_hashable(l) assert is_hashable(hashable(l)) l1 = [1, 2, 3] l2 = [1, 2, 3, 4] l3 = [1, 2, 4] assert find_ne(l1, l2) == DifferentLength(l1, l2) assert find_ne(l2, l1) == DifferentLength(l2, l1) assert find_ne(l1, l3) == DiffersAtIndex(l1, l3, 2) e1 = eval(estr(l1)) assert_equivalent(e1, l1) tup = tuple(l) examine_sequence(List, l) examine_sequence(Tuple, tup) examine_sequence(Tuple, ([ -1839677305294322342, b'', b'\x05l\xbf', b'0\xcfXp\xaa', -8468204163727415930 ], True)) for cls in subclasses(Sequence): for k in xrange(SAMPLES): val = cls.generate() with on_error(elog, examine_sequence, (cls, val)): hangwatch(1, examine_sequence, cls, val) buf = [] last = None for item in enumerate_(cls.type, max_enum=SAMPLES * 10, step=100): assert type(item) is cls.type assert item != last buf.append(item) last = item assert is_unique(buf) assert list(visit(l, enumerate=True)) == [(0, 1), (1, 2.3), (2, 'abc')] assert list(visit([])) == [] l = [1, 2, (3, 4)] assert primitive_form(l) == [1, 2, [3, 4]] assert collect(l) == primitive_form(l)
def test_vars(): a, b = vars('a', 'b') assert_equivalent(a, Variable('a')) assert_equivalent(b, Variable('b')) c = vars('c') assert_equivalent(c, Variable('c')) d, e = vars('d e') assert_equivalent(d, Variable('d')) assert_equivalent(e, Variable('e'))
def test_assert_equivalent(): from syn.base_utils import assert_equivalent e1 = EquivObj(1) e2 = EquivObj(1) e3 = EquivObj(2) assert_equivalent(e1, e2) assert_raises(AssertionError, assert_equivalent, e1, e3) assert_raises(AssertionError, assert_equivalent, e2, e3) assert_raises(AssertionError, assert_equivalent, e1, e1)
def test_sequence(): l = [1, 2.3, 'abc'] t = Type.dispatch(l) assert isinstance(t, Sequence) assert type(t) is List if PY2: assert set(hashable(l)) == set(t.hashable()) == \ {'__builtin__.list', 1, 2.3, 'abc'} else: assert set(hashable(l)) == set(t.hashable()) == \ {'builtins.list', 1, 2.3, 'abc'} assert not is_hashable(l) assert is_hashable(hashable(l)) l1 = [1, 2, 3] l2 = [1, 2, 3, 4] l3 = [1, 2, 4] assert find_ne(l1, l2) == DifferentLength(l1, l2) assert find_ne(l2, l1) == DifferentLength(l2, l1) assert find_ne(l1, l3) == DiffersAtIndex(l1, l3, 2) e1 = eval(estr(l1)) assert_equivalent(e1, l1) tup = tuple(l) examine_sequence(List, l) examine_sequence(Tuple, tup) examine_sequence(Tuple, ([-1839677305294322342, b'', b'\x05l\xbf', b'0\xcfXp\xaa', -8468204163727415930], True)) for cls in subclasses(Sequence): for k in xrange(SAMPLES): val = cls.generate() with on_error(elog, examine_sequence, (cls, val)): hangwatch(1, examine_sequence, cls, val) buf = [] last = None for item in enumerate_(cls.type, max_enum=SAMPLES * 10, step=100): assert type(item) is cls.type assert item != last buf.append(item) last = item assert is_unique(buf) assert list(visit(l, enumerate=True)) == [(0, 1), (1, 2.3), (2, 'abc')] assert list(visit([])) == [] l = [1, 2, (3, 4)] assert primitive_form(l) == [1, 2, [3, 4]] assert collect(l) == primitive_form(l)
def test_object_conversion(): class Foo(object): pass obj = Foo() obj.a = 1 obj.b = 2.3 obj.c = 'abc' obj.d = 'def' ct1 = ConvTest(1, 2.3, 'abc') ct2 = ConvTest.from_object(obj) assert_equivalent(ct2, ct1) assert not hasattr(ct2, 'd')
def test_normal_type(): b = Bar(1, 2.3) b2 = Bar(1, 2.4) b3 = Bar(2, 2.3) assert b != b2 assert_equivalent(Bar(1, 2.3), Bar(1, 2.3)) if PY3: assert not is_hashable(b) else: assert is_hashable(b) assert is_hashable(hashable(b)) assert find_ne(b, b) is None assert find_ne(b, b2) == DiffersAtAttribute(b, b2, 'b') assert find_ne(b, b3) == DiffersAtAttribute(b, b3, 'a') # Is evaluable, but not correct, because we haven't given the # types system the proper information for this class e1 = eval(estr(b)) assert b != e1 assert list(visit(b)) == [('a', 1), ('b', 2.3)] assert attrs(b) == ['a', 'b'] assert rstr(b).startswith('<{} object at '.format(get_fullname(Bar))) sval = deserialize(serialize(b)) assert_equivalent(b, sval) assert deep_feq(b, sval) assert primitive_form(Bar) is Bar assert primitive_form(b) == dict(a=1, b=2.3) b4 = Bar(2, b2) assert primitive_form(b4) == dict(a=2, b=dict(a=1, b=2.4)) assert collect(b4) == primitive_form(b4) def dothing(obj): if isinstance(obj, collections.Mapping): return safe_sorted(obj.values()) return safe_sorted(obj) assert collect(b4, dothing) in [[2, [1, 2.4]], [2, [2.4, 1]], [[1, 2.4], 2], [[2.4, 1], 2]] # Because the types system knows nothing of the Bar class assert_raises(NotImplementedError, generate, Bar) assert_raises(NotImplementedError, list, enum(Bar, max_enum=50))
def test_misc_serialization(): assert int is deserialize(serialize(int)) d = dict(a=1, b=2) dd = deserialize(d) assert_equivalent(d, dd) k = KWObject(a=1, b=2.3) assert k != KWObject(a=2, b=2.3) assert_equivalent(KWObject(a=1, b=2.3), KWObject(b=2.3, a=1)) sval = deserialize(serialize(k)) assert_equivalent(sval, k) assert deep_feq(sval, k) assert KWObject is deserialize(serialize(KWObject)) f = Foo2(1, b=2.3, c='abc') f2 = Foo2(1, b=2.4, c='abc') assert f != f2 sval = deserialize(serialize(f)) assert_equivalent(sval, f) assert deep_feq(sval, f) assert Foo2 is deserialize(serialize(Foo2)) n = NoSer() n.a = 1 sval = deserialize(serialize(n)) assert isinstance(sval, NoSer) assert n != sval assert vars(n) != vars(sval) assert n.a == 1 assert not hasattr(sval, 'a')
def test_syn_types_functionality(): s = SynTypesTest(a=1, b=1.2, c='abc') s2 = SynTypesTest(a=1, b=1.2, c='abcd') assert not is_hashable(s) assert is_hashable(hashable(s)) assert find_ne(s, s) is None assert find_ne(s, s2) == DiffersAtAttribute(s, s2, 'c') e1 = eval(estr(s)) assert_equivalent(e1, s) assert list(visit(s)) == [('a', 1), ('b', 1.2), ('c', 'abc')] assert rstr(s) == "SynTypesTest(a = 1, b = 1.2, c = 'abc')" assert attrs(s) == ['a', 'b', 'c'] assert pairs(s) == [('a', 1), ('b', 1.2), ('c', 'abc')] sval = deserialize(serialize(s)) assert_equivalent(sval, s) assert deep_feq(sval, s) assert primitive_form(s) == dict(a=1, b=1.2, c='abc') assert primitive_form(SynTypesTest) is SynTypesTest assert SynTypesTest is deserialize(serialize(SynTypesTest)) val = generate(SynTypesTest) assert type(val) is SynTypesTest buf = [] last = None for item in enum(SynTypesTest, max_enum=SAMPLES * 10, step=100): assert type(item) is SynTypesTest assert item != last buf.append(item) last = item assert enumeration_value(SynTypesTest, 0) == \ first(enum(SynTypesTest, max_enum=1)) assert is_unique(buf) val = generate(SynTypesTest2) assert type(val) is not SynTypesTest2 assert type(val) is SynTypesTest item = first(enum(SynTypesTest3, max_enum=1)) assert type(item) is SynTypesTest3 assert not hasattr(item, 'd')
def test_copy(): c = CopyTest(1, 1.2, 'abc') assert_equivalent(c, c.copy()) c2 = CopyTest2(1, 2.3, 'abc', d=[1, 2], e=[3, 4]) c2c = c2.copy() assert_equivalent(c2.d, c2c.d) assert c2.e == [3, 4] assert not hasattr(c2c, 'e') c3 = CopyTest3(1, 2.3, 'abc', d=[1, 2], e=[3, 4], f=5) c3c = copy(c3) assert c3c.to_dict() == dict(a=1, b=2.3, c='abc', d=[1, 2], f=5) assert c3.copy(exclude=['eq_exclude']).to_dict() == \ dict(a=1, b=2.3, c='abc', d=[1,2])
def test_copy(): c = CopyTest(1, 1.2, 'abc') assert_equivalent(c, c.copy()) c2 = CopyTest2(1, 2.3, 'abc', d=[1, 2], e=[3, 4]) c2c = c2.copy() assert_equivalent(c2.d, c2c.d) assert c2.e == [3, 4] assert not hasattr(c2c, 'e') c3 = CopyTest3(1, 2.3, 'abc', d=[1, 2], e=[3, 4], f=5) c3c = copy(c3) assert c3c.to_dict() == dict(a=1, b=2.3, c='abc', d=[1,2], f=5) assert c3.copy(exclude=['eq_exclude']).to_dict() == \ dict(a=1, b=2.3, c='abc', d=[1,2])
def test_assert_type_equivalent(): from syn.base_utils import assert_type_equivalent, assert_equivalent from syn.base_utils.dict import AttrDict e1 = EquivObj(1) e2 = EquivObj(1) e3 = EquivObj2(1) assert_type_equivalent(e1, e2) assert_equivalent(e1, e3) assert_raises(AssertionError, assert_type_equivalent, e1, e3) d1 = dict(a = 1, b = 2) d2 = AttrDict(a = 1, b = 2) assert_equivalent(d1, d2) assert_raises(AssertionError, assert_type_equivalent, d1, d2)
def test_assert_type_equivalent(): from syn.base_utils import assert_type_equivalent, assert_equivalent from syn.base_utils.dict import AttrDict e1 = EquivObj(1) e2 = EquivObj(1) e3 = EquivObj2(1) assert_type_equivalent(e1, e2) assert_equivalent(e1, e3) assert_raises(AssertionError, assert_type_equivalent, e1, e3) d1 = dict(a=1, b=2) d2 = AttrDict(a=1, b=2) assert_equivalent(d1, d2) assert_raises(AssertionError, assert_type_equivalent, d1, d2)
def test_mapping(): d = dict(a = 1, b = 2.3) t = Type.dispatch(d) assert isinstance(t, Mapping) assert type(t) is Dict if PY2: assert set(hashable(d)) == set(t.hashable()) == \ {'__builtin__.dict', ('a', 1), ('b', 2.3)} else: assert set(hashable(d)) == set(t.hashable()) == \ {'builtins.dict', ('a', 1), ('b', 2.3)} d1 = dict(a=1, b=2) d2 = dict(a=1, b=2, c=3) d3 = dict(a=1, b=3) assert find_ne(d1, d2) == KeyDifferences(d1, d2) assert find_ne(d2, d1) == KeyDifferences(d2, d1) assert find_ne(d1, d3) == DiffersAtKey(d1, d3, 'b') e1 = eval(estr(d1)) assert_equivalent(e1, d1) assert not is_hashable(d) assert is_hashable(hashable(d)) examine_mapping(Dict, d) for cls in subclasses(Mapping): for k in xrange(SAMPLES): val = cls.generate() with on_error(elog, examine_mapping, (cls, val)): hangwatch(1, examine_mapping, cls, val) buf = [] last = None for item in enumerate_(cls.type, max_enum=SAMPLES * 10, step=100): assert type(item) is cls.type assert item != last buf.append(item) last = item assert is_unique(buf) d = dict(a=1, b=[1, 2, (3, 4)]) assert primitive_form(d) == dict(a=1, b=[1, 2, [3, 4]]) assert collect(d) == primitive_form(d)
def test_env(): Updateable()._update_pre({}) Updateable()._update_post({}) with assign(ye, 'INITIAL_MACROS', dict(a='1', b='2')): e = Env() assert e.macros assert e.contexts assert e.default_context assert not e.tasks assert not e.secret_values e1 = Env(macros=dict(a='b', b='{{a}}c', c='d{{b}}')) e2 = Env(macros=dict(a='a', d='{{c}}e')) e3 = Env(macros=dict(a='{{d}}')) e1c = e1.copy() assert_equivalent(e1, e1c) assert_equivalent(e1.macros, e1c.macros) e0 = deepcopy(e1) e0.resolve_macros() assert e0.env == dict(a='b', b='bc', c='dbc') e1.update(e2) e1c = deepcopy(e1) e1.resolve_macros() assert e1.env == dict(a='a', b='ac', c='dac', d='dace') e2.macros['a'] = 'c' e1c.update(e2) e1c2 = deepcopy(e1c) e1c.resolve_macros() assert e1c.env == dict(a='c', b='cc', c='dcc', d='dcce') e1c2.update(e3) assert_raises(ValueError, e1c2.resolve_macros) e = Env(default_task='foo') e.update(Env()) assert e.default_task == 'foo' e.update(Env(default_task='bar')) assert e.default_task == 'bar'
def test_long(): if PY2: lst = list(enumerate_(long, max_enum=5)) assert lst == [0, 1, 2, 3, 4] x = long('1L') assert rstr(x) == '1' assert estr(x) == '1L' assert_equivalent(hashable(-x), -x) gen = generate(long) assert isinstance(gen, long) assert find_ne(gen, gen+1) == NotEqual(gen, gen+1) assert_type_equivalent(deserialize(serialize(x)), x) assert TYPE_REGISTRY[long] is Long assert Long in TYPE_REGISTRY.values() else: assert Long not in TYPE_REGISTRY.values()
def test_long(): if PY2: lst = list(enumerate_(long, max_enum=5)) assert lst == [0, 1, 2, 3, 4] x = long('1L') assert rstr(x) == '1' assert estr(x) == '1L' assert_equivalent(hashable(-x), -x) gen = generate(long) assert isinstance(gen, long) assert find_ne(gen, gen + 1) == NotEqual(gen, gen + 1) assert_type_equivalent(deserialize(serialize(x)), x) assert TYPE_REGISTRY[long] is Long assert Long in TYPE_REGISTRY.values() else: assert Long not in TYPE_REGISTRY.values()
def test_base(): kwargs = dict(a=5, b=3.4, c=u'abc') obj = A(**kwargs) assert obj.a == 5 assert obj.b == 3.4 assert obj.c == u'abc' assert obj.to_dict() == kwargs assert obj.to_dict(exclude=['a', 'b']) == dict(c=u'abc') assert obj != 5 assert_equivalent(obj, A(**kwargs)) assert_inequivalent(obj, A(a=6, b=3.4, c=u'abc')) assert A(a=5, b=3.4).to_dict() == dict(a=5, b=3.4) assert_deepcopy_idempotent(obj) assert_pickle_idempotent(obj) assert_raises(TypeError, A, a=5.1, b=3.4) assert_raises(AttributeError, A, a=5)
def test_set(): s = frozenset([1, 2.3, 'abc']) t = Type.dispatch(s) assert isinstance(t, Set) assert type(t) is FrozenSet assert hashable(s) == t.hashable() == s assert is_hashable(s) assert is_hashable(hashable(s)) s1 = {1, 2, 3} s2 = {2, 3, 4} assert find_ne(s1, s2) == SetDifferences(s1, s2) e1 = eval(estr(s1)) assert_equivalent(e1, s1) examine_set(Set, set(s)) examine_set(FrozenSet, s) for cls in subclasses(Set, [Set]): for k in xrange(SAMPLES): val = cls.generate() with on_error(elog, examine_set, (cls, val)): hangwatch(1, examine_set, cls, val) buf = [] last = None for item in enumerate_(cls.type, max_enum=SAMPLES * 10, step=100): assert type(item) is cls.type assert item != last buf.append(item) last = item assert is_unique(buf) s = {1, 2, (3, 4)} assert primitive_form(s) == [1, 2, [3, 4]] assert collect(s) == primitive_form(s)
def test_base(): kwargs = dict(a=5, b=3.4, c=u'abc') obj = A(**kwargs) assert obj.a == 5 assert obj.b == 3.4 assert obj.c == u'abc' assert obj.to_dict() == kwargs assert obj.to_tuple() == (5, 3.4, u'abc') assert not is_hashable(obj) assert obj != 5 assert_equivalent(obj, A(**kwargs)) assert_inequivalent(obj, A(a=6, b=3.4, c=u'abc')) assert A(a=5, b=3.4).to_dict() == dict(a=5, b=3.4) check_idempotence(obj) assert_raises(TypeError, A, a=5.1, b=3.4) assert_raises(AttributeError, A, a=5) assert_equivalent(A(**kwargs), A(**kwargs)) assert_inequivalent(A2(**kwargs), A2(**kwargs)) assert_raises(AssertionError, assert_pickle_idempotent, A2(**kwargs)) obj2 = A2(**kwargs) assert_type_equivalent(obj2.to_dict(), dict(a=5, b=3.4, c=u'abc')) assert obj2.to_dict(include=['getstate_exclude']) == dict(b=3.4) obj3 = A3(**kwargs) assert obj3.to_tuple() == (5, 3.4, u'abc') assert is_hashable(obj3) obj4 = A4(a=[1, 2, 3], b=3.4, c='abc') assert is_hashable(obj4)
def test_tree_node(): n = Node() assert n._children == [] assert n._parent is None assert n._id is None assert n._name is None assert bool(n) is True assert_equivalent(n, Node()) obj = Node(_id=4545, _name='foonode') assert obj._children == [] assert obj._parent is None assert obj._id == 4545 assert obj._name == 'foonode' assert list(obj.children()) == obj._children assert obj.parent() is obj._parent assert obj.id() is obj._id assert obj.name() is obj._name assert_inequivalent(obj, n) treenode_tst_1(Node) treenode_tst_2(Node) treenode_tst_3(Node)
def test_tree_node(): n = Node() assert n._children == [] assert n._parent is None assert n._id is None assert n._name is None assert bool(n) is True assert_equivalent(n, Node()) obj = Node(_id = 4545, _name = 'foonode') assert obj._children == [] assert obj._parent is None assert obj._id == 4545 assert obj._name == 'foonode' assert list(obj.children()) == obj._children assert obj.parent() is obj._parent assert obj.id() is obj._id assert obj.name() is obj._name assert_inequivalent(obj, n) treenode_tst_1(Node) treenode_tst_2(Node) treenode_tst_3(Node)
def test_custom_type(): b = Baz(1, 2.3) b2 = Baz(1, 2.4) b3 = Baz(2, 2.3) assert b != b2 assert_equivalent(Baz(1, 2.3), Baz(1, 2.3)) if PY3: assert not is_hashable(b) else: assert is_hashable(b) assert is_hashable(hashable(b)) assert find_ne(b, b) is None assert find_ne(b, b2) == DiffersAtAttribute(b, b2, 'b') assert find_ne(b, b3) == DiffersAtAttribute(b, b3, 'a') e1 = eval(estr(b)) assert_equivalent(e1, b) assert list(visit(b)) == [('a', 1), ('b', 2.3)] assert rstr(b) == 'Baz(1,2.3)' assert attrs(b) == ['a', 'b'] sval = deserialize(serialize(b)) assert_equivalent(sval, b) assert deep_feq(sval, b) assert Baz is deserialize(serialize(Baz)) assert primitive_form(Baz) is Baz assert primitive_form(b) == dict(a=1, b=2.3) val = generate(Baz) assert type(val) is Baz assert isinstance(val.a, int) assert isinstance(val.b, float) buf = [] last = None for item in enum(Baz, max_enum=SAMPLES * 10, step=100): assert type(item) is Baz assert item != last buf.append(item) last = item assert is_unique(buf)
def test_custom_object(): f = Foo(1, 1.2) f2 = Foo(1, 1.3) f3 = Foo(2, 1.2) assert f != f2 assert_equivalent(Foo(1, 2.3), Foo(1, 2.3)) assert not is_hashable(f) assert is_hashable(hashable(f)) assert find_ne(f, f) is None assert find_ne(f, f2) == DiffersAtAttribute(f, f2, 'b') assert find_ne(f, f3) == DiffersAtAttribute(f, f3, 'a') e1 = eval(estr(f)) assert_equivalent(e1, f) assert list(visit(f)) == [('a', 1), ('b', 1.2)] assert rstr(f) == 'Foo(1,1.2)' assert attrs(f) == ['a', 'b'] assert pairs(f) == [('a', 1), ('b', 1.2)] sval = deserialize(serialize(f)) assert_equivalent(sval, f) assert deep_feq(sval, f) assert Foo is deserialize(serialize(Foo)) assert primitive_form(Foo) is Foo assert primitive_form(f) == dict(a=1, b=1.2) assert collect(f) == primitive_form(f) val = generate(Foo) assert type(val) is Foo buf = [] last = None for item in enum(Foo, max_enum=SAMPLES * 10, step=100): assert type(item) is Foo assert item != last buf.append(item) last = item assert enumeration_value(Foo, 0) == first(enum(Foo, max_enum=1)) assert is_unique(buf)
def test_listwrapper(): obj = ListWrapper(1, 2, 3) check_idempotence(obj) objc = obj.copy() assert_equivalent(obj, objc) assert_equivalent(obj._list, objc._list) assert obj._list is not objc._list assert isinstance(obj, collections.MutableSequence) assert issubclass(ListWrapper, collections.MutableSequence) cobj = deepcopy(obj) _list = list(range(10)) cobj._list = list(_list) assert list(cobj) == _list cobj.append(11) assert list(cobj) == _list + [11] cobj.extend([12, 13]) assert list(cobj) == _list + [11, 12, 13] cobj.insert(0, 14) assert list(cobj) == [14] + _list + [11, 12, 13] cobj.pop() assert list(cobj) == [14] + _list + [11, 12] cobj.remove(12) assert list(cobj) == [14] + _list + [11] assert cobj.count(1) == 1 assert cobj.index(0) == 1 cobj.sort() assert list(cobj) == _list + [11, 14] assert cobj[-1] == 14 cobj[-1] = 15 assert list(cobj) == _list + [11, 15] del cobj[-1] cobj.reverse() _list.reverse() assert list(cobj) == [11] + _list class LW1(ListWrapper): _opts = dict(max_len=1, min_len=None) class LW2(ListWrapper): _opts = dict(max_len=None, min_len=50) assert_raises(ValueError, LW1(_list=_list).validate) assert_raises(ValueError, LW2(_list=_list).validate) class LW3(ListWrapper): _attrs = dict(a=Attr(int), b=Attr(float)) lw = LW3(1, 2, 3, a=1, b=1.2) assert str(lw) == "LW3(1, 2, 3, a = 1, b = 1.2)" pretty_lw = '''LW3(1, 2, 3, a = 1, b = 1.2)''' assert lw.pretty() == pretty_lw
def treenode_tst_3(cls): n5 = cls(_id = 5) n4 = cls(_id = 4) n3 = cls(n4, _id = 3) n2 = cls(_id = 2) n1 = cls(n2, n3, n5, _id = 1) assert n4.collect_rootward() == [n4, n3, n1] assert list(n4.rootward()) == [n4, n3, n1] assert list(n4.rootward(filt=lambda n: n._id >= 3)) == [n4, n3] assert list(n4.rootward(filt=lambda n: n._id <= 3)) == [n3, n1] assert list(n4.rootward(func=attrgetter('_id'), filt=lambda n: n._id <= 3)) == [3, 1] assert list(n1.depth_first()) == [n1, n2, n3, n4, n5] assert list(n1.depth_first(yield_depth=True)) == \ [(0, n1), (1, n2), (1, n3), (2, n4), (1, n5)] assert list(n1.depth_first(reverse=True)) == [n5, n4, n3, n2, n1] assert list(n1.depth_first(reverse=True, yield_depth=True)) == \ [(1, n5), (2, n4), (1, n3), (1, n2), (0, n1)] assert list(n1.depth_first(func=attrgetter('_id'), filt=lambda n: n._id % 2 == 0)) == [2, 4] assert n1._children == [n2, n3, n5] assert n3._children == [n4] assert n2._parent is n1 assert n3._parent is n1 assert n4._parent is n3 assert n5._parent is n1 assert list(n1.children()) == [n2, n3, n5] assert list(n1.children(reverse=True)) == [n5, n3, n2] assert list(n5.siblings()) == [n2, n3] assert list(n5.siblings(preceding=True)) == [n2, n3] assert list(n5.siblings(preceding=True, axis=True)) == [n3, n2] assert list(n5.siblings(following=True)) == [] assert list(n5.siblings(following=True, axis=True)) == [] assert list(n4.siblings()) == [] assert list(n3.siblings()) == [n2, n5] assert list(n3.siblings(preceding=True)) == [n2] assert list(n3.siblings(preceding=True, axis=True)) == [n2] assert list(n3.siblings(following=True)) == [n5] assert list(n3.siblings(following=True, axis=True)) == [n5] assert list(n2.siblings()) == [n3, n5] assert list(n2.siblings(axis=True)) == [n3, n5] assert list(n2.siblings(following=True)) == [n3, n5] assert list(n2.siblings(following=True, axis=True)) == [n3, n5] assert list(n2.siblings(preceding=True)) == [] assert list(n2.siblings(preceding=True, axis=True)) == [] assert list(n1.siblings()) == [] assert list(n1.descendants()) == [n2, n3, n4, n5] assert list(n1.descendants(include_self=True)) == [n1, n2, n3, n4, n5] assert list(n2.descendants()) == [] assert list(n3.descendants()) == [n4] assert list(n4.descendants()) == [] assert list(n5.descendants()) == [] assert list(n1.ancestors()) == [] assert list(n2.ancestors()) == [n1] assert list(n3.ancestors()) == [n1] assert list(n4.ancestors()) == [n3, n1] assert list(n4.ancestors(include_self=True)) == [n4, n3, n1] assert list(n5.ancestors()) == [n1] assert list(n1.following()) == [n2, n3, n4, n5] assert list(n2.following()) == [n3, n4, n5] assert list(n3.following()) == [n4, n5] assert list(n4.following()) == [n5] assert list(n5.following()) == [] assert list(n1.preceding()) == [] assert list(n2.preceding()) == [n1] assert list(n3.preceding()) == [n2, n1] assert list(n4.preceding()) == [n3, n2, n1] assert list(n5.preceding()) == [n4, n3, n2, n1] assert n1.root() is n1 assert n2.root() is n1 assert n3.root() is n1 assert n4.root() is n1 assert n5.root() is n1 assert_equivalent(n1, n1.copy()) assert_equivalent(n2, n2.copy()) assert_equivalent(n3, n3.copy()) assert_equivalent(n4, n4.copy()) assert_equivalent(n5, n5.copy()) assert n1.node_count() == 5 n4.add_child(Node()) assert n1.node_count() == 6 assert n4.node_count() == 2 n3.remove_child(n4) assert n1.node_count() == 4 n1.remove_child(n5) assert n1.node_count() == 3 assert n1._children == [n2, n3] assert n5._parent is None assert list(n5.siblings()) == [] assert list(n1.descendants()) == [n2, n3] assert_raises(TreeError, n1.remove_child, n5) def set_foo(n): n.foo = n._id * 2 consume(n1.depth_first(set_foo)) assert list(n1.depth_first(attrgetter('foo'))) == [2, 4, 6]
def test_mapping_conversion(): dct = dict(a = 1, b = 2.3, c = 'abc') assert_equivalent(Base._dict_from_mapping(dct), dct) ct1 = ConvTest(1, 2.3, 'abc') assert_equivalent(ConvTest.from_mapping(dct), ct1)
def test_mapping_conversion(): dct = dict(a=1, b=2.3, c='abc') assert_equivalent(Base._dict_from_mapping(dct), dct) ct1 = ConvTest(1, 2.3, 'abc') assert_equivalent(ConvTest.from_mapping(dct), ct1)
def test_dependencies(): def assert_listeq(A, B): for a in A: assert a in B for b in B: assert b in A with open(DEPS1, 'rt') as f: deps = Dependencies.from_yaml(f) contexts = dict(dev = [Apt('libxml2-dev'), Apt('libxslt1-dev'), Pip('lxml')], prod = [Pip('PyYAML')]) assert_equivalent(deps, Dependencies(contexts=contexts)) assert_listeq(deps.deps_from_context('all'), deps.contexts.dev + deps.contexts.prod) assert deps.deps_from_context('dev') == deps.contexts.dev assert deps.deps_from_context('prod') == deps.contexts.prod assert_raises(ValueError, deps.deps_from_context, 'foo') with open(DEPS2, 'rt') as f: deps2 = Dependencies.from_yaml(f) contexts = dict(dev = [Apt('gcc', order=0), Apt('make')]) assert_equivalent(deps2, Dependencies(contexts = contexts)) assert deps2.deps_from_context('all') == deps2.contexts.dev assert deps2.deps_from_context('dev') == deps2.contexts.dev assert_raises(ValueError, deps2.deps_from_context, 'prod') with open(DEPS3, 'rt') as f: deps3 = Dependencies.from_yaml(f) contexts = dict(prod = [Pip('six'), Pip('syn', version=Eq('0.0.7'), always_upgrade=True)]) assert_equivalent(deps3, Dependencies(contexts=contexts)) assert deps3.deps_from_context('all') == deps3.contexts.prod assert_raises(ValueError, deps3.deps_from_context, 'dev') assert deps3.deps_from_context('prod') == deps3.contexts.prod with open(DEPS4, 'rt') as f: deps4 = Dependencies.from_yaml(f) assert 'includes' not in deps4.contexts assert_listeq(deps4.deps_from_context('c1'), deps4.contexts.c1 + deps4.contexts.c2 + deps4.contexts.c3 + deps4.contexts.c4) assert_listeq(deps4.deps_from_context('c2'), deps4.contexts.c2 + deps4.contexts.c3) assert_listeq(deps4.deps_from_context('c3'), deps4.contexts.c3) assert_listeq(deps4.deps_from_context('c4'), deps4.contexts.c4) assert_listeq(deps4.deps_from_context('c5'), deps4.contexts.c5) assert_raises(AssertionError, Dependencies, contexts = dict(c1 = [Apt('make')], c2 = [Pip('six')]), includes = dict(c1 = ['c2', 'c3'])) assert_raises(AssertionError, Dependencies, contexts = dict(c1 = [Apt('make')], c2 = [Pip('six')]), includes = dict(c3 = ['c2', 'c2'])) with open(DEPS5, 'rt') as f: deps5 = Dependencies.from_yaml(f) with assign(Apt, '_pkgs', dict()): with assign(Pip, '_pkgs', dict()): from depman.apt import Install, Update from depman.pip import Install as PipInstall ops = deps5.satisfy('prod', execute=False) assert ops == [Update(order=Apt.order), Install('a', 'b', 'c', 'd', order=Apt.order), PipInstall('a', 'b', 'c', order=Pip.order)] with assign(aptd, 'command', MagicMock()): with assign(pipd, 'command', MagicMock()): deps5.satisfy('prod') assert aptd.command.call_count == 2 aptd.command.assert_any_call('apt-get update') aptd.command.assert_any_call('apt-get install -y a b c d') assert pipd.command.call_count == 1 pipd.command.assert_any_call('pip install --upgrade a b c') with open(DEPS6, 'rt') as f: deps6 = Dependencies.from_yaml(f) hdr = deps6.export_header() assert hdr == '# Auto-generated by depman {}\n'.format(dver) out = deps6.export('all', dispatch_type('pip'), None, write=False) eout = hdr + 'a\nb==1.2\nc<=1.2\nd>=1.2' # expected output (or export output) assert out == eout with open(TEST1, 'wt') as f: deps6.export('prod', dispatch_type('pip'), f) with open(TEST1, 'rt') as f: assert f.read() == eout with assign(Apt, '_pkgs', dict(a='1', b='1.3', c='1.3', f='1')): with assign(Pip, '_pkgs', dict(a='1', b='1.3', c='1.3')): from depman.apt import Install, Update, Remove from depman.pip import Install as PipInstall ops = deps6.satisfy('prod', execute=False) assert ops == [Remove('b', 'c', order=Apt.order), Update(order=Apt.order), Install('b=1.2', 'c=1.2', 'd', 'e=1.3', 'f', order=Apt.order), PipInstall('b==1.2', 'c==1.2', 'd', order=Pip.order)] with assign(aptd, 'command', MagicMock()): with assign(pipd, 'command', MagicMock()): deps6.satisfy('prod') assert aptd.command.call_count == 3 aptd.command.assert_any_call('apt-get remove -y b c') aptd.command.assert_any_call('apt-get update') aptd.command.assert_any_call('apt-get install -y b=1.2 ' 'c=1.2 d e=1.3 f') assert pipd.command.call_count == 1 pipd.command.assert_any_call('pip install --upgrade b==1.2 ' 'c==1.2 d') with open(DEPS7, 'rt') as f: deps7 = Dependencies.from_yaml(f) with assign(Apt, '_pkgs', dict()): with assign(Pip, '_pkgs', dict()): from depman.apt import Install, Update from depman.pip import Install as PipInstall ops = deps7.satisfy('prod', execute=False) assert ops == [PipInstall('d', order=Pip.order), Update(order=Apt.order), Install('b', order=Apt.order), Update(order=Apt.order), Install('a', order=Apt.order), PipInstall('c', order=Pip.order)] with assign(aptd, 'command', MagicMock()): with assign(pipd, 'command', MagicMock()): deps7.satisfy('prod') assert aptd.command.call_count == 4 aptd.command.assert_any_call('apt-get update') aptd.command.assert_any_call('apt-get install -y a') aptd.command.assert_any_call('apt-get install -y b') assert pipd.command.call_count == 2 pipd.command.assert_any_call('pip install --upgrade c') pipd.command.assert_any_call('pip install --upgrade d') with open(DEPS8, 'rt') as f: deps8 = Dependencies.from_yaml(f) with assign(Apt, '_pkgs', dict()): with assign(Pip, '_pkgs', dict()): from depman.apt import Install, Update from depman.pip import Install as PipInstall from depman.yatr import Task ops = deps8.satisfy('prod', execute=False) assert ops == [PipInstall('g', order=Pip.order), Update(order=Apt.order), Install('a', 'b', 'd', order=Apt.order), Update(order=Apt.order), Install('c', order=Apt.order), PipInstall('e', 'f', order=Pip.order), Task('z', order=Yatr.order)] with assign(aptd, 'command', MagicMock()): with assign(pipd, 'command', MagicMock()): with assign(yatrd, 'command', MagicMock()): deps8.satisfy('prod') assert aptd.command.call_count == 4 aptd.command.assert_any_call('apt-get update') aptd.command.assert_any_call('apt-get install -y a b d') aptd.command.assert_any_call('apt-get install -y c') assert pipd.command.call_count == 2 pipd.command.assert_any_call('pip install --upgrade e f') pipd.command.assert_any_call('pip install --upgrade g') assert yatrd.command.call_count == 1 yatrd.command.assert_any_call('yatr z') with open(DEPS9, 'rt') as f: deps9 = Dependencies.from_yaml(f) with assign(Apt, '_pkgs', dict()): with assign(Pip, '_pkgs', dict()): from depman.pip import Install as PipInstall from depman.yatr import Task ops = deps9.satisfy('prod', execute=False) assert ops[0:2] == [PipInstall('a', order=Pip.order), PipInstall('b', order=Pip.order)] others = [PipInstall('c', order=Pip.order), PipInstall('d', order=Pip.order), Task('z', order=Yatr.order)] assert ops[2] in others assert ops[3] in others assert ops[4] in others with open(DEPS10, 'rt') as f: deps10 = Dependencies.from_yaml(f) with assign(Apt, '_pkgs', dict()): with assign(Pip, '_pkgs', dict()): from depman.apt import Install, Update from depman.pip import Install as PipInstall from depman.yatr import Task ops = deps10.satisfy('prod', execute=False) assert ops == [Task('install-from-source', order=Yatr.order), Update(order=Apt.order), Install('a', 'b', 'd', order=Apt.order), Update(order=Apt.order), Install('c', order=Apt.order), Task('install-from-source-2', order=Yatr.order), PipInstall('e', 'g', order=Pip.order), PipInstall('f', order=Pip.order), Task('cleanup', order=Yatr.order)] with assign(aptd, 'command', MagicMock()): with assign(pipd, 'command', MagicMock()): with assign(yatrd, 'command', MagicMock()): deps10.satisfy('prod') assert aptd.command.call_count == 4 aptd.command.assert_any_call('apt-get update') aptd.command.assert_any_call('apt-get install -y a b d') aptd.command.assert_any_call('apt-get install -y c') assert pipd.command.call_count == 2 pipd.command.assert_any_call('pip install --upgrade e g') pipd.command.assert_any_call('pip install --upgrade f') assert yatrd.command.call_count == 3 yatrd.command.assert_any_call('yatr install-from-source') yatrd.command.assert_any_call('yatr install-from-source-2') yatrd.command.assert_any_call('yatr cleanup') with open(DEPSEX, 'rt') as f: depsex = Dependencies.from_yaml(f) with assign(Apt, '_pkgs', dict()): with assign(Pip, '_pkgs', dict()): from depman.apt import Install, Update from depman.pip import Install as PipInstall from depman.yatr import Task # all ops = depsex.satisfy('all', execute=False) _ops = [Task('install-from-source', order=Yatr.order), Update(order=Apt.order), Install('libxml2-dev=2.9.1+dfsg1-5+deb8u2', 'libxslt1-dev', order=Apt.order), Task('install-from-source-2', order=Yatr.order), PipInstall('Sphinx', 'coverage', 'gevent==1.0.2', 'lxml', 'nose', 'numpy', 'six', 'syn', order=Pip.order), PipInstall('openopt', order=Pip.order), Task('-f other_tasks.yml', 'cleanup', order=Yatr.order)] assert ops == _ops with assign(aptd, 'command', MagicMock()): with assign(pipd, 'command', MagicMock()): with assign(yatrd, 'command', MagicMock()): depsex.satisfy('all') assert aptd.command.call_count == 2 aptd.command.assert_any_call('apt-get update') aptd.command.assert_any_call('apt-get install -y libxml2-dev=2.9.1+dfsg1-5+deb8u2 libxslt1-dev') assert pipd.command.call_count == 2 pipd.command.assert_any_call('pip install --upgrade Sphinx coverage gevent==1.0.2 lxml nose numpy six syn') pipd.command.assert_any_call('pip install --upgrade openopt') assert yatrd.command.call_count == 3 yatrd.command.assert_any_call('yatr install-from-source') yatrd.command.assert_any_call('yatr install-from-source-2') yatrd.command.assert_any_call('yatr -f other_tasks.yml cleanup') # test ops = depsex.satisfy('test', execute=False) _ops = [PipInstall('coverage', 'nose', order=Pip.order)] assert ops == _ops with assign(aptd, 'command', MagicMock()): with assign(pipd, 'command', MagicMock()): with assign(yatrd, 'command', MagicMock()): depsex.satisfy('test') assert aptd.command.call_count == 0 assert pipd.command.call_count == 1 pipd.command.assert_any_call('pip install --upgrade coverage nose') assert yatrd.command.call_count == 0 # dev ops = depsex.satisfy('dev', execute=False) _ops = [Task('install-from-source', order=Yatr.order), Update(order=Apt.order), Install('libxml2-dev=2.9.1+dfsg1-5+deb8u2', 'libxslt1-dev', order=Apt.order), PipInstall('Sphinx', 'coverage', 'lxml', 'nose', order=Pip.order)] assert ops == _ops with assign(aptd, 'command', MagicMock()): with assign(pipd, 'command', MagicMock()): with assign(yatrd, 'command', MagicMock()): depsex.satisfy('dev') assert aptd.command.call_count == 2 aptd.command.assert_any_call('apt-get update') aptd.command.assert_any_call('apt-get install -y libxml2-dev=2.9.1+dfsg1-5+deb8u2 libxslt1-dev') assert pipd.command.call_count == 1 pipd.command.assert_any_call('pip install --upgrade Sphinx coverage lxml nose') assert yatrd.command.call_count == 1 yatrd.command.assert_any_call('yatr install-from-source') # prod ops = depsex.satisfy('prod', execute=False) _ops = [Task('install-from-source-2', order=Yatr.order), PipInstall('gevent==1.0.2', 'numpy', 'six', 'syn', order=Pip.order), PipInstall('openopt', order=Pip.order), Task('-f other_tasks.yml', 'cleanup', order=Yatr.order)] assert ops == _ops with assign(aptd, 'command', MagicMock()): with assign(pipd, 'command', MagicMock()): with assign(yatrd, 'command', MagicMock()): depsex.satisfy('prod') assert aptd.command.call_count == 0 assert pipd.command.call_count == 2 pipd.command.assert_any_call('pip install --upgrade gevent==1.0.2 numpy six syn') pipd.command.assert_any_call('pip install --upgrade openopt') assert yatrd.command.call_count == 2 yatrd.command.assert_any_call('yatr install-from-source-2') yatrd.command.assert_any_call('yatr -f other_tasks.yml cleanup')
def treenode_tst_3(cls): n5 = cls(_id=5) n4 = cls(_id=4) n3 = cls(n4, _id=3) n2 = cls(_id=2) n1 = cls(n2, n3, n5, _id=1) assert n4.collect_rootward() == [n4, n3, n1] assert list(n4.rootward()) == [n4, n3, n1] assert list(n4.rootward(filt=lambda n: n._id >= 3)) == [n4, n3] assert list(n4.rootward(filt=lambda n: n._id <= 3)) == [n3, n1] assert list(n4.rootward(func=attrgetter('_id'), filt=lambda n: n._id <= 3)) == [3, 1] assert list(n1.depth_first()) == [n1, n2, n3, n4, n5] assert list(n1.depth_first(yield_depth=True)) == \ [(0, n1), (1, n2), (1, n3), (2, n4), (1, n5)] assert list(n1.depth_first(reverse=True)) == [n5, n4, n3, n2, n1] assert list(n1.depth_first(reverse=True, yield_depth=True)) == \ [(1, n5), (2, n4), (1, n3), (1, n2), (0, n1)] assert list( n1.depth_first(func=attrgetter('_id'), filt=lambda n: n._id % 2 == 0)) == [2, 4] assert n1._children == [n2, n3, n5] assert n3._children == [n4] assert n2._parent is n1 assert n3._parent is n1 assert n4._parent is n3 assert n5._parent is n1 assert list(n1.children()) == [n2, n3, n5] assert list(n1.children(reverse=True)) == [n5, n3, n2] assert list(n5.siblings()) == [n2, n3] assert list(n5.siblings(preceding=True)) == [n2, n3] assert list(n5.siblings(preceding=True, axis=True)) == [n3, n2] assert list(n5.siblings(following=True)) == [] assert list(n5.siblings(following=True, axis=True)) == [] assert list(n4.siblings()) == [] assert list(n3.siblings()) == [n2, n5] assert list(n3.siblings(preceding=True)) == [n2] assert list(n3.siblings(preceding=True, axis=True)) == [n2] assert list(n3.siblings(following=True)) == [n5] assert list(n3.siblings(following=True, axis=True)) == [n5] assert list(n2.siblings()) == [n3, n5] assert list(n2.siblings(axis=True)) == [n3, n5] assert list(n2.siblings(following=True)) == [n3, n5] assert list(n2.siblings(following=True, axis=True)) == [n3, n5] assert list(n2.siblings(preceding=True)) == [] assert list(n2.siblings(preceding=True, axis=True)) == [] assert list(n1.siblings()) == [] assert list(n1.descendants()) == [n2, n3, n4, n5] assert list(n1.descendants(include_self=True)) == [n1, n2, n3, n4, n5] assert list(n2.descendants()) == [] assert list(n3.descendants()) == [n4] assert list(n4.descendants()) == [] assert list(n5.descendants()) == [] assert list(n1.ancestors()) == [] assert list(n2.ancestors()) == [n1] assert list(n3.ancestors()) == [n1] assert list(n4.ancestors()) == [n3, n1] assert list(n4.ancestors(include_self=True)) == [n4, n3, n1] assert list(n5.ancestors()) == [n1] assert list(n1.following()) == [n2, n3, n4, n5] assert list(n2.following()) == [n3, n4, n5] assert list(n3.following()) == [n4, n5] assert list(n4.following()) == [n5] assert list(n5.following()) == [] assert list(n1.preceding()) == [] assert list(n2.preceding()) == [n1] assert list(n3.preceding()) == [n2, n1] assert list(n4.preceding()) == [n3, n2, n1] assert list(n5.preceding()) == [n4, n3, n2, n1] assert n1.root() is n1 assert n2.root() is n1 assert n3.root() is n1 assert n4.root() is n1 assert n5.root() is n1 assert_equivalent(n1, n1.copy()) assert_equivalent(n2, n2.copy()) assert_equivalent(n3, n3.copy()) assert_equivalent(n4, n4.copy()) assert_equivalent(n5, n5.copy()) assert n1.node_count() == 5 n4.add_child(Node()) assert n1.node_count() == 6 assert n4.node_count() == 2 n3.remove_child(n4) assert n1.node_count() == 4 n1.remove_child(n5) assert n1.node_count() == 3 assert n1._children == [n2, n3] assert n5._parent is None assert list(n5.siblings()) == [] assert list(n1.descendants()) == [n2, n3] assert_raises(TreeError, n1.remove_child, n5) def set_foo(n): n.foo = n._id * 2 consume(n1.depth_first(set_foo)) assert list(n1.depth_first(attrgetter('foo'))) == [2, 4, 6]