Coverage for tests/test_project.py: 100%
109 statements
« prev ^ index » next coverage.py v7.16.2, created at 2026-10-01 22:07 +0000
« prev ^ index » next coverage.py v7.16.2, created at 2026-10-01 22:07 +0000
1import numpy as np
2import peprs
3import pytest
5from pepdbagent.exceptions import ProjectNotFoundError
7from .utils import (
8 PEPDBAgentContextManager,
9 get_path_to_example_file,
10 list_of_available_peps,
11)
14@pytest.mark.skipif(
15 not PEPDBAgentContextManager().db_setup(),
16 reason="DB is not setup",
17)
18class TestProject:
19 """
20 Test project methods
21 """
23 def test_create_project(self):
24 with PEPDBAgentContextManager(add_data=False) as agent:
25 prj = peprs.Project(list_of_available_peps()["namespace3"]["subtables"])
26 agent.project.create(prj, namespace="test", name="imply", overwrite=False)
27 assert True
29 def test_create_project_from_dict(self):
30 with PEPDBAgentContextManager(add_data=False) as agent:
31 prj = peprs.Project(list_of_available_peps()["namespace3"]["subtables"])
32 agent.project.create(
33 prj.to_dict(raw=True, by_sample=True),
34 namespace="test",
35 name="imply",
36 overwrite=True,
37 )
38 assert True
40 @pytest.mark.parametrize(
41 "namespace, name",
42 [
43 ["namespace1", "amendments1"],
44 ["namespace1", "amendments2"],
45 ["namespace1", "basic"],
46 ["namespace2", "derive"],
47 ["namespace2", "imply"],
48 ["namespace3", "piface"],
49 ["namespace3", "subtable2"],
50 ],
51 )
52 def test_get_project(self, namespace, name):
53 with PEPDBAgentContextManager(add_data=True) as agent:
54 kk = agent.project.get(
55 namespace=namespace, name=name, tag="default", raw=True
56 )
57 ff = peprs.Project(get_path_to_example_file(namespace, name)).to_dict(
58 raw=True, by_sample=True
59 )
60 # pepdbagent always sets the registry name on the stored config,
61 # overriding any name in the file (which may be empty or different).
62 ff["config"]["name"] = name
63 assert kk["config"] == ff["config"]
64 assert kk["samples"] == ff["samples"]
65 assert kk.get("subsamples", []) == ff.get("subsamples", [])
67 @pytest.mark.parametrize(
68 "namespace, name",
69 [
70 ["namespace1", "amendments1"],
71 ],
72 )
73 def test_get_config(self, namespace, name):
74 with PEPDBAgentContextManager(add_data=True) as agent:
75 description = ""
76 kk = agent.project.get_config(
77 namespace=namespace,
78 name=name,
79 tag="default",
80 )
81 ff = peprs.Project(get_path_to_example_file(namespace, name))
82 expected_config = ff.config.copy()
83 expected_config["description"] = description
84 expected_config["name"] = name
85 assert kk == expected_config
87 @pytest.mark.parametrize(
88 "namespace, name",
89 [
90 ["namespace3", "subtables"],
91 ],
92 )
93 def test_get_subsamples(self, namespace, name):
94 with PEPDBAgentContextManager(add_data=True) as agent:
95 prj_subtables = agent.project.get_subsamples(
96 namespace=namespace,
97 name=name,
98 tag="default",
99 )
100 orgiginal_prj = peprs.Project(get_path_to_example_file(namespace, name))
102 assert (
103 prj_subtables
104 == orgiginal_prj.to_dict(raw=True, by_sample=True)["subsamples"]
105 )
107 @pytest.mark.parametrize(
108 "namespace, name",
109 [
110 ["namespace3", "subtables"],
111 ],
112 )
113 def test_get_samples_raw(self, namespace, name):
114 with PEPDBAgentContextManager(add_data=True) as agent:
115 prj_samples = agent.project.get_samples(
116 namespace=namespace, name=name, tag="default", raw=True
117 )
118 orgiginal_prj = peprs.Project(get_path_to_example_file(namespace, name))
120 assert (
121 prj_samples
122 == orgiginal_prj.to_dict(raw=True, by_sample=True)["samples"]
123 )
125 @pytest.mark.parametrize(
126 "namespace, name",
127 [
128 ["namespace3", "subtables"],
129 ],
130 )
131 def test_get_samples_processed(self, namespace, name):
132 with PEPDBAgentContextManager(add_data=True) as agent:
133 prj_samples = agent.project.get_samples(
134 namespace=namespace,
135 name=name,
136 tag="default",
137 raw=False,
138 )
139 orgiginal_prj = peprs.Project(get_path_to_example_file(namespace, name))
140 expected = (
141 orgiginal_prj.to_pandas()
142 .replace({np.nan: None})
143 .to_dict(orient="records")
144 )
146 # Normalize numpy arrays (used for subsample list columns) to plain lists
147 # so dict equality works without raising "truth value is ambiguous".
148 def _normalize(samples):
149 return [
150 {
151 k: (v.tolist() if isinstance(v, np.ndarray) else v)
152 for k, v in s.items()
153 }
154 for s in samples
155 ]
157 assert _normalize(prj_samples) == _normalize(expected)
159 @pytest.mark.parametrize(
160 "namespace, name,tag",
161 [
162 ["incorrect_namespace", "amendments1", "default"],
163 ["namespace1", "subtable2", "default"],
164 ["namespace3", "basic", "default"],
165 ["namespace3", "subtable2", "incorrect_tag"],
166 ["namespace1", "incorrect_name", "default"],
167 ],
168 )
169 def test_get_project_error(self, namespace, name, tag):
170 with PEPDBAgentContextManager(add_data=True) as agent:
171 with pytest.raises(ProjectNotFoundError, match="Project does not exist."):
172 agent.project.get(namespace=namespace, name=name, tag=tag)
174 @pytest.mark.parametrize(
175 "namespace, name",
176 [
177 ["namespace1", "amendments1"],
178 ["namespace1", "amendments2"],
179 ["namespace2", "derive"],
180 ["namespace2", "imply"],
181 ],
182 )
183 def test_overwrite_project(self, namespace, name):
184 with PEPDBAgentContextManager(add_data=True) as agent:
185 new_prj = agent.project.get(namespace="namespace1", name="basic", raw=False)
187 agent.project.create(
188 project=new_prj,
189 namespace=namespace,
190 name=name,
191 tag="default",
192 overwrite=True,
193 )
195 assert (
196 agent.project.get(namespace=namespace, name=name, raw=False) == new_prj
197 )
199 @pytest.mark.parametrize(
200 "namespace, name",
201 [
202 ["namespace1", "amendments1"],
203 ["namespace2", "derive"],
204 ],
205 )
206 def test_delete_project(self, namespace, name):
207 with PEPDBAgentContextManager(add_data=True) as agent:
208 agent.project.delete(namespace=namespace, name=name, tag="default")
210 with pytest.raises(ProjectNotFoundError, match="Project does not exist."):
211 agent.project.get(namespace=namespace, name=name, tag="default")
213 def test_delete_not_existing_project(self):
214 with PEPDBAgentContextManager(add_data=True) as agent:
215 with pytest.raises(ProjectNotFoundError, match="Project does not exist."):
216 agent.project.delete(
217 namespace="namespace1", name="nothing", tag="default"
218 )
220 @pytest.mark.parametrize(
221 "namespace, name",
222 [
223 ["namespace1", "amendments2"],
224 ["namespace2", "derive"],
225 ["namespace2", "imply"],
226 ],
227 )
228 def test_fork_projects(self, namespace, name):
229 with PEPDBAgentContextManager(add_data=True) as agent:
230 agent.project.fork(
231 original_namespace=namespace,
232 original_name=name,
233 original_tag="default",
234 fork_namespace="new_namespace",
235 fork_name="new_name",
236 fork_tag="new_tag",
237 )
239 assert agent.project.exists(
240 namespace="new_namespace", name="new_name", tag="new_tag"
241 )
242 result = agent.annotation.get(
243 namespace="new_namespace", name="new_name", tag="new_tag"
244 )
245 assert result.results[0].forked_from == f"{namespace}/{name}:default"
247 @pytest.mark.parametrize(
248 "namespace, name",
249 [
250 ["namespace1", "amendments1"],
251 ["namespace1", "amendments2"],
252 ],
253 )
254 def test_parent_project_delete(self, namespace, name):
255 """
256 Test if parent project is deleted, forked project is not deleted
257 """
258 with PEPDBAgentContextManager(add_data=True) as agent:
259 agent.project.fork(
260 original_namespace=namespace,
261 original_name=name,
262 original_tag="default",
263 fork_namespace="new_namespace",
264 fork_name="new_name",
265 fork_tag="new_tag",
266 )
268 assert agent.project.exists(
269 namespace="new_namespace", name="new_name", tag="new_tag"
270 )
271 agent.project.delete(namespace=namespace, name=name, tag="default")
272 assert agent.project.exists(
273 namespace="new_namespace", name="new_name", tag="new_tag"
274 )
276 @pytest.mark.parametrize(
277 "namespace, name",
278 [
279 ["namespace1", "amendments1"],
280 ["namespace1", "amendments2"],
281 ],
282 )
283 def test_child_project_delete(self, namespace, name):
284 """
285 Test if child project is deleted, parent project is not deleted
286 """
287 with PEPDBAgentContextManager(add_data=True) as agent:
288 agent.project.fork(
289 original_namespace=namespace,
290 original_name=name,
291 original_tag="default",
292 fork_namespace="new_namespace",
293 fork_name="new_name",
294 fork_tag="new_tag",
295 )
297 assert agent.project.exists(
298 namespace="new_namespace", name="new_name", tag="new_tag"
299 )
300 assert agent.project.exists(namespace=namespace, name=name, tag="default")
301 agent.project.delete(
302 namespace="new_namespace", name="new_name", tag="new_tag"
303 )
304 assert agent.project.exists(namespace=namespace, name=name, tag="default")
306 @pytest.mark.parametrize(
307 "namespace, name",
308 [
309 ["namespace1", "amendments1"],
310 ["namespace1", "amendments2"],
311 ],
312 )
313 def test_project_can_be_forked_twice(self, namespace, name):
314 """
315 Test if project can be forked twice
316 """
317 with PEPDBAgentContextManager(add_data=True) as agent:
318 agent.project.fork(
319 original_namespace=namespace,
320 original_name=name,
321 original_tag="default",
322 fork_namespace="new_namespace",
323 fork_name="new_name",
324 fork_tag="new_tag",
325 )
326 agent.project.fork(
327 original_namespace=namespace,
328 original_name=name,
329 original_tag="default",
330 fork_namespace="new_namespace2",
331 fork_name="new_name2",
332 fork_tag="new_tag2",
333 )
335 result = agent.annotation.get(
336 namespace="new_namespace", name="new_name", tag="new_tag"
337 )
338 assert result.results[0].forked_from == f"{namespace}/{name}:default"
340 result = agent.annotation.get(
341 namespace="new_namespace2", name="new_name2", tag="new_tag2"
342 )
343 assert result.results[0].forked_from == f"{namespace}/{name}:default"