def test_add_class_attrs_does_not_create_duplicate_types(manager):
    with collector() as classes:
        class DynamicThing(Entity):
            id = Uuid()
    manager.save_collected_classes(classes)
    del DynamicThing
    manager.reload_types()

    DynamicThing = manager.type_registry.get_class_by_id(
        'DynamicThing')

    DynamicThing.cls_attr = "ham"
    manager.save(DynamicThing)

    rows = manager.query(
        ''' START base = node(*)
            MATCH tpe -[r:ISA]-> base
            RETURN tpe.id , r.__type__, base.id
            ORDER BY tpe.id, base.id
        ''')
    result = list(rows)

    assert result == [
        ('DynamicThing', 'IsA', 'Entity'),
    ]
def test_class_attr_class_serialization(manager):
    with collector() as classes:
        class A(Entity):
            id = Uuid()
            cls_attr = "spam"

        class B(A):
            cls_attr = "ham"

        class C(B):
            pass

    manager.save_collected_classes(classes)

    # we want inherited attributes when we serialize
    assert manager.serialize(C) == {
        '__type__': 'PersistableType',
        'id': 'C',
        'cls_attr': 'ham',
    }

    # we don't want inherited attributes in the db
    query_str = join_lines(
        "START",
        get_start_clause(C, 'C', manager.type_registry),
        """
            RETURN C
        """
    )

    (db_attrs,) = next(manager._execute(query_str))
    properties = db_attrs.get_properties()
    assert 'cls_attr' not in properties
def test_delete_class_attrs(manager):
    with collector() as classes:
        class DynamicThing(Entity):
            id = Uuid()
            cls_attr = "spam"

    manager.save_collected_classes(classes)

    del DynamicThing

    # this is the same as creating a new manager using the same URL
    manager.reload_types()

    DynamicThing = manager.type_registry.get_class_by_id(
        'DynamicThing')
    assert DynamicThing.cls_attr == "spam"

    delattr(DynamicThing, 'cls_attr')
    manager.save(DynamicThing)

    del DynamicThing

    manager.reload_types()

    DynamicThing = manager.type_registry.get_class_by_id(
        'DynamicThing')
    assert not(hasattr(DynamicThing, 'cls_attr'))
Beispiel #4
0
def test_cannot_reparent_with_incompatible_attributes(manager, static_types):
    Cetacean = static_types['Cetacean']
    WaterBound = static_types['WaterBound']

    Whale = manager.create_type('Whale', (WaterBound,), {})
    manager.save(Whale)

    with pytest.raises(CannotUpdateType) as e:
        manager.update_type(Whale, (Cetacean,))
    assert e.value.message == "Inherited attributes are not identical"

    with collector() as collected:
        class A(Entity):
            foo = String()

        class B(Entity):
            foo = Bool()
    manager.save_collected_classes(collected)

    C = manager.create_type('C', (A,), {})
    manager.save(C)

    with pytest.raises(CannotUpdateType) as e:
        manager.update_type(C, (B,))
    assert e.value.message == "Inherited attributes are not identical"
def test_basic(manager):
    with collector() as collected:
        class A(Entity):
            pass

        class A2(A):
            pass

        class B(Entity):
            pass

        class B2(B):
            pass

        class AB(A, B):
            pass

    manager.save_collected_classes(collected)
    amended_registry = get_type_registry_with_base_change(
        manager, 'AB', ('A2', 'B2'))

    AmendedAB = amended_registry.get_class_by_id('AB')
    assert [c.__name__ for c in AmendedAB.mro()] == [
        'AB', 'A2', 'A', 'B2', 'B', 'Entity', 'AttributedBase',
        'Persistable', 'object'
    ]

    # check original registry is unchanged
    OriginalAB = manager.type_registry.get_class_by_id('AB')
    assert [c.__name__ for c in OriginalAB.mro()] == [
        'AB', 'A', 'B', 'Entity', 'AttributedBase',
        'Persistable', 'object'
    ]
