hatchet-sdk 1.17.1__py3-none-any.whl → 1.18.0__py3-none-any.whl
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.
Potentially problematic release.
This version of hatchet-sdk might be problematic. Click here for more details.
- hatchet_sdk/config.py +1 -0
- hatchet_sdk/features/stubs.py +99 -0
- hatchet_sdk/hatchet.py +5 -0
- hatchet_sdk/runnables/workflow.py +6 -0
- hatchet_sdk/worker/worker.py +18 -3
- {hatchet_sdk-1.17.1.dist-info → hatchet_sdk-1.18.0.dist-info}/METADATA +3 -3
- {hatchet_sdk-1.17.1.dist-info → hatchet_sdk-1.18.0.dist-info}/RECORD +9 -8
- {hatchet_sdk-1.17.1.dist-info → hatchet_sdk-1.18.0.dist-info}/WHEEL +0 -0
- {hatchet_sdk-1.17.1.dist-info → hatchet_sdk-1.18.0.dist-info}/entry_points.txt +0 -0
hatchet_sdk/config.py
CHANGED
|
@@ -86,6 +86,7 @@ class ClientConfig(BaseSettings):
|
|
|
86
86
|
disable_log_capture: bool = False
|
|
87
87
|
log_queue_size: int = 1000
|
|
88
88
|
grpc_enable_fork_support: bool = False
|
|
89
|
+
force_shutdown_on_shutdown_signal: bool = False
|
|
89
90
|
|
|
90
91
|
@model_validator(mode="after")
|
|
91
92
|
def validate_token_and_tenant(self) -> "ClientConfig":
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
from typing import TYPE_CHECKING, Any, overload
|
|
2
|
+
|
|
3
|
+
from hatchet_sdk.context.context import Context
|
|
4
|
+
from hatchet_sdk.runnables.types import EmptyModel, R, TWorkflowInput
|
|
5
|
+
from hatchet_sdk.runnables.workflow import Standalone, Workflow
|
|
6
|
+
|
|
7
|
+
if TYPE_CHECKING:
|
|
8
|
+
from hatchet_sdk import Hatchet
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class StubsClient:
|
|
12
|
+
def __init__(self, client: "Hatchet"):
|
|
13
|
+
self.client = client
|
|
14
|
+
|
|
15
|
+
@overload
|
|
16
|
+
def workflow(
|
|
17
|
+
self,
|
|
18
|
+
*,
|
|
19
|
+
name: str,
|
|
20
|
+
input_validator: None = None,
|
|
21
|
+
) -> Workflow[EmptyModel]: ...
|
|
22
|
+
|
|
23
|
+
@overload
|
|
24
|
+
def workflow(
|
|
25
|
+
self,
|
|
26
|
+
*,
|
|
27
|
+
name: str,
|
|
28
|
+
input_validator: type[TWorkflowInput],
|
|
29
|
+
) -> Workflow[TWorkflowInput]: ...
|
|
30
|
+
|
|
31
|
+
def workflow(
|
|
32
|
+
self,
|
|
33
|
+
*,
|
|
34
|
+
name: str,
|
|
35
|
+
input_validator: type[TWorkflowInput] | None = None,
|
|
36
|
+
) -> Workflow[EmptyModel] | Workflow[TWorkflowInput]:
|
|
37
|
+
return self.client.workflow(name=name, input_validator=input_validator)
|
|
38
|
+
|
|
39
|
+
@overload
|
|
40
|
+
def task(
|
|
41
|
+
self,
|
|
42
|
+
*,
|
|
43
|
+
name: str,
|
|
44
|
+
input_validator: None = None,
|
|
45
|
+
output_validator: None = None,
|
|
46
|
+
) -> Standalone[EmptyModel, EmptyModel]: ...
|
|
47
|
+
|
|
48
|
+
@overload
|
|
49
|
+
def task(
|
|
50
|
+
self,
|
|
51
|
+
*,
|
|
52
|
+
name: str,
|
|
53
|
+
input_validator: None = None,
|
|
54
|
+
output_validator: type[R],
|
|
55
|
+
) -> Standalone[EmptyModel, R]: ...
|
|
56
|
+
|
|
57
|
+
@overload
|
|
58
|
+
def task(
|
|
59
|
+
self,
|
|
60
|
+
*,
|
|
61
|
+
name: str,
|
|
62
|
+
input_validator: type[TWorkflowInput],
|
|
63
|
+
output_validator: None = None,
|
|
64
|
+
) -> Standalone[TWorkflowInput, EmptyModel]: ...
|
|
65
|
+
|
|
66
|
+
@overload
|
|
67
|
+
def task(
|
|
68
|
+
self,
|
|
69
|
+
*,
|
|
70
|
+
name: str,
|
|
71
|
+
input_validator: type[TWorkflowInput],
|
|
72
|
+
output_validator: type[R],
|
|
73
|
+
) -> Standalone[TWorkflowInput, R]: ...
|
|
74
|
+
|
|
75
|
+
def task(
|
|
76
|
+
self,
|
|
77
|
+
*,
|
|
78
|
+
name: str,
|
|
79
|
+
input_validator: type[TWorkflowInput] | None = None,
|
|
80
|
+
output_validator: type[R] | None = None,
|
|
81
|
+
) -> (
|
|
82
|
+
Standalone[EmptyModel, R]
|
|
83
|
+
| Standalone[TWorkflowInput, R]
|
|
84
|
+
| Standalone[EmptyModel, EmptyModel]
|
|
85
|
+
| Standalone[TWorkflowInput, EmptyModel]
|
|
86
|
+
):
|
|
87
|
+
def mock_func(input: Any, ctx: Context) -> Any:
|
|
88
|
+
raise NotImplementedError(
|
|
89
|
+
"This is a stub function and should not be called directly."
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
return_type = output_validator if output_validator is not None else EmptyModel
|
|
93
|
+
mock_func.__annotations__ = {
|
|
94
|
+
"input": Any,
|
|
95
|
+
"ctx": Context,
|
|
96
|
+
"return": return_type,
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return self.client.task(name=name, input_validator=input_validator)(mock_func)
|
hatchet_sdk/hatchet.py
CHANGED
|
@@ -20,6 +20,7 @@ from hatchet_sdk.features.metrics import MetricsClient
|
|
|
20
20
|
from hatchet_sdk.features.rate_limits import RateLimitsClient
|
|
21
21
|
from hatchet_sdk.features.runs import RunsClient
|
|
22
22
|
from hatchet_sdk.features.scheduled import ScheduledClient
|
|
23
|
+
from hatchet_sdk.features.stubs import StubsClient
|
|
23
24
|
from hatchet_sdk.features.workers import WorkersClient
|
|
24
25
|
from hatchet_sdk.features.workflows import WorkflowsClient
|
|
25
26
|
from hatchet_sdk.labels import DesiredWorkerLabel
|
|
@@ -156,6 +157,10 @@ class Hatchet:
|
|
|
156
157
|
def listener(self) -> RunEventListenerClient:
|
|
157
158
|
return self._client.listener
|
|
158
159
|
|
|
160
|
+
@property
|
|
161
|
+
def stubs(self) -> StubsClient:
|
|
162
|
+
return StubsClient(client=self)
|
|
163
|
+
|
|
159
164
|
@property
|
|
160
165
|
def config(self) -> ClientConfig:
|
|
161
166
|
return self._client.config
|
|
@@ -1406,6 +1406,7 @@ class Standalone(BaseWorkflow[TWorkflowInput], Generic[TWorkflowInput, R]):
|
|
|
1406
1406
|
parent_outputs: dict[str, JSONSerializableMapping] | None = None,
|
|
1407
1407
|
retry_count: int = 0,
|
|
1408
1408
|
lifespan: Any = None,
|
|
1409
|
+
dependencies: dict[str, Any] | None = None,
|
|
1409
1410
|
) -> R:
|
|
1410
1411
|
"""
|
|
1411
1412
|
Mimic the execution of a task. This method is intended to be used to unit test
|
|
@@ -1417,6 +1418,7 @@ class Standalone(BaseWorkflow[TWorkflowInput], Generic[TWorkflowInput, R]):
|
|
|
1417
1418
|
:param parent_outputs: Outputs from parent tasks, if any. This is useful for mimicking DAG functionality. For instance, if you have a task `step_2` that has a `parent` which is `step_1`, you can pass `parent_outputs={"step_1": {"result": "Hello, world!"}}` to `step_2.mock_run()` to be able to access `ctx.task_output(step_1)` in `step_2`.
|
|
1418
1419
|
:param retry_count: The number of times the task has been retried.
|
|
1419
1420
|
:param lifespan: The lifespan to be used in the task, which is useful if one was set on the worker. This will allow you to access `ctx.lifespan` inside of your task.
|
|
1421
|
+
:param dependencies: Dependencies to be injected into the task. This is useful for tasks that have dependencies defined using `Depends`. **IMPORTANT**: You must pass the dependencies _directly_, **not** the `Depends` objects themselves. For example, if you have a task that has a dependency `config: Annotated[str, Depends(get_config)]`, you should pass `dependencies={"config": "config_value"}` to `aio_mock_run`.
|
|
1420
1422
|
|
|
1421
1423
|
:return: The output of the task.
|
|
1422
1424
|
"""
|
|
@@ -1427,6 +1429,7 @@ class Standalone(BaseWorkflow[TWorkflowInput], Generic[TWorkflowInput, R]):
|
|
|
1427
1429
|
parent_outputs=parent_outputs,
|
|
1428
1430
|
retry_count=retry_count,
|
|
1429
1431
|
lifespan=lifespan,
|
|
1432
|
+
dependencies=dependencies,
|
|
1430
1433
|
)
|
|
1431
1434
|
|
|
1432
1435
|
async def aio_mock_run(
|
|
@@ -1436,6 +1439,7 @@ class Standalone(BaseWorkflow[TWorkflowInput], Generic[TWorkflowInput, R]):
|
|
|
1436
1439
|
parent_outputs: dict[str, JSONSerializableMapping] | None = None,
|
|
1437
1440
|
retry_count: int = 0,
|
|
1438
1441
|
lifespan: Any = None,
|
|
1442
|
+
dependencies: dict[str, Any] | None = None,
|
|
1439
1443
|
) -> R:
|
|
1440
1444
|
"""
|
|
1441
1445
|
Mimic the execution of a task. This method is intended to be used to unit test
|
|
@@ -1447,6 +1451,7 @@ class Standalone(BaseWorkflow[TWorkflowInput], Generic[TWorkflowInput, R]):
|
|
|
1447
1451
|
:param parent_outputs: Outputs from parent tasks, if any. This is useful for mimicking DAG functionality. For instance, if you have a task `step_2` that has a `parent` which is `step_1`, you can pass `parent_outputs={"step_1": {"result": "Hello, world!"}}` to `step_2.mock_run()` to be able to access `ctx.task_output(step_1)` in `step_2`.
|
|
1448
1452
|
:param retry_count: The number of times the task has been retried.
|
|
1449
1453
|
:param lifespan: The lifespan to be used in the task, which is useful if one was set on the worker. This will allow you to access `ctx.lifespan` inside of your task.
|
|
1454
|
+
:param dependencies: Dependencies to be injected into the task. This is useful for tasks that have dependencies defined using `Depends`. **IMPORTANT**: You must pass the dependencies _directly_, **not** the `Depends` objects themselves. For example, if you have a task that has a dependency `config: Annotated[str, Depends(get_config)]`, you should pass `dependencies={"config": "config_value"}` to `aio_mock_run`.
|
|
1450
1455
|
|
|
1451
1456
|
:return: The output of the task.
|
|
1452
1457
|
"""
|
|
@@ -1457,6 +1462,7 @@ class Standalone(BaseWorkflow[TWorkflowInput], Generic[TWorkflowInput, R]):
|
|
|
1457
1462
|
parent_outputs=parent_outputs,
|
|
1458
1463
|
retry_count=retry_count,
|
|
1459
1464
|
lifespan=lifespan,
|
|
1465
|
+
dependencies=dependencies,
|
|
1460
1466
|
)
|
|
1461
1467
|
|
|
1462
1468
|
@property
|
hatchet_sdk/worker/worker.py
CHANGED
|
@@ -405,8 +405,22 @@ class Worker:
|
|
|
405
405
|
logger.exception("error checking listener health")
|
|
406
406
|
|
|
407
407
|
def _setup_signal_handlers(self) -> None:
|
|
408
|
-
signal.signal(
|
|
409
|
-
|
|
408
|
+
signal.signal(
|
|
409
|
+
signal.SIGTERM,
|
|
410
|
+
(
|
|
411
|
+
self._handle_force_quit_signal
|
|
412
|
+
if self.config.force_shutdown_on_shutdown_signal
|
|
413
|
+
else self._handle_exit_signal
|
|
414
|
+
),
|
|
415
|
+
)
|
|
416
|
+
signal.signal(
|
|
417
|
+
signal.SIGINT,
|
|
418
|
+
(
|
|
419
|
+
self._handle_force_quit_signal
|
|
420
|
+
if self.config.force_shutdown_on_shutdown_signal
|
|
421
|
+
else self._handle_exit_signal
|
|
422
|
+
),
|
|
423
|
+
)
|
|
410
424
|
signal.signal(signal.SIGQUIT, self._handle_force_quit_signal)
|
|
411
425
|
|
|
412
426
|
def _handle_exit_signal(self, signum: int, frame: FrameType | None) -> None:
|
|
@@ -416,7 +430,8 @@ class Worker:
|
|
|
416
430
|
self.loop.create_task(self.exit_gracefully())
|
|
417
431
|
|
|
418
432
|
def _handle_force_quit_signal(self, signum: int, frame: FrameType | None) -> None:
|
|
419
|
-
|
|
433
|
+
signal_received = signal.Signals(signum).name
|
|
434
|
+
logger.info(f"received {signal_received}...")
|
|
420
435
|
if self.loop:
|
|
421
436
|
self.loop.create_task(self._exit_forcefully())
|
|
422
437
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: hatchet-sdk
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.18.0
|
|
4
4
|
Summary:
|
|
5
5
|
License: MIT
|
|
6
6
|
Author: Alexander Belanger
|
|
@@ -12,9 +12,9 @@ Classifier: Programming Language :: Python :: 3.10
|
|
|
12
12
|
Classifier: Programming Language :: Python :: 3.11
|
|
13
13
|
Classifier: Programming Language :: Python :: 3.12
|
|
14
14
|
Provides-Extra: otel
|
|
15
|
+
Provides-Extra: v0
|
|
15
16
|
Requires-Dist: aiohttp (>=3.10.5,<4.0.0)
|
|
16
|
-
Requires-Dist:
|
|
17
|
-
Requires-Dist: aiostream (>=0.5.2,<0.6.0)
|
|
17
|
+
Requires-Dist: cel-python (>=0.4.0,<0.5.0) ; extra == "v0"
|
|
18
18
|
Requires-Dist: grpcio (>=1.64.1,!=1.68.*) ; python_version < "3.13"
|
|
19
19
|
Requires-Dist: grpcio (>=1.69.0) ; python_version >= "3.13"
|
|
20
20
|
Requires-Dist: grpcio-tools (>=1.64.1,!=1.68.*) ; python_version < "3.13"
|
|
@@ -258,7 +258,7 @@ hatchet_sdk/clients/rest/rest.py,sha256=zZHTzgl-NBdcK6XhG23m_s9RKRONGPPItzGe407s
|
|
|
258
258
|
hatchet_sdk/clients/rest/tenacity_utils.py,sha256=WeNt_1ah2-NKB9qTI3JnTjItpSviBV95U0cPM4kB5as,1211
|
|
259
259
|
hatchet_sdk/clients/v1/api_client.py,sha256=vUaQr7Xi71a2kFHkZy-pB3tCg3-t0ROlqbPUQA6skIA,2013
|
|
260
260
|
hatchet_sdk/conditions.py,sha256=CnhpkXgVXM3wc0kAX8KZQA6tp8NFAbdzAN2xFbw7Hb0,4522
|
|
261
|
-
hatchet_sdk/config.py,sha256=
|
|
261
|
+
hatchet_sdk/config.py,sha256=QVHFVPmqNxc7PFb2Mvll1BGDEmIo9h587N44W7KoYxE,5349
|
|
262
262
|
hatchet_sdk/connection.py,sha256=XCBY9-UxaN3blakgZ59AhDpjb1ilLOOlmNNM6QaDtMM,2961
|
|
263
263
|
hatchet_sdk/context/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
264
264
|
hatchet_sdk/context/context.py,sha256=KE-GsaosBar8USXSj1lkWHdsZXfXFf6tI9RwGTOF-aM,16278
|
|
@@ -290,10 +290,11 @@ hatchet_sdk/features/metrics.py,sha256=do4kVX6cjDszHocc-IoS8BdT5ChptPc39oElbW6Cd
|
|
|
290
290
|
hatchet_sdk/features/rate_limits.py,sha256=eh55Z3w75cYUthqTyoWmNxj_6tN3rjebMKm3of-vxv0,2155
|
|
291
291
|
hatchet_sdk/features/runs.py,sha256=u0KEcLOLSWusgyp8T4z30yR9UxSdz9CdyrGxM9SSr-g,23758
|
|
292
292
|
hatchet_sdk/features/scheduled.py,sha256=t7YA9CoJrzBhH82ChTSFWaTF_dyoC9i1O_wf9ywsphc,8939
|
|
293
|
+
hatchet_sdk/features/stubs.py,sha256=5NF43cgZKzh7qzYv_lLae4Xkh_zrz2wMj8M_OoTAAF8,2604
|
|
293
294
|
hatchet_sdk/features/tenant.py,sha256=xkhh5mRKCWbunk_S1iBmGR-DYR-F4mjxk8jLyYUyzNE,886
|
|
294
295
|
hatchet_sdk/features/workers.py,sha256=DVdno28RmtlfhMJUkaPcOMHNKXCPV0RFrXtLqV6zWyE,2600
|
|
295
296
|
hatchet_sdk/features/workflows.py,sha256=WTt58imAFRrEEB3M5hEEIBwNtrzdWbITFpgtsIqJNSM,4770
|
|
296
|
-
hatchet_sdk/hatchet.py,sha256=
|
|
297
|
+
hatchet_sdk/hatchet.py,sha256=v4V7_jHy5cYYFGM2nvrjmuu979i59KuDDRZZUyW8Eis,26558
|
|
297
298
|
hatchet_sdk/labels.py,sha256=nATgxWE3lFxRTnfISEpoIRLGbMfAZsHF4lZTuG4Mfic,182
|
|
298
299
|
hatchet_sdk/logger.py,sha256=5uOr52T4mImSQm1QvWT8HvZFK5WfPNh3Y1cBQZRFgUQ,333
|
|
299
300
|
hatchet_sdk/metadata.py,sha256=XkRbhnghJJGCdVvF-uzyGBcNaTqpeQ3uiQvNNP1wyBc,107
|
|
@@ -304,7 +305,7 @@ hatchet_sdk/runnables/action.py,sha256=zrVHpyzIQ9XZgWwY69b_6uhZd53An4trRoLd9b3os
|
|
|
304
305
|
hatchet_sdk/runnables/contextvars.py,sha256=jHrrewUlFPAT9f2u3VCsuSlDBtBoagEUtUzJOSmm4yk,1118
|
|
305
306
|
hatchet_sdk/runnables/task.py,sha256=JsiDBkYQVJodyqtNDT9z8Pwz3ePL8GhY0Z1-ptPw9ms,16030
|
|
306
307
|
hatchet_sdk/runnables/types.py,sha256=M23xSMTBPl12CXCCXZ0wbnqZ_sePB6CJKtOdipiNDlg,4362
|
|
307
|
-
hatchet_sdk/runnables/workflow.py,sha256
|
|
308
|
+
hatchet_sdk/runnables/workflow.py,sha256=-oz0q76N-NAi3Xon1VXkzDvZe0ZjbXR_O-3sTCGfokk,58876
|
|
308
309
|
hatchet_sdk/token.py,sha256=KjIiInwG5Kqd_FO4BSW1x_5Uc7PFbnzIVJqr50-ZldE,779
|
|
309
310
|
hatchet_sdk/utils/aio.py,sha256=cu1rD_UZkShtfzi7iXMYwBBaCRdxJQTdUC0_mf8nU2E,499
|
|
310
311
|
hatchet_sdk/utils/backoff.py,sha256=6B5Rb5nLKw_TqqgpJMYjIBV1PTTtbOMRZCveisVhg_I,353
|
|
@@ -540,9 +541,9 @@ hatchet_sdk/worker/action_listener_process.py,sha256=CzXen-7tFG_rryvM2xWV2_KMUFC
|
|
|
540
541
|
hatchet_sdk/worker/runner/run_loop_manager.py,sha256=BcdfxSvZdrxbeTZSUASwCTMKJe6pwLorHVKPTprkM2k,4176
|
|
541
542
|
hatchet_sdk/worker/runner/runner.py,sha256=QULD00hEyW2dcHCcH46C1k7mxr5nHEwtusyAs33VOO0,22857
|
|
542
543
|
hatchet_sdk/worker/runner/utils/capture_logs.py,sha256=hNELuNHS0HmoMZJ7F7yIjZuahPEx9cOx9JZro618W74,4675
|
|
543
|
-
hatchet_sdk/worker/worker.py,sha256=
|
|
544
|
+
hatchet_sdk/worker/worker.py,sha256=BP8A70hQxNvJ8VG8Osb5NTE4mwdcmEkiLwdtwkkNbuE,16868
|
|
544
545
|
hatchet_sdk/workflow_run.py,sha256=KcylcqRwKADtnzOTjoiVr1vdr7qTZFtDeD5aRS6A4Y8,2823
|
|
545
|
-
hatchet_sdk-1.
|
|
546
|
-
hatchet_sdk-1.
|
|
547
|
-
hatchet_sdk-1.
|
|
548
|
-
hatchet_sdk-1.
|
|
546
|
+
hatchet_sdk-1.18.0.dist-info/METADATA,sha256=tRyt8eMKJTTZlPu_Hp0nhrvabcnRywZjMLjAcxTh_Js,3575
|
|
547
|
+
hatchet_sdk-1.18.0.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
|
|
548
|
+
hatchet_sdk-1.18.0.dist-info/entry_points.txt,sha256=Un_76pcLse-ZGBlwebhQpnTPyQrripeHW8J7qmEpGOk,1400
|
|
549
|
+
hatchet_sdk-1.18.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|