datashare-python 0.2.13__tar.gz → 0.2.14__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. {datashare_python-0.2.13 → datashare_python-0.2.14}/PKG-INFO +1 -1
  2. {datashare_python-0.2.13 → datashare_python-0.2.14}/pyproject.toml +4 -2
  3. datashare_python-0.2.13/tests/__init__.py +0 -0
  4. datashare_python-0.2.13/tests/cli/test_project.py +0 -23
  5. datashare_python-0.2.13/tests/cli/test_tasks.py +0 -241
  6. datashare_python-0.2.13/tests/cli/test_worker.py +0 -46
  7. datashare_python-0.2.13/tests/conftest.py +0 -14
  8. datashare_python-0.2.13/tests/test_discovery.py +0 -44
  9. datashare_python-0.2.13/tests/test_object.py +0 -28
  10. datashare_python-0.2.13/tests/test_task_client.py +0 -242
  11. datashare_python-0.2.13/tests/test_template.py +0 -40
  12. datashare_python-0.2.13/tests/test_utils.py +0 -17
  13. datashare_python-0.2.13/tests/test_worker.py +0 -68
  14. datashare_python-0.2.13/uv.lock +0 -2381
  15. {datashare_python-0.2.13 → datashare_python-0.2.14}/.gitignore +0 -0
  16. {datashare_python-0.2.13 → datashare_python-0.2.14}/README.md +0 -0
  17. {datashare_python-0.2.13 → datashare_python-0.2.14}/datashare_python/.gitignore +0 -0
  18. {datashare_python-0.2.13 → datashare_python-0.2.14}/datashare_python/__init__.py +0 -0
  19. {datashare_python-0.2.13 → datashare_python-0.2.14}/datashare_python/__main__.py +0 -0
  20. {datashare_python-0.2.13 → datashare_python-0.2.14}/datashare_python/cli/__init__.py +0 -0
  21. {datashare_python-0.2.13 → datashare_python-0.2.14}/datashare_python/cli/local.py +0 -0
  22. {datashare_python-0.2.13 → datashare_python-0.2.14}/datashare_python/cli/project.py +0 -0
  23. {datashare_python-0.2.13 → datashare_python-0.2.14}/datashare_python/cli/task.py +0 -0
  24. {datashare_python-0.2.13 → datashare_python-0.2.14}/datashare_python/cli/utils.py +0 -0
  25. {datashare_python-0.2.13 → datashare_python-0.2.14}/datashare_python/cli/worker.py +0 -0
  26. {datashare_python-0.2.13 → datashare_python-0.2.14}/datashare_python/config.py +0 -0
  27. {datashare_python-0.2.13 → datashare_python-0.2.14}/datashare_python/conftest.py +0 -0
  28. {datashare_python-0.2.13 → datashare_python-0.2.14}/datashare_python/constants.py +0 -0
  29. {datashare_python-0.2.13 → datashare_python-0.2.14}/datashare_python/dependencies.py +0 -0
  30. {datashare_python-0.2.13 → datashare_python-0.2.14}/datashare_python/discovery.py +0 -0
  31. {datashare_python-0.2.13 → datashare_python-0.2.14}/datashare_python/exceptions.py +0 -0
  32. {datashare_python-0.2.13 → datashare_python-0.2.14}/datashare_python/local_client.py +0 -0
  33. {datashare_python-0.2.13 → datashare_python-0.2.14}/datashare_python/objects.py +0 -0
  34. {datashare_python-0.2.13 → datashare_python-0.2.14}/datashare_python/task_client.py +0 -0
  35. {datashare_python-0.2.13 → datashare_python-0.2.14}/datashare_python/template.py +0 -0
  36. {datashare_python-0.2.13 → datashare_python-0.2.14}/datashare_python/types_.py +0 -0
  37. {datashare_python-0.2.13 → datashare_python-0.2.14}/datashare_python/utils.py +0 -0
  38. {datashare_python-0.2.13 → datashare_python-0.2.14}/datashare_python/worker.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: datashare-python