Beispiel #6
0
def test_changing_bases_does_not_create_duplicate_types(manager):
    with collector() as classes:
        class ShrubBaseA(Entity):
            id = Uuid()

        class ShrubBaseB(Entity):
            pass

        class Shrub(ShrubBaseA):
            pass

    manager.save_collected_classes(classes)
    del Shrub

    manager.reload_types()

    with collector() as classes:
        class Shrub(ShrubBaseB, ShrubBaseA):
            pass

        class SubShrub(Shrub):
            pass

    manager.type_registry.register(SubShrub)
    manager.save(SubShrub)

    rows = manager.query(
        ''' START base = node(*)
            MATCH tpe -[r:ISA]-> base
            RETURN tpe.id , r.__type__, r.base_index, base.id
            ORDER BY tpe.id, r.base_index, base.id
        ''')
    result = list(rows)

    assert result == [
        ('Shrub', 'IsA', 0, 'ShrubBaseB'),
        ('Shrub', 'IsA', 1, 'ShrubBaseA'),
        ('ShrubBaseA', 'IsA', 0, 'Entity'),
        ('ShrubBaseB', 'IsA', 0, 'Entity'),
        ('SubShrub', 'IsA', 0, 'Shrub'),
    ]
def test_unknown_types(manager):
    with collector() as collected:
        class A(Entity):
            pass

    manager.save_collected_classes(collected)

    with pytest.raises(UnknownType):
        get_type_registry_with_base_change(manager, 'A', ['Invalid'])

    with pytest.raises(UnknownType):
        get_type_registry_with_base_change(manager, 'Invalid', ['A'])
def test_class_name_escaping(manager):
    with collector() as classes:
        class Match(Entity):
            id = Uuid()
            where = Uuid()

        class Set(Match):
            pass

        class Return(Set):
            pass

    manager.save_collected_classes(classes)
Beispiel #9
0
def test_dynamic_unique_attr_adds_label(manager):
    with collector() as collected:

        class Foo(Entity):
            attr = Integer(unique=False)

        class Bar(Entity):
            attr = Integer(unique=True)

    manager.save_collected_classes(collected)

    assert manager.type_registry.get_labels_for_type(Foo) == set()
    assert manager.type_registry.get_labels_for_type(Bar) == set(["Bar"])
def test_duplicate_base_class(manager):
    with collector() as collected:
        class A(Entity):
            pass

        class B(Entity):
            pass

        class C(A, B):
            pass

    manager.save_collected_classes(collected)

    with pytest.raises(ValueError) as ex:
        get_type_registry_with_base_change(manager, 'C', ('A', 'B', 'A'))
    assert "duplicate base class" in str(ex)
def test_load_class_attr(manager):
    with collector() as classes:
        class DynamicThing(Entity):
            id = Uuid(unique=True)
            cls_attr = "spam"

    manager.save_collected_classes(classes)
    manager.reload_types()

    data = {
        '__type__': 'PersistableType',
        'id': 'DynamicThing',
        'cls_attr': 'ham'
    }
    cls = manager.deserialize(data)
    assert cls.cls_attr == 'ham'
def test_become_your_own_ancestor(manager):
    with collector() as collected:
        class A(Entity):
            pass

        class A2(A):
            pass

        class A3(A2):
            pass

    manager.save_collected_classes(collected)

    # become your own parent
    with pytest.raises(ValueError) as ex:
        get_type_registry_with_base_change(manager, 'A', ('A3',))
    assert "inheritance cycle" in str(ex)
def test_amended_indexes(manager):
    with collector() as collected:
        class A(Entity):
            id = Integer(unique=True)

        class B(Entity):
            code = String(unique=True)

    manager.save_collected_classes(collected)

    amended_registry = get_type_registry_with_base_change(
        manager, 'B', ('A',))

    # confirm that the "amended" indexes of B are now using both id and code
    amended_indexes = amended_registry.get_unique_attrs(B)
    assert {(get_type_id(cls), attr) for cls, attr in amended_indexes} == {
        ('A', 'id'), ('B', 'code')
    }
def test_class_attr_inheritence(manager):
    with collector() as classes:
        class A(Entity):
            attr = True

        class B(A):
            pass

        class C(B):
            attr = False

        class D(C):
            pass

    manager.save_collected_classes(classes)

    assert A().attr is True
    assert B().attr is True
    assert C().attr is False
    assert D().attr is False
Beispiel #15
0
def test_reparent_with_matching_attributes(manager):
    """ Reparenting with different but identical attributes is allowed.
    """
    with collector() as collected:
        class C(Entity):
            foo = String()

        class D(Entity):
            foo = String()
    manager.save_collected_classes(collected)

    E = manager.create_type('E', (C,), {})
    manager.save(E)

    manager.update_type(E, (D,))

    UpdatedD = manager.type_registry.get_class_by_id(get_type_id(D))
    UpdatedE = manager.type_registry.get_class_by_id(get_type_id(E))
    assert UpdatedE.__bases__ == (UpdatedD,)
    assert issubclass(UpdatedE, UpdatedD)
