This repository was archived by the owner on Mar 8, 2018. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathtest_attrs_sqlalchemy.py
130 lines (99 loc) · 4.19 KB
/
test_attrs_sqlalchemy.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
import pytest
import sqlalchemy as sa
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.ext.hybrid import hybrid_property
from attrs_sqlalchemy import attrs_sqlalchemy
class TestAttrsSqlalchemy:
def test_deprecation(self):
with pytest.warns(UserWarning, match='attrs_sqlalchemy is deprecated'):
@attrs_sqlalchemy
class MyModel(declarative_base()):
__tablename__ = 'mymodel'
id = sa.Column(sa.Integer, primary_key=True)
@pytest.mark.parametrize('decorator', [attrs_sqlalchemy, attrs_sqlalchemy()])
def test_attrs_sqlalchemy(self, decorator):
"""
Decorating a class with ``@attrs_sqlalchemy`` or
``@attrs_sqlalchemy()`` should add ``__repr__``, ``__eq__``, and
``__hash__`` methods based on the fields on the model.
"""
TestBase = declarative_base()
@attrs_sqlalchemy
class MyModel(TestBase):
__tablename__ = 'mymodel'
id = sa.Column(sa.Integer, primary_key=True)
text = sa.Column(sa.String)
instance = MyModel(id=1, text='hello')
same_data = MyModel(id=1, text='hello')
same_pk = MyModel(id=1, text='world')
# All fields are the same
assert instance == same_data
# Primary key is not enough for equality
assert instance != same_pk
# Instances should have a repr containing their keys and type
assert repr(instance) == "MyModel(id=1, text='hello')"
# Instances should be hashable by their fields and used in a dict
d = {instance: True}
assert d.get(same_data) == d[instance]
assert d.get(same_pk) is None
def test_field_name_not_column_name(self):
"""
``@attrs_sqlalchemy`` should use attribute/field names, not column names.
"""
@attrs_sqlalchemy
class MyModel(declarative_base()):
__tablename__ = 'mymodel'
_id = sa.Column('id', sa.Integer, primary_key=True)
text = sa.Column(sa.String)
assert {attr.name for attr in MyModel.__attrs_attrs__} == {'_id', 'text'}
def test_subclass(self):
"""
When used on a subclass, ``@attrs_sqalchemy`` should also include the
attributes from the parent class(es), even if a parent class is also
decorated with ``@attrs_sqlalchemy``.
"""
@attrs_sqlalchemy
class ParentModel(declarative_base()):
__tablename__ = 'parent'
id = sa.Column(sa.Integer, primary_key=True)
type = sa.Column(sa.String)
__mapper_args__ = {
'polymorphic_identity': 'parent',
'polymorphic_on': type,
}
@attrs_sqlalchemy
class ChildModel(ParentModel):
__tablename__ = 'child'
id = sa.Column(sa.Integer, sa.ForeignKey('parent.id'), primary_key=True)
child_field = sa.Column(sa.Integer)
__mapper_args__ = {
'polymorphic_identity': 'child',
}
@attrs_sqlalchemy
class ChildChildModel(ChildModel):
__tablename__ = 'very_child'
id = sa.Column(sa.Integer, sa.ForeignKey('child.id'), primary_key=True)
very_child_field = sa.Column(sa.String)
__mapper_args__ = {
'polymorphic_identity': 'childchild',
}
assert {attr.name for attr in ChildModel.__attrs_attrs__} == {
'id', 'type', 'child_field',
}
assert {attr.name for attr in ChildChildModel.__attrs_attrs__} == {
'id', 'type', 'child_field', 'very_child_field',
}
def test_hybrid_property(self):
"""
Hybrid properties should not be included in the attributes used by
``@attrs_sqlalchemy``.
"""
@attrs_sqlalchemy
class MyModel(declarative_base()):
__tablename__ = 'mymodel'
id = sa.Column(sa.Integer, primary_key=True)
text = sa.Column(sa.String)
@hybrid_property
def tiny_text(self): # pragma: no cover
return self.text[:10]
assert {attr.name for attr in MyModel.__attrs_attrs__} == {'id', 'text'}