Skip to content

Commit 10185a2

Browse files
authored
Merge pull request #1126 from ethho/dev-tests-plat-153-declare
PLAT-153: Migrate test_declare.py
2 parents 6ee5d20 + 45f9997 commit 10185a2

File tree

2 files changed

+325
-1
lines changed

2 files changed

+325
-1
lines changed

tests/conftest.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ def connection_root(connection_root_bare):
118118

119119
# Teardown
120120
conn_root.query("SET FOREIGN_KEY_CHECKS=0")
121-
cur = conn_root.query('SHOW DATABASES LIKE "{}\_%%"'.format(PREFIX))
121+
cur = conn_root.query('SHOW DATABASES LIKE "{}\\_%%"'.format(PREFIX))
122122
for db in cur.fetchall():
123123
conn_root.query("DROP DATABASE `{}`".format(db[0]))
124124
conn_root.query("SET FOREIGN_KEY_CHECKS=1")

tests/test_declare.py

Lines changed: 324 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,324 @@
1+
import pytest
2+
from .schema import *
3+
import datajoint as dj
4+
import inspect
5+
from datajoint.declare import declare
6+
7+
8+
class TestDeclare:
9+
def test_schema_decorator(self, schema_any):
10+
assert issubclass(Subject, dj.Lookup)
11+
assert not issubclass(Subject, dj.Part)
12+
13+
def test_class_help(self, schema_any):
14+
help(TTest)
15+
help(TTest2)
16+
assert TTest.definition in TTest.__doc__
17+
assert TTest.definition in TTest2.__doc__
18+
19+
def test_instance_help(self, schema_any):
20+
help(TTest())
21+
help(TTest2())
22+
assert TTest().definition in TTest().__doc__
23+
assert TTest2().definition in TTest2().__doc__
24+
25+
def test_describe(self, schema_any):
26+
"""real_definition should match original definition"""
27+
rel = Experiment()
28+
context = inspect.currentframe().f_globals
29+
s1 = declare(rel.full_table_name, rel.definition, context)
30+
s2 = declare(rel.full_table_name, rel.describe(), context)
31+
assert s1 == s2
32+
33+
def test_describe_indexes(self, schema_any):
34+
"""real_definition should match original definition"""
35+
rel = IndexRich()
36+
context = inspect.currentframe().f_globals
37+
s1 = declare(rel.full_table_name, rel.definition, context)
38+
s2 = declare(rel.full_table_name, rel.describe(), context)
39+
assert s1 == s2
40+
41+
def test_describe_dependencies(self, schema_any):
42+
"""real_definition should match original definition"""
43+
rel = ThingC()
44+
context = inspect.currentframe().f_globals
45+
s1 = declare(rel.full_table_name, rel.definition, context)
46+
s2 = declare(rel.full_table_name, rel.describe(), context)
47+
assert s1 == s2
48+
49+
def test_part(self, schema_any):
50+
"""
51+
Lookup and part with the same name. See issue #365
52+
"""
53+
local_schema = dj.Schema(schema_any.database)
54+
55+
@local_schema
56+
class Type(dj.Lookup):
57+
definition = """
58+
type : varchar(255)
59+
"""
60+
contents = zip(("Type1", "Type2", "Type3"))
61+
62+
@local_schema
63+
class TypeMaster(dj.Manual):
64+
definition = """
65+
master_id : int
66+
"""
67+
68+
class Type(dj.Part):
69+
definition = """
70+
-> TypeMaster
71+
-> Type
72+
"""
73+
74+
def test_attributes(self, schema_any):
75+
"""
76+
Test autoincrement declaration
77+
"""
78+
auto = Auto()
79+
auto.fill()
80+
subject = Subject()
81+
experiment = Experiment()
82+
trial = Trial()
83+
ephys = Ephys()
84+
channel = Ephys.Channel()
85+
86+
assert auto.heading.names == ["id", "name"]
87+
assert auto.heading.attributes["id"].autoincrement
88+
89+
# test attribute declarations
90+
assert subject.heading.names == [
91+
"subject_id",
92+
"real_id",
93+
"species",
94+
"date_of_birth",
95+
"subject_notes",
96+
]
97+
assert subject.primary_key == ["subject_id"]
98+
assert subject.heading.attributes["subject_id"].numeric
99+
assert not subject.heading.attributes["real_id"].numeric
100+
101+
assert experiment.heading.names == [
102+
"subject_id",
103+
"experiment_id",
104+
"experiment_date",
105+
"username",
106+
"data_path",
107+
"notes",
108+
"entry_time",
109+
]
110+
assert experiment.primary_key == ["subject_id", "experiment_id"]
111+
112+
assert trial.heading.names == [ # tests issue #516
113+
"animal",
114+
"experiment_id",
115+
"trial_id",
116+
"start_time",
117+
]
118+
assert trial.primary_key == ["animal", "experiment_id", "trial_id"]
119+
120+
assert ephys.heading.names == [
121+
"animal",
122+
"experiment_id",
123+
"trial_id",
124+
"sampling_frequency",
125+
"duration",
126+
]
127+
assert ephys.primary_key == ["animal", "experiment_id", "trial_id"]
128+
129+
assert channel.heading.names == [
130+
"animal",
131+
"experiment_id",
132+
"trial_id",
133+
"channel",
134+
"voltage",
135+
"current",
136+
]
137+
assert channel.primary_key == ["animal", "experiment_id", "trial_id", "channel"]
138+
assert channel.heading.attributes["voltage"].is_blob
139+
140+
def test_dependencies(self, schema_any):
141+
user = User()
142+
subject = Subject()
143+
experiment = Experiment()
144+
trial = Trial()
145+
ephys = Ephys()
146+
channel = Ephys.Channel()
147+
148+
assert experiment.full_table_name in user.children(primary=False)
149+
assert set(experiment.parents(primary=False)) == {user.full_table_name}
150+
assert experiment.full_table_name in user.children(primary=False)
151+
assert set(experiment.parents(primary=False)) == {user.full_table_name}
152+
assert set(
153+
s.full_table_name
154+
for s in experiment.parents(primary=False, as_objects=True)
155+
) == {user.full_table_name}
156+
157+
assert experiment.full_table_name in subject.descendants()
158+
assert experiment.full_table_name in {
159+
s.full_table_name for s in subject.descendants(as_objects=True)
160+
}
161+
assert subject.full_table_name in experiment.ancestors()
162+
assert subject.full_table_name in {
163+
s.full_table_name for s in experiment.ancestors(as_objects=True)
164+
}
165+
166+
assert trial.full_table_name in experiment.descendants()
167+
assert trial.full_table_name in {
168+
s.full_table_name for s in experiment.descendants(as_objects=True)
169+
}
170+
assert experiment.full_table_name in trial.ancestors()
171+
assert experiment.full_table_name in {
172+
s.full_table_name for s in trial.ancestors(as_objects=True)
173+
}
174+
175+
assert set(trial.children(primary=True)) == {
176+
ephys.full_table_name,
177+
trial.Condition.full_table_name,
178+
}
179+
assert set(trial.parts()) == {trial.Condition.full_table_name}
180+
assert set(s.full_table_name for s in trial.parts(as_objects=True)) == {
181+
trial.Condition.full_table_name
182+
}
183+
assert set(ephys.parents(primary=True)) == {trial.full_table_name}
184+
assert set(
185+
s.full_table_name for s in ephys.parents(primary=True, as_objects=True)
186+
) == {trial.full_table_name}
187+
assert set(ephys.children(primary=True)) == {channel.full_table_name}
188+
assert set(
189+
s.full_table_name for s in ephys.children(primary=True, as_objects=True)
190+
) == {channel.full_table_name}
191+
assert set(channel.parents(primary=True)) == {ephys.full_table_name}
192+
assert set(
193+
s.full_table_name for s in channel.parents(primary=True, as_objects=True)
194+
) == {ephys.full_table_name}
195+
196+
def test_descendants_only_contain_part_table(self, schema_any):
197+
"""issue #927"""
198+
199+
class A(dj.Manual):
200+
definition = """
201+
a: int
202+
"""
203+
204+
class B(dj.Manual):
205+
definition = """
206+
-> A
207+
b: int
208+
"""
209+
210+
class Master(dj.Manual):
211+
definition = """
212+
table_master: int
213+
"""
214+
215+
class Part(dj.Part):
216+
definition = """
217+
-> master
218+
-> B
219+
"""
220+
221+
context = dict(A=A, B=B, Master=Master)
222+
schema_any(A, context=context)
223+
schema_any(B, context=context)
224+
schema_any(Master, context=context)
225+
assert A.descendants() == [
226+
"`djtest_test1`.`a`",
227+
"`djtest_test1`.`b`",
228+
"`djtest_test1`.`master__part`",
229+
]
230+
231+
def test_bad_attribute_name(self, schema_any):
232+
class BadName(dj.Manual):
233+
definition = """
234+
Bad_name : int
235+
"""
236+
237+
with pytest.raises(dj.DataJointError):
238+
schema_any(BadName)
239+
240+
def test_bad_fk_rename(self, schema_any):
241+
"""issue #381"""
242+
243+
class A(dj.Manual):
244+
definition = """
245+
a : int
246+
"""
247+
248+
class B(dj.Manual):
249+
definition = """
250+
b -> A # invalid, the new syntax is (b) -> A
251+
"""
252+
253+
schema_any(A)
254+
with pytest.raises(dj.DataJointError):
255+
schema_any(B)
256+
257+
def test_primary_nullable_foreign_key(self, schema_any):
258+
class Q(dj.Manual):
259+
definition = """
260+
-> [nullable] Experiment
261+
"""
262+
263+
with pytest.raises(dj.DataJointError):
264+
schema_any(Q)
265+
266+
def test_invalid_foreign_key_option(self, schema_any):
267+
class R(dj.Manual):
268+
definition = """
269+
-> Experiment
270+
----
271+
-> [optional] User
272+
"""
273+
274+
with pytest.raises(dj.DataJointError):
275+
schema_any(R)
276+
277+
def test_unsupported_datatype(self, schema_any):
278+
class Q(dj.Manual):
279+
definition = """
280+
experiment : int
281+
---
282+
description : text
283+
"""
284+
285+
with pytest.raises(dj.DataJointError):
286+
schema_any(Q)
287+
288+
def test_int_datatype(self, schema_any):
289+
@schema_any
290+
class Owner(dj.Manual):
291+
definition = """
292+
ownerid : int
293+
---
294+
car_count : integer
295+
"""
296+
297+
def test_unsupported_int_datatype(self, schema_any):
298+
class Driver(dj.Manual):
299+
definition = """
300+
driverid : tinyint
301+
---
302+
car_count : tinyinteger
303+
"""
304+
305+
with pytest.raises(dj.DataJointError):
306+
schema_any(Driver)
307+
308+
def test_long_table_name(self, schema_any):
309+
"""
310+
test issue #205 -- reject table names over 64 characters in length
311+
"""
312+
313+
class WhyWouldAnyoneCreateATableNameThisLong(dj.Manual):
314+
definition = """
315+
master : int
316+
"""
317+
318+
class WithSuchALongPartNameThatItCrashesMySQL(dj.Part):
319+
definition = """
320+
-> (master)
321+
"""
322+
323+
with pytest.raises(dj.DataJointError):
324+
schema_any(WhyWouldAnyoneCreateATableNameThisLong)

0 commit comments

Comments
 (0)