def test_amended_indexes_same_attr_name(manager):
    with collector() as collected:
        class A(Entity):
            id = Integer(unique=True)

        class B(Entity):
            id = String(unique=True)

        class C(A):
            pass

    manager.save_collected_classes(collected)

    amended_registry = get_type_registry_with_base_change(
        manager, 'C', ('A', 'B'))

    # confirm that the "amended" indexes of C are still just A.id
    amended_indexes = amended_registry.get_unique_attrs(C)
    assert {(get_type_id(cls), attr) for cls, attr in amended_indexes} == {
        ('A', 'id'),
    }
def test_class_att_overriding(manager):
    with collector() as classes:
        class A(Entity):
            id = Uuid()
            cls_attr = "spam"

        class B(A):
            cls_attr = "ham"

        class C(B):
            pass

    manager.save_collected_classes(classes)
    manager.reload_types()

    a = A()
    b = B()
    c = C()

    assert a.cls_attr == "spam"
    assert b.cls_attr == "ham"
    assert c.cls_attr == "ham"

    manager.save(a)
    manager.save(b)
    manager.save(c)

    query_str = join_lines(
        "START",
        get_start_clause(A, 'A', manager.type_registry),
        """
            MATCH node -[:INSTANCEOF]-> () -[:ISA*0..]-> A
            return node
        """
    )

    results = list(manager.query(query_str))

    for col, in results:
        assert col.cls_attr == col.__class__.cls_attr
def test_true_class_attr(manager):
    with collector() as classes:
        class DynamicThing(Entity):
            id = Uuid()
            cls_attr = True

    manager.save_collected_classes(classes)

    # we want inherited attributes when we serialize
    assert manager.serialize(DynamicThing) == {
        '__type__': 'PersistableType',
        'id': 'DynamicThing',
        'cls_attr': True,
    }

    manager.reload_types()
    DynamicThing = manager.type_registry.get_class_by_id(
        'DynamicThing')
    thing = DynamicThing()

    assert DynamicThing.cls_attr is True
    assert thing.cls_attr is True
def test_class_attrs(manager):
    with collector() as collected:
        class A(Entity):
            cls_attr = 'fromA'
            cls_attr_A = 'A'

        class B(Entity):
            cls_attr = 'fromB'
            cls_attr_B = 'B'

        class C(A):
            cls_attr = 'fromC'
            cls_attr_C = 'C'

    manager.save_collected_classes(collected)

    def get_cls_attrs(cls):
        attr_names = ['cls_attr', 'cls_attr_A', 'cls_attr_B', 'cls_attr_C']
        return {a: getattr(cls, a, None) for a in attr_names}

    # check initial state
    assert get_cls_attrs(C) == {
        'cls_attr': 'fromC',
        'cls_attr_A': 'A',
        'cls_attr_B': None,
        'cls_attr_C': 'C'
    }

    amended_registry = get_type_registry_with_base_change(
        manager, 'C', ('A', 'B'))

    amended_C = amended_registry.get_class_by_id('C')
    assert get_cls_attrs(amended_C) == {
        'cls_attr': 'fromC',
        'cls_attr_A': 'A',
        'cls_attr_B': 'B',
        'cls_attr_C': 'C'
    }
Beispiel #20
0
def test_static_descriptor_caching(manager):
    with collector():

        class Thing(Entity):
            prop_x = String(required=True)

        class That(Entity):
            prop_y = String(unique=True)

        type_registry = TypeRegistry()

        thing_descriptor1 = type_registry.get_descriptor(Thing)
        thing_descriptor2 = type_registry.get_descriptor(Thing)

        that_descriptor1 = type_registry.get_descriptor(That)
        that_descriptor2 = type_registry.get_descriptor(That)

        # assert repeated calls return the same objects
        assert thing_descriptor1 is thing_descriptor2
        assert that_descriptor1 is that_descriptor2

        # check that different types still get different descriptors
        assert thing_descriptor1 is not that_descriptor1
def test_bad_mro(manager):
    """
    from http://www.python.org/download/releases/2.3/mro/

     -----------
    |           |
    |    O      |
    |  /   \    |
     - X    Y  /
       |  / | /
       | /  |/
       A    B
       \   /
         ?
    """

    with collector() as collected:
        class X(Entity):
            pass

        class Y(Entity):
            pass

        class A(X, Y):
            pass

        class B(Y):  # to become B(Y, X)
            pass

        class AB(A, B):
            pass

    manager.save_collected_classes(collected)

    with pytest.raises(ValueError) as ex:
        get_type_registry_with_base_change(manager, 'B', ('Y', 'X'))
    assert "Cannot create a consistent method resolution" in str(ex)