3
- Version: 0.2.13
3
+ Version: 0.2.14
4
4
  Summary: Manage Python tasks and local resources in Datashare
5
5
  Project-URL: Homepage, https://icij.github.io/datashare-python/
6
6
  Project-URL: Documentation, https://icij.github.io/datashare-python/
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "datashare-python"
3
- version = "0.2.13"
3
+ version = "0.2.14"
4
4
  description = "Manage Python tasks and local resources in Datashare"
5
5
  authors = [
6
6
  { name = "Clément Doumouro", email = "cdoumouro@icij.org" },
@@ -35,13 +35,15 @@ datashare-python = "datashare_python.__main__:main"
35
35
  [build-system]
36
36
  requires = ["hatchling"]
37
37
  build-backend = "hatchling.build"
38
- package = ["datashare_python"]
39
38
 
40
39
  [tool.hatch.build.targets.wheel]
41
40
  artifacts = [
42
41
  "worker-template.tar.gz"
43
42
  ]
44
43
 
44
+ [tool.hatch.build.targets.sdist]
45
+ only-include = ["datashare_python"]
46
+
45
47
  [tool.uv]
46
48
  package = true
47
49
 
File without changes
@@ -1,23 +0,0 @@
1
- from pathlib import Path
2
-
3
- from datashare_python.cli import cli_app
4
- from typer.testing import CliRunner
5
-
6
-
7
- async def test_init_project(
8
- typer_asyncio_patch, # noqa: ANN001, ARG001
9
- local_template_build, # noqa: ANN001, ARG001
10
- tmp_path: Path,
11
- ) -> None:
12
- # Given
13
- runner = CliRunner(mix_stderr=False)
14
- test_worker_project = "test-project"
15
- # When
16
- args = ["project", "init", str(test_worker_project), "-p", str(tmp_path)]
17
- result = runner.invoke(
18
- cli_app,
19
- args,
20
- catch_exceptions=False,
21
- )
22
- # Then
23
- assert result.exit_code == 0
@@ -1,241 +0,0 @@
1
- import logging
2
- from contextlib import AbstractAsyncContextManager
3
- from datetime import UTC, datetime
4
- from typing import Any, Self
5
- from unittest.mock import AsyncMock, MagicMock
6
-
7
- import click
8
- from _pytest.logging import LogCaptureFixture
9
- from _pytest.monkeypatch import MonkeyPatch
10
- from datashare_python.cli import cli_app
11
- from datashare_python.cli import task as cli_task
12
- from datashare_python.objects import StacktraceItem, Task, TaskError, TaskState
13
- from packaging.version import Version
14
- from typer.testing import CliRunner
15
-
16
- BUGGED_CLICK_VERSION = Version("8.1.8")
17
- CLICK_VERSION = Version(click.__version__)
18
-
19
-
20
- async def test_task_create_task(
21
- monkeypatch: MonkeyPatch,
22
- typer_asyncio_patch, # noqa: ANN001, ARG001
23
- caplog: LogCaptureFixture,
24
- ) -> None:
25
- # Given
26
- mock_client_fn = MagicMock()
27
- mock_client = AsyncMock()
28
- task_id = "hello_world-some-id"
29
- mock_client.create_task.return_value = task_id
30
- mock_client_fn.return_value = mock_client
31
-
32
- class MockedClient:
33
- def __init__(self, datashare_url: str, api_key: str | None = None) -> None: # noqa: ARG002
34
- ...
35
-
36
- async def __aenter__(self) -> Self:
37
- return self
38
-
39
- async def __aexit__(self, exc_type, exc_val, exc_tb): ... # noqa: ANN001
40
-
41
- async def create_task(
42
- self, # noqa: ANN001, ARG001
43
- name: str, # noqa: ARG001, ARG002
44
- args: dict[str, Any], # noqa: ARG001, ARG002
45
- *,
46
- id_: str | None = None, # noqa: ARG001, ARG002
47
- group: str | None = None, # noqa: ARG001, ARG002
48
- ) -> str:
49
- return task_id
50
-
51
- monkeypatch.setattr(cli_task, "DatashareTaskClient", MockedClient)
52
- # When
53
- runner = CliRunner(mix_stderr=False)
54
- with caplog.at_level(logging.INFO):
55
- result = runner.invoke(
56
- cli_app, ["task", "start", "hello_world"], catch_exceptions=False
57
- )
58
- # Then
59
- assert result.exit_code == 0
60
- assert result.stdout == task_id + "\n"
61
- assert ("Task(hello_world-some-id) started" in r for r in caplog.records)
62
- assert ("Task(hello_world-some-id) 🛫" in r for r in caplog.records)
63
-
64
-
65
- async def test_task_watch(
66
- monkeypatch: MonkeyPatch,
67
- typer_asyncio_patch, # noqa: ANN001, ARG001
68
- ) -> None:
69
- # Given
70
- task_id = "hello_world-some-id"
71
- created_at = datetime.now(UTC)
72
-
73
- states = [
74
- Task(
75
- id=task_id,
76
- name="hello_world",
77
- progress=0,
78
- state=TaskState.CREATED,
79
- created_at=created_at,
80
- ),
81
- Task(
82
- id=task_id,
83
- name="hello_world",
84
- progress=0,
85
- state=TaskState.QUEUED,
86
- created_at=created_at,
87
- ),
88
- Task(
89
- id=task_id,
90
- name="hello_world",
91
- progress=0,
92
- state=TaskState.RUNNING,
93
- created_at=created_at,
94
- ),
95
- Task(
96
- id=task_id,
97
- name="hello_world",
98
- progress=0.5,
99
- state=TaskState.RUNNING,
100
- created_at=created_at,
101
- ),
102
- Task(
103
- id=task_id,
104
- name="hello_world",
105
- progress=0.99,
106
- state=TaskState.RUNNING,
107
- created_at=created_at,
108
- ),
109
- Task(
110
- id=task_id,
111
- name="hello_world",
112
- progress=1.0,
113
- state=TaskState.DONE,
114
- completed_at=datetime.now(UTC),
115
- created_at=created_at,
116
- ),
117
- ]
118
-
119
- class MockedClient(AbstractAsyncContextManager):
120
- def __init__(self, datashare_url: str, api_key: str | None = None) -> None: # noqa: ARG002
121
- self._state_it = None
122
-
123
- async def get_task(self, task_id: str) -> Task: # noqa: ARG002
124
- return next(self._state_it)
125
-
126
- async def __aenter__(self) -> Self:
127
- self._state_it = iter(states)
128
- return self
129
-
130
- async def __aexit__(self, exc_type, exc_val, exc_tb): ... # noqa: ANN001
131
-
132
- monkeypatch.setattr(cli_task, "DatashareTaskClient", MockedClient)
133
- # When
134
- runner = CliRunner(mix_stderr=False)
135
- result = runner.invoke(
136
- cli_app, ["task", "watch", task_id, "-p", 0.001], catch_exceptions=False
137
- )
138
- # Then
139
- assert result.exit_code == 0
140
- assert result.stdout.endswith(task_id + "\n")
141
- assert "Task(hello_world-some-id) 🛫" in result.stderr
142
- if CLICK_VERSION > BUGGED_CLICK_VERSION:
143
- assert "Task(hello_world-some-id) 🛬" in result.stderr
144
- assert "Task(hello_world-some-id) ✅" in result.stderr
145
- assert "1.0" in result.stderr
146
-
147
-
148
- async def test_task_watch_error(
149
- monkeypatch: MonkeyPatch,
150
- typer_asyncio_patch, # noqa: ANN001, ARG001
151
- ) -> None:
152
- # Given
153
- mock_client_fn = MagicMock()
154
- mock_client = AsyncMock()
155
- task_id = "hello_world-some-id"
156
- mock_client_fn.return_value = mock_client
157
- created_at = datetime.now(UTC)
158
-
159
- class MockedClient(AbstractAsyncContextManager):
160
- def __init__(self, datashare_url: str, api_key: str | None = None) -> None: # noqa: ARG002
161
- self._state_it = None
162
-
163
- async def __aenter__(self) -> Self:
164
- return self
165
-
166
- async def __aexit__(self, exc_type, exc_val, exc_tb): ... # noqa: ANN001
167
-
168
- async def get_task(self, task_id: str) -> Task: # noqa: ARG002
169
- return Task(
170
- id=task_id,
171
- name="hello_world",
172
- progress=0,
173
- state=TaskState.ERROR,
174
- created_at=created_at,
175
- )
176
-
177
- async def get_task_error(self, task_id: str) -> TaskError: # noqa: ARG002
178
- return TaskError(
179
- name="SomeError",
180
- message="some error occurred",
181
- stacktrace=[
182
- StacktraceItem(name="some_func", file="some_file.py", lineno=666)
183
- ],
184
- )
185
-
186
- monkeypatch.setattr(cli_task, "DatashareTaskClient", MockedClient)
187
- # When
188
- runner = CliRunner(mix_stderr=False)
189
- result = runner.invoke(
190
- cli_app, ["task", "watch", task_id, "-p", 0.001], catch_exceptions=False
191
- )
192
- # Then
193
- assert result.exit_code == 1
194
- if CLICK_VERSION > BUGGED_CLICK_VERSION:
195
- assert (
196
- "Task(hello_world-some-id) failed with the following error:"
197
- in result.stderr
198
- )
199
- assert "Task(hello_world-some-id) ❌" in result.stderr
200
-
201
-
202
- async def test_task_watch_cancelled(
203
- monkeypatch: MonkeyPatch,
204
- typer_asyncio_patch, # noqa: ANN001, ARG001
205
- ) -> None:
206
- # Given
207
- mock_client_fn = MagicMock()
208
- mock_client = AsyncMock()
209
- task_id = "hello_world-some-id"
210
- mock_client_fn.return_value = mock_client
211
- created_at = datetime.now(UTC)
212
-
213
- class MockedClient(AbstractAsyncContextManager):
214
- def __init__(self, datashare_url: str, api_key: str | None = None) -> None: # noqa: ARG002
215
- self._state_it = None
216
-
217
- async def __aenter__(self) -> Self:
218
- return self
219
-
220
- async def __aexit__(self, exc_type, exc_val, exc_tb): ... # noqa: ANN001
221
-
222
- async def get_task(self, task_id: str) -> Task: # noqa: ARG002
223
- return Task(
224
- id=task_id,
225
- name="hello_world",
226
- progress=0,
227
- state=TaskState.CANCELLED,
228
- created_at=created_at,
229
- )
230
-
231
- monkeypatch.setattr(cli_task, "DatashareTaskClient", MockedClient)
232
- # When
233
- runner = CliRunner(mix_stderr=False)
234
- result = runner.invoke(
235
- cli_app, ["task", "watch", task_id, "-p", 0.001], catch_exceptions=False
236
- )
237
- # Then
238
- assert result.exit_code == 1
239
- if CLICK_VERSION > BUGGED_CLICK_VERSION:
240
- assert "Task(hello_world-some-id) was cancelled" in result.stderr
241
- assert "Task(hello_world-some-id) 🛑" in result.stderr
@@ -1,46 +0,0 @@
1
- from _pytest.capture import CaptureFixture
2
- from _pytest.monkeypatch import MonkeyPatch
3
- from datashare_python.cli import cli_app
4
- from temporalio.worker import Worker
5
- from typer.testing import CliRunner
6
-
7
-
8
- async def _mock_worker_run(self) -> None: # noqa: ANN001
9
- pass
10
-
11
-
12
- async def test_start_workers(
13
- worker_lifetime_deps, # noqa: ANN001, ARG001
14
- typer_asyncio_patch, # noqa: ANN001, ARG001
15
- monkeypatch: MonkeyPatch,
16
- capsys: CaptureFixture[str],
17
- ) -> None:
18
- # Given
19
- runner = CliRunner(mix_stderr=False)
20
- monkeypatch.setattr(Worker, "run", _mock_worker_run)
21
- with capsys.disabled():
22
- # When
23
- result = runner.invoke(
24
- cli_app,
25
- [
26
- "worker",
27
- "start",
28
- "--queue",
29
- "cpu",
30
- "--activities",
31
- "ping",
32
- "--activities",
33
- "create-translation-batches",
34
- "--workflows",
35
- "ping",
36
- "--temporal-address",
37
- "localhost:7233",
38
- ],
39
- catch_exceptions=False,
40
- )
41
- # Then
42
- assert result.exit_code == 0
43
- expected = """Starting datashare worker running:
44
- - 1 workflow: ping
45
- - 1 activity: create-translation-batches"""
46
- assert expected in result.stderr
@@ -1,14 +0,0 @@
1
- import pytest # noqa: I001
2
- import nest_asyncio
3
- from datashare_python.conftest import * # noqa: F403
4
- from datashare_python.template import build_template_tarball
5
-
6
-
7
- @pytest.fixture # noqa: F405
8
- def typer_asyncio_patch() -> None:
9
- nest_asyncio.apply()
10
-
11
-
12
- @pytest.fixture(scope="session")
13
- def local_template_build() -> None:
14
- build_template_tarball()
@@ -1,44 +0,0 @@
1
- import pytest
2
- from datashare_python.discovery import discover_activities, discover_workflows
3
-
4
-
5
- @pytest.mark.parametrize(
6
- ("names", "expected_workflows"),
7
- [
8
- ([], {"ping", "translate-and-classify"}),
9
- (["ping", "translate-and-classify"], {"ping", "translate-and-classify"}),
10
- (["ping"], {"ping"}),
11
- (["pi.*"], {"ping"}),
12
- (["pong"], set()),
13
- ],
14
- )
15
- def test_discover_workflows(names: list[str], expected_workflows: set[str]) -> None:
16
- # When
17
- workflows = {wf_name for wf_name, _ in discover_workflows(names)}
18
- # Then
19
- assert workflows == expected_workflows
20
-
21
-
22
- @pytest.mark.parametrize(
23
- ("names", "expected_activities"),
24
- [
25
- (
26
- [],
27
- {
28
- "classify-docs",
29
- "create-classification-batches",
30
- "create-translation-batches",
31
- "pong",
32
- "translate-docs",
33
- },
34
- ),
35
- (["translate-docs"], {"translate-docs"}),
36
- ([".*transl.*"], {"create-translation-batches", "translate-docs"}),
37
- (["idontexist"], set()),
38
- ],
39
- )
40
- def test_discover_activities(names: list[str], expected_activities: set[str]) -> None:
41
- # When
42
- activities = {act_name for act_name, _ in discover_activities(names)}
43
- # Then
44
- assert activities == expected_activities
@@ -1,28 +0,0 @@
1
- from datetime import datetime
2
-
3
- from datashare_python.objects import Task, TaskState
4
-
5
-
6
- def test_task_ser() -> None:
7
- # Given
8
- task = Task(id="some_id", name="some_name", args=dict())
9
-
10
- # When
11
- serialized = task.model_dump()
12
-
13
- # Then
14
- assert isinstance(serialized.pop("createdAt"), datetime)
15
- expected = {
16
- "@type": "Task",
17
- "args": {},
18
- "completedAt": None,
19
- "error": None,
20
- "id": "some_id",
21
- "maxRetries": None,
22
- "name": "some_name",
23
- "progress": None,
24
- "result": None,
25
- "retriesLeft": None,
26
- "state": TaskState.CREATED,
27
- }
28
- assert serialized == expected
@@ -1,242 +0,0 @@
1
- import uuid
2
- from collections.abc import AsyncGenerator
3
- from contextlib import asynccontextmanager
4
- from datetime import UTC, datetime
5
- from typing import Any
6
- from unittest.mock import AsyncMock
7
-
8
- from _pytest.monkeypatch import MonkeyPatch
9
- from aiohttp.typedefs import StrOrURL
10
- from datashare_python.objects import (
11
- StacktraceItem,
12
- Task,
13
- TaskError,
14
- TaskResult,
15
- TaskState,
16
- User,
17
- )
18
- from datashare_python.task_client import AiohttpClient, DatashareTaskClient
19
-
20
-
21
- async def test_task_client_create_task(monkeypatch: MonkeyPatch) -> None:
22
- # Given
23
- datashare_url = "http://some-url"
24
- user = User(id="user")
25
- api_key = "some-api-key"
26
- auth = (user, api_key)
27
- task_name = "hello"
28
- task_id = f"{task_name}-{uuid.uuid4()}"
29
- args = {"greeted": "world"}
30
- group = "PYTHON"
31
-
32
- @asynccontextmanager
33
- async def _put_and_assert(
34
- _, # noqa: ANN001
35
- url: StrOrURL,
36
- *,
37
- data: Any = None,
38
- **kwargs: Any,
39
- ) -> AsyncGenerator[AsyncMock, None]:
40
- assert url == f"/api/task/{task_id}?group={group}"
41
- expected_task = {
42
- "@type": "Task",
43
- "id": task_id,
44
- "state": "CREATED",
45
- "name": "hello",
46
- "args": {
47
- "greeted": "world",
48
- "user": {
49
- "@type": "org.icij.datashare.user.User",
50
- "details": {},
51
- "id": "user",
52
- },
53
- },
54
- }
55
- assert data is None
56
- json_data = kwargs.pop("json")
57
- assert not kwargs
58
- assert isinstance(json_data.pop("createdAt", None), str)
59
- assert json_data == expected_task
60
- mocked_res = AsyncMock()
61
- mocked_res.json.return_value = {"taskId": task_id}
62
- yield mocked_res
63
-
64
- monkeypatch.setattr(AiohttpClient, "_put", _put_and_assert)
65
-
66
- task_client = DatashareTaskClient(datashare_url, auth=auth)
67
- async with task_client:
68
- # When
69
- t_id = await task_client.create_task(task_name, args, id_=task_id, group=group)
70
- assert t_id == task_id
71
-
72
-
73
- async def test_task_client_get_task(monkeypatch: MonkeyPatch) -> None:
74
- # Given
75
- datashare_url = "http://some-url"
76
- user = User(id="user")
77
- api_key = "some-api-key"
78
- auth = (user, api_key)
79
- task_name = "hello"
80
- task_id = f"{task_name}-{uuid.uuid4()}"
81
-
82
- @asynccontextmanager
83
- async def _get_and_assert(
84
- _, # noqa: ANN001
85
- url: StrOrURL,
86
- *,
87
- allow_redirects: bool = True,
88
- **kwargs: Any,
89
- ) -> AsyncGenerator[AsyncMock, None]:
90
- assert url == f"/api/task/{task_id}"
91
- task_ = {
92
- "@type": "Task",
93
- "id": task_id,
94
- "state": "CREATED",
95
- "createdAt": datetime.now(UTC),
96
- "name": "hello",
97
- "args": {"greeted": "world"},
98
- }
99
- assert allow_redirects
100
- assert not kwargs
101
- mocked_res = AsyncMock()
102
- mocked_res.json.return_value = task_
103
- yield mocked_res
104
-
105
- monkeypatch.setattr(AiohttpClient, "_get", _get_and_assert)
106
-
107
- task_client = DatashareTaskClient(datashare_url, auth=auth)
108
- async with task_client:
109
- # When
110
- task = await task_client.get_task(task_id)
111
- assert isinstance(task, Task)
112
-
113
-
114
- async def test_task_client_get_task_state(monkeypatch: MonkeyPatch) -> None:
115
- # Given
116
- datashare_url = "http://some-url"
117
- user = User(id="user")
118
- api_key = "some-api-key"
119
- auth = (user, api_key)
120
- task_name = "hello"
121
- task_id = f"{task_name}-{uuid.uuid4()}"
122
-
123
- @asynccontextmanager
124
- async def _get_and_assert(
125
- _, # noqa: ANN001
126
- url: StrOrURL,
127
- *,
128
- allow_redirects: bool = True,
129
- **kwargs: Any,
130
- ) -> AsyncGenerator[AsyncMock, None]:
131
- assert url == f"/api/task/{task_id}"
132
- task = {
133
- "@type": "Task",
134
- "id": task_id,
135
- "state": "DONE",
136
- "createdAt": datetime.now(UTC),
137
- "completedAt": datetime.now(UTC),
138
- "name": "hello",
139
- "args": {"greeted": "world"},
140
- "result": TaskResult(value="hellow"),
141
- }
142
- assert allow_redirects
143
- assert not kwargs
144
- mocked_res = AsyncMock()
145
- mocked_res.json.return_value = task
146
- yield mocked_res
147
-
148
- monkeypatch.setattr(AiohttpClient, "_get", _get_and_assert)
149
-
150
- task_client = DatashareTaskClient(datashare_url, auth=auth)
151
- async with task_client:
152
- # When
153
- res = await task_client.get_task_state(task_id)
154
- assert res == TaskState.DONE
155
-
156
-
157
- async def test_task_client_get_task_result(monkeypatch: MonkeyPatch) -> None:
158
- # Given
159
- datashare_url = "http://some-url"
160
- user = User(id="user")
161
- api_key = "some-api-key"
162
- auth = (user, api_key)
163
- task_name = "hello"
164
- task_id = f"{task_name}-{uuid.uuid4()}"
165
-
166
- @asynccontextmanager
167
- async def _get_and_assert(
168
- _, # noqa: ANN001
169
- url: StrOrURL,
170
- *,
171
- allow_redirects: bool = True,
172
- **kwargs: Any,
173
- ) -> AsyncGenerator[AsyncMock, None]:
174
- assert url == f"/api/task/{task_id}/result"
175
- assert allow_redirects
176
- assert not kwargs
177
- mocked_res = AsyncMock()
178
- mocked_res.json.return_value = "hellow world"
179
- yield mocked_res
180
-
181
- monkeypatch.setattr(AiohttpClient, "_get", _get_and_assert)
182
-
183
- task_client = DatashareTaskClient(datashare_url, auth=auth)
184
- async with task_client:
185
- # When
186
- res = await task_client.get_task_result(task_id)
187
- assert res == "hellow world"
188
-
189
-
190
- async def test_task_client_get_task_error(monkeypatch: MonkeyPatch) -> None:
191
- # Given
192
- datashare_url = "http://some-url"
193
- user = User(id="user")
194
- api_key = "some-api-key"
195
- auth = (user, api_key)
196
- task_name = "hello"
197
- task_id = f"{task_name}-{uuid.uuid4()}"
198
-
199
- @asynccontextmanager
200
- async def _get_and_assert(
201
- _, # noqa: ANN001
202
- url: StrOrURL,
203
- *,
204
- allow_redirects: bool = True,
205
- **kwargs: Any,
206
- ) -> AsyncGenerator[AsyncMock, None]:
207
- assert url == f"/api/task/{task_id}"
208
- task = {
209
- "@type": "Task",
210
- "id": task_id,
211
- "state": "ERROR",
212
- "createdAt": datetime.now(UTC),
213
- "completedAt": datetime.now(UTC),
214
- "name": "hello",
215
- "args": {"greeted": "world"},
216
- "error": {
217
- "@type": "TaskError",
218
- "name": "SomeError",
219
- "message": "some error found",
220
- "cause": "i'm the culprit",
221
- "stacktrace": [{"lineno": 666, "file": "some_file.py", "name": "err"}],
222
- },
223
- }
224
- assert allow_redirects
225
- assert not kwargs
226
- mocked_res = AsyncMock()
227
- mocked_res.json.return_value = task
228
- yield mocked_res
229
-
230
- monkeypatch.setattr(AiohttpClient, "_get", _get_and_assert)
231
-
232
- task_client = DatashareTaskClient(datashare_url, auth=auth)
233
- async with task_client:
234
- # When
235
- error = await task_client.get_task_error(task_id)
236
- expected_error = TaskError(
237
- name="SomeError",
238
- message="some error found",
239
- cause="i'm the culprit",
240
- stacktrace=[StacktraceItem(name="err", file="some_file.py", lineno=666)],
241
- )
242
- assert error == expected_error