Skip to content

Commit b2ee3a8

Browse files
Add Project and Task Operations (#1294)
* wip add required routes for updates, deletions and creations. * wip update api client. * wip Fix typechecking issues. * Add tests for project and update cassettes. * wip TaskType operations. * wip update tasktype class. * Fix some tests. * Update tests. * Add tests and task_type operations. * Changelog and task operations. * Add tests for update and delete task. * format and lint.k * update command for task list. * Update docstrings and parameters for settings. * Add markdown extension for collapsed boxes. --------- Co-authored-by: Tom Herold <[email protected]>
1 parent 42463fa commit b2ee3a8

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+11637
-3060
lines changed

docs/mkdocs.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ markdown_extensions:
109109
- attr_list
110110
- md_in_html
111111
- footnotes
112+
- pymdownx.details
112113
- pymdownx.highlight
113114
- pymdownx.inlinehilite
114115
- pymdownx.superfences

webknossos/Changelog.md

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,22 @@ For upgrade instructions, please check the respective _Breaking Changes_ section
1515
### Breaking Changes
1616

1717
### Added
18+
- Added operations for `Project`, `Task` and `TaskType` classes and objects: [#1294](https://github.com/scalableminds/webknossos-libs/pull/1294)
19+
- Added operations for `Project` class:
20+
- `Project.create()` for creating a new project.
21+
- `my_project.delete()` to delete a project object
22+
- Added `my_project.update()` to update `priority`, `expected_time` and `is_blacklisted_from_report` values of an existing project object.
23+
- Added operations for `TaskType` class:
24+
- `TaskType.get_list()` to get all `TaskType` objects.
25+
- `TaskType.get_by_id()` to get a `TaskType` by id.
26+
- `TaskType.get_by_name()` to get a `TaskType` by name.
27+
- `TaskType.create()` to create a new `TaskType`.
28+
- Added operations `my_task_type.delete()` method for `TaskType` objects.
29+
- Added `Task.get_list()`to get all `Task` objects.
30+
- Added operations for `Task` objects:
31+
- `my_task.update()` to update a `Task` object.
32+
- `my_task.delete()` to delete a `Task` object.
33+
- Added `TaskExperience` class to store domain and value pair.
1834

1935
### Changed
2036

@@ -87,7 +103,6 @@ For upgrade instructions, please check the respective _Breaking Changes_ section
87103
- Fixed an issue that creates an Error when `add_mag()` was called just with a `chunk_shape`. [#1315](https://github.com/scalableminds/webknossos-libs/pull/1315)
88104

89105

90-
91106
## [2.3.8](https://github.com/scalableminds/webknossos-libs/releases/tag/v2.3.8) - 2025-05-28
92107
[Commits](https://github.com/scalableminds/webknossos-libs/compare/v2.3.7...v2.3.8)
93108

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
import pytest
2+
3+
import webknossos as wk
4+
5+
pytestmark = [pytest.mark.use_proxay]
6+
7+
8+
def test_get_project() -> None:
9+
teams = wk.Team.get_list()
10+
11+
project = wk.Project.create(
12+
name="test_get_project",
13+
priority=1,
14+
paused=False,
15+
expected_time=1234,
16+
team=teams[0],
17+
is_blacklisted_from_report=False,
18+
)
19+
project_by_name = wk.Project.get_by_name(project.name)
20+
assert project_by_name == project
21+
project_by_id = wk.Project.get_by_id(project.project_id)
22+
assert project_by_id == project
23+
24+
25+
def test_project_create() -> None:
26+
"""Test creating a project."""
27+
28+
teams = wk.Team.get_list()
29+
30+
project = wk.Project.create(
31+
name="test_create_project",
32+
priority=1,
33+
paused=False,
34+
expected_time=1234,
35+
team=teams[0],
36+
is_blacklisted_from_report=False,
37+
)
38+
assert project.name == "test_create_project"
39+
assert project.priority == 1
40+
assert project.paused is False
41+
assert project.expected_time == 1234
42+
assert project.team_id == teams[0].id
43+
assert project.is_blacklisted_from_report is False
44+
assert project.owner_id == wk.User.get_current_user().user_id
45+
46+
47+
def test_project_update() -> None:
48+
"""Test updating a project."""
49+
teams = wk.Team.get_list()
50+
51+
project = wk.Project.create(
52+
name="test_update_project",
53+
priority=1,
54+
paused=False,
55+
expected_time=1234,
56+
team=teams[0],
57+
is_blacklisted_from_report=False,
58+
)
59+
project = project.update(
60+
priority=2,
61+
expected_time=5678,
62+
is_blacklisted_from_report=True,
63+
)
64+
assert project.priority == 2
65+
assert project.expected_time == 5678
66+
assert project.is_blacklisted_from_report is True
67+
68+
69+
def test_project_delete() -> None:
70+
"""Test deleting a project."""
71+
teams = wk.Team.get_list()
72+
73+
project = wk.Project.create(
74+
name="test_delete_project",
75+
priority=1,
76+
paused=False,
77+
expected_time=1234,
78+
team=teams[0],
79+
is_blacklisted_from_report=False,
80+
)
81+
project.delete()
82+
with pytest.raises(Exception):
83+
wk.Project.get_by_name("test_delete_project")
84+
85+
86+
def test_project_get_owner() -> None:
87+
"""Test getting the owner of a project."""
88+
teams = wk.Team.get_list()
89+
90+
project = wk.Project.create(
91+
name="test_get_owner_project",
92+
priority=1,
93+
paused=False,
94+
expected_time=1234,
95+
team=teams[0],
96+
is_blacklisted_from_report=False,
97+
)
98+
owner = project.get_owner()
99+
assert owner.user_id == wk.User.get_current_user().user_id
100+
101+
102+
def test_project_get_tasks() -> None:
103+
"""Test getting the task of a project."""
104+
teams = wk.Team.get_list()
105+
ds_id = wk.Dataset.open_remote("l4_sample")._dataset_id
106+
107+
project = wk.Project.create(
108+
name="test_get_task_project",
109+
priority=1,
110+
paused=False,
111+
expected_time=1234,
112+
team=teams[0].id,
113+
is_blacklisted_from_report=False,
114+
)
115+
task_type = wk.TaskType.create(
116+
name="test_task_type",
117+
description="test_task_type_description",
118+
team=teams[0].name,
119+
tracing_type="volume",
120+
)
121+
for i in range(3):
122+
wk.Task.create(
123+
task_type_id=task_type.task_type_id,
124+
project_name=project.name,
125+
needed_experience_domain="test_domain",
126+
needed_experience_value=3,
127+
starting_position=wk.Vec3Int(0, 0, 0),
128+
dataset_id=ds_id,
129+
)
130+
131+
assert len(project.get_tasks()) == 3
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
from collections.abc import Iterator
2+
3+
import pytest
4+
5+
import webknossos as wk
6+
from webknossos.client.api_client.errors import UnexpectedStatusError
7+
8+
pytestmark = [pytest.mark.use_proxay]
9+
10+
TEST_PROJECT_NAME = "test_project"
11+
TEST_TASK_TYPE_NAME = "test_task_type"
12+
13+
14+
@pytest.fixture(autouse=True)
15+
def setup_task_type_and_project() -> Iterator[None]:
16+
team = wk.Team.get_list()[0]
17+
task_type = wk.TaskType.create(
18+
name="test_task_type",
19+
description="This is a test task type",
20+
team=team,
21+
tracing_type="volume",
22+
)
23+
project = wk.Project.create(
24+
name=TEST_PROJECT_NAME,
25+
priority=1,
26+
paused=False,
27+
expected_time=1234,
28+
team=team,
29+
is_blacklisted_from_report=False,
30+
)
31+
yield
32+
task_type.delete()
33+
project.delete()
34+
35+
36+
def test_get_task() -> None:
37+
tasks = wk.Task.create(
38+
task_type_id=wk.TaskType.get_by_name(TEST_TASK_TYPE_NAME).task_type_id,
39+
project_name=TEST_PROJECT_NAME,
40+
needed_experience_domain="testing",
41+
needed_experience_value=0,
42+
starting_position=wk.Vec3Int(0, 0, 0),
43+
dataset_id=wk.Dataset.open_remote("l4_sample")._dataset_id,
44+
)
45+
task_by_id = wk.Task.get_by_id(tasks[0].task_id)
46+
assert task_by_id == tasks[0]
47+
48+
49+
def test_task_get_project() -> None:
50+
tasks = wk.Task.create(
51+
task_type_id=wk.TaskType.get_by_name(TEST_TASK_TYPE_NAME).task_type_id,
52+
project_name=TEST_PROJECT_NAME,
53+
needed_experience_domain="testing",
54+
needed_experience_value=0,
55+
starting_position=wk.Vec3Int(0, 0, 0),
56+
dataset_id=wk.Dataset.open_remote("l4_sample")._dataset_id,
57+
)
58+
project = tasks[0].get_project()
59+
assert project.name == TEST_PROJECT_NAME
60+
61+
62+
def test_get_task_type() -> None:
63+
task_type_by_name = wk.TaskType.get_by_name(TEST_TASK_TYPE_NAME)
64+
assert task_type_by_name.name == TEST_TASK_TYPE_NAME
65+
66+
task_type_by_id = wk.TaskType.get_by_id(task_type_by_name.task_type_id)
67+
assert task_type_by_id == task_type_by_name
68+
69+
70+
def test_update_task() -> None:
71+
tasks = wk.Task.create(
72+
task_type_id=wk.TaskType.get_by_name(TEST_TASK_TYPE_NAME).task_type_id,
73+
project_name=TEST_PROJECT_NAME,
74+
needed_experience_domain="testing",
75+
needed_experience_value=0,
76+
starting_position=wk.Vec3Int(0, 0, 0),
77+
dataset_id=wk.Dataset.open_remote("l4_sample")._dataset_id,
78+
)
79+
task = tasks[0]
80+
updated = task.update(
81+
remaining_instances=4,
82+
)
83+
assert updated.status.pending_instance_count == 4
84+
85+
86+
def test_delete_task() -> None:
87+
tasks = wk.Task.create(
88+
task_type_id=wk.TaskType.get_by_name(TEST_TASK_TYPE_NAME).task_type_id,
89+
project_name=TEST_PROJECT_NAME,
90+
needed_experience_domain="testing",
91+
needed_experience_value=0,
92+
starting_position=wk.Vec3Int(0, 0, 0),
93+
dataset_id=wk.Dataset.open_remote("l4_sample")._dataset_id,
94+
)
95+
task = tasks[0]
96+
task.delete()
97+
with pytest.raises(UnexpectedStatusError):
98+
wk.Task.get_by_id(
99+
task.task_id
100+
) # Should raise KeyError since the task is deleted
101+
102+
103+
def test_task_list() -> None:
104+
tasks = wk.Task.create(
105+
task_type_id=wk.TaskType.get_by_name(TEST_TASK_TYPE_NAME).task_type_id,
106+
project_name=TEST_PROJECT_NAME,
107+
needed_experience_domain="testing",
108+
needed_experience_value=0,
109+
starting_position=wk.Vec3Int(0, 0, 0),
110+
dataset_id=wk.Dataset.open_remote("l4_sample")._dataset_id,
111+
)
112+
task_list = wk.Task.get_list()
113+
assert len(task_list) > 0
114+
assert tasks[0] in task_list

webknossos/tests/cassettes/test_annotation/test_annotation_upload_download_roundtrip.yml

Lines changed: 93 additions & 125 deletions
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)