Beispiel #22
0
def test_descriptor_property_caching(manager):
    with collector():

        class Thing(Entity):
            prop_x = String(required=True)

        class That(Entity):
            prop_y = String(unique=True)

        type_registry = TypeRegistry()

        thing_descriptor = type_registry.get_descriptor(Thing)
        that_descriptor = type_registry.get_descriptor(That)

        property_names = [
            'attributes', 'relationships', 'declared_attributes',
            'class_attributes', 'declared_class_attributes'
        ]
        for name in property_names:
            thing_val1 = getattr(thing_descriptor, name)
            thing_val2 = getattr(thing_descriptor, name)
            that_val = getattr(that_descriptor, name)
            assert thing_val1 is thing_val2, name
            assert thing_val2 is not that_val, name
def test_move_down_the_hieararchy(manager):

    with collector() as collected:
        class A(Entity):
            pass

        class A2(A):
            pass

        class A3(A2):
            pass

        class A4(A3):
            pass

        class B(A):
            pass

        class C(B):
            pass

    manager.save_collected_classes(collected)

    get_type_registry_with_base_change(manager, 'B', ('A4',))
def test_class_and_attr_name_clash(manager):
    with collector() as classes:
        class Foo(Entity):
            Foo = Uuid()

    manager.save_collected_classes(classes)
def test_invalidate_type_system(manager, static_types):
    Related = static_types['Related']

    with collector():
        class TypeA(Entity):
            id = Uuid(unique=True)

        class TypeB(Entity):
            attr = String(unique=True)

        class BaseType(Entity):
            pass

    manager.type_registry.register(TypeA)
    manager.type_registry.register(TypeB)
    manager.type_registry.register(BaseType)

    versions = []

    def is_distinct_version(v):
        distinct = v not in versions
        versions.append(v)
        return distinct

    v0 = manager._type_system_version()
    assert is_distinct_version(v0)

    manager.save(TypeA)  # create type
    manager.save(BaseType)
    v1 = manager._type_system_version()
    assert is_distinct_version(v1)

    manager.save(TypeA)  # save unchanged type
    assert manager._type_system_version() == v1

    type_a = TypeA()
    manager.save(type_a)  # create instance
    assert manager._type_system_version() == v1

    type_b = TypeB(attr="value")
    manager.save(TypeB)
    manager.save(type_b)  # create instance & type
    v3 = manager._type_system_version()
    assert is_distinct_version(v3)

    type_b.new_attr = "value"
    manager.save(type_b)  # add instance attribute
    assert manager._type_system_version() == v3

    type_b.new_attr = "new_value"
    manager.save(type_b)  # modify instance attribute
    assert manager._type_system_version() == v3

    del type_b.new_attr
    manager.save(type_b)  # delete instance attribute
    assert manager._type_system_version() == v3

    isa = IsA(type_a, BaseType)
    isa.base_index = 1
    manager.save(isa)  # create a type-hierarchy relationship
    v4 = manager._type_system_version()
    assert is_distinct_version(v4)

    rel = Related(type_a, type_b)
    manager.save(rel)  # create a non-type-hierarchy relationship
    assert manager._type_system_version() == v4

    manager.update_type(TypeA, (BaseType,))  # reparent
    v5 = manager._type_system_version()
    assert is_distinct_version(v5)

    # update_type reloads the type hierarchy, so refresh references
    TypeA = manager.type_registry.get_class_by_id('TypeA')
    TypeB = manager.type_registry.get_class_by_id('TypeB')
    BaseType = manager.type_registry.get_class_by_id('BaseType')

    manager.delete(isa)  # delete a type-hierarchy relationship
    v6 = manager._type_system_version()
    assert is_distinct_version(v6)

    manager.delete(rel)  # delete a non-type-hierarchy relationship
    assert manager._type_system_version() == v6

    manager.delete(TypeA)  # delete type
    v7 = manager._type_system_version()
    assert is_distinct_version(v7)

    manager.delete(type_a)  # delete instance
    assert manager._type_system_version() == v7

    TypeB.cls_attr = "value"
    manager.save(TypeB)  # add class attribute
    v8 = manager._type_system_version()
    assert is_distinct_version(v8)

    TypeB.cls_attr = "new_value"
    manager.save(TypeB)  # modify class attribute
    v9 = manager._type_system_version()
    assert is_distinct_version(v9)

    del TypeB.cls_attr
    manager.save(TypeB)  # delete class attribute
    v10 = manager._type_system_version()
    assert is_distinct_version(v10)