mirror of
https://github.com/hatchet-dev/hatchet.git
synced 2026-02-17 21:59:05 -06:00
[Python] Feat: Dependency Injection, Improved error handling (#2067)
* feat: first pass at dependency injection * feat: add DI example + tests * feat: finish up tests * feat: docs * chore: gen * chore: lint * chore: changelog + ver * fix: split up paragraphs * refactor: improve impl * chore: gen * feat: inject input + ctx into deps * chore: gen * [Python] Feat: More use of `logger.exception` (#2069) * feat: add more instances of `logger.exception` * chore: ver * chore: changelog * fix: one more error log * chore: gen * chore: gen * chore: lint * fix: improve shutdown * chore: changelog * unwind: exit handler * feat: task run error * feat: improve error serde with more context * chore: changelog * fix: changelog * chore: gen * fix: rm celpy + lark dep, casing issues * chore: changelog * fix: respect log levels over the API * fix: changelog * refactor: rename log forwarder * fix: circular import
This commit is contained in:
@@ -0,0 +1,49 @@
|
||||
import pytest
|
||||
|
||||
from examples.dependency_injection.worker import (
|
||||
ASYNC_DEPENDENCY_VALUE,
|
||||
SYNC_DEPENDENCY_VALUE,
|
||||
Output,
|
||||
async_dep,
|
||||
async_task_with_dependencies,
|
||||
di_workflow,
|
||||
durable_async_task_with_dependencies,
|
||||
durable_sync_task_with_dependencies,
|
||||
sync_dep,
|
||||
sync_task_with_dependencies,
|
||||
)
|
||||
from hatchet_sdk import EmptyModel
|
||||
from hatchet_sdk.runnables.workflow import Standalone
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"task",
|
||||
[
|
||||
async_task_with_dependencies,
|
||||
sync_task_with_dependencies,
|
||||
durable_async_task_with_dependencies,
|
||||
durable_sync_task_with_dependencies,
|
||||
],
|
||||
)
|
||||
@pytest.mark.asyncio(loop_scope="session")
|
||||
async def test_di_standalones(
|
||||
task: Standalone[EmptyModel, Output],
|
||||
) -> None:
|
||||
result = await task.aio_run()
|
||||
|
||||
assert isinstance(result, Output)
|
||||
assert result.sync_dep == SYNC_DEPENDENCY_VALUE
|
||||
assert result.async_dep == ASYNC_DEPENDENCY_VALUE
|
||||
|
||||
|
||||
@pytest.mark.asyncio(loop_scope="session")
|
||||
async def test_di_workflows() -> None:
|
||||
result = await di_workflow.aio_run()
|
||||
|
||||
assert len(result) == 4
|
||||
|
||||
for output in result.values():
|
||||
parsed = Output.model_validate(output)
|
||||
|
||||
assert parsed.sync_dep == SYNC_DEPENDENCY_VALUE
|
||||
assert parsed.async_dep == ASYNC_DEPENDENCY_VALUE
|
||||
159
examples/python/dependency_injection/worker.py
Normal file
159
examples/python/dependency_injection/worker.py
Normal file
@@ -0,0 +1,159 @@
|
||||
# > Simple
|
||||
|
||||
from typing import Annotated
|
||||
|
||||
from pydantic import BaseModel
|
||||
|
||||
from hatchet_sdk import Context, Depends, DurableContext, EmptyModel, Hatchet
|
||||
|
||||
hatchet = Hatchet(debug=False)
|
||||
|
||||
SYNC_DEPENDENCY_VALUE = "sync_dependency_value"
|
||||
ASYNC_DEPENDENCY_VALUE = "async_dependency_value"
|
||||
|
||||
|
||||
# > Declare dependencies
|
||||
async def async_dep(input: EmptyModel, ctx: Context) -> str:
|
||||
return ASYNC_DEPENDENCY_VALUE
|
||||
|
||||
|
||||
def sync_dep(input: EmptyModel, ctx: Context) -> str:
|
||||
return SYNC_DEPENDENCY_VALUE
|
||||
|
||||
|
||||
|
||||
|
||||
class Output(BaseModel):
|
||||
sync_dep: str
|
||||
async_dep: str
|
||||
|
||||
|
||||
# > Inject dependencies
|
||||
@hatchet.task()
|
||||
async def async_task_with_dependencies(
|
||||
_i: EmptyModel,
|
||||
ctx: Context,
|
||||
async_dep: Annotated[str, Depends(async_dep)],
|
||||
sync_dep: Annotated[str, Depends(sync_dep)],
|
||||
) -> Output:
|
||||
return Output(
|
||||
sync_dep=sync_dep,
|
||||
async_dep=async_dep,
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
||||
@hatchet.task()
|
||||
def sync_task_with_dependencies(
|
||||
_i: EmptyModel,
|
||||
ctx: Context,
|
||||
async_dep: Annotated[str, Depends(async_dep)],
|
||||
sync_dep: Annotated[str, Depends(sync_dep)],
|
||||
) -> Output:
|
||||
return Output(
|
||||
sync_dep=sync_dep,
|
||||
async_dep=async_dep,
|
||||
)
|
||||
|
||||
|
||||
@hatchet.durable_task()
|
||||
async def durable_async_task_with_dependencies(
|
||||
_i: EmptyModel,
|
||||
ctx: DurableContext,
|
||||
async_dep: Annotated[str, Depends(async_dep)],
|
||||
sync_dep: Annotated[str, Depends(sync_dep)],
|
||||
) -> Output:
|
||||
return Output(
|
||||
sync_dep=sync_dep,
|
||||
async_dep=async_dep,
|
||||
)
|
||||
|
||||
|
||||
@hatchet.durable_task()
|
||||
def durable_sync_task_with_dependencies(
|
||||
_i: EmptyModel,
|
||||
ctx: DurableContext,
|
||||
async_dep: Annotated[str, Depends(async_dep)],
|
||||
sync_dep: Annotated[str, Depends(sync_dep)],
|
||||
) -> Output:
|
||||
return Output(
|
||||
sync_dep=sync_dep,
|
||||
async_dep=async_dep,
|
||||
)
|
||||
|
||||
|
||||
di_workflow = hatchet.workflow(
|
||||
name="dependency-injection-workflow",
|
||||
)
|
||||
|
||||
|
||||
@di_workflow.task()
|
||||
async def wf_async_task_with_dependencies(
|
||||
_i: EmptyModel,
|
||||
ctx: Context,
|
||||
async_dep: Annotated[str, Depends(async_dep)],
|
||||
sync_dep: Annotated[str, Depends(sync_dep)],
|
||||
) -> Output:
|
||||
return Output(
|
||||
sync_dep=sync_dep,
|
||||
async_dep=async_dep,
|
||||
)
|
||||
|
||||
|
||||
@di_workflow.task()
|
||||
def wf_sync_task_with_dependencies(
|
||||
_i: EmptyModel,
|
||||
ctx: Context,
|
||||
async_dep: Annotated[str, Depends(async_dep)],
|
||||
sync_dep: Annotated[str, Depends(sync_dep)],
|
||||
) -> Output:
|
||||
return Output(
|
||||
sync_dep=sync_dep,
|
||||
async_dep=async_dep,
|
||||
)
|
||||
|
||||
|
||||
@di_workflow.durable_task()
|
||||
async def wf_durable_async_task_with_dependencies(
|
||||
_i: EmptyModel,
|
||||
ctx: DurableContext,
|
||||
async_dep: Annotated[str, Depends(async_dep)],
|
||||
sync_dep: Annotated[str, Depends(sync_dep)],
|
||||
) -> Output:
|
||||
return Output(
|
||||
sync_dep=sync_dep,
|
||||
async_dep=async_dep,
|
||||
)
|
||||
|
||||
|
||||
@di_workflow.durable_task()
|
||||
def wf_durable_sync_task_with_dependencies(
|
||||
_i: EmptyModel,
|
||||
ctx: DurableContext,
|
||||
async_dep: Annotated[str, Depends(async_dep)],
|
||||
sync_dep: Annotated[str, Depends(sync_dep)],
|
||||
) -> Output:
|
||||
return Output(
|
||||
sync_dep=sync_dep,
|
||||
async_dep=async_dep,
|
||||
)
|
||||
|
||||
|
||||
def main() -> None:
|
||||
worker = hatchet.worker(
|
||||
"dependency-injection-worker",
|
||||
workflows=[
|
||||
async_task_with_dependencies,
|
||||
sync_task_with_dependencies,
|
||||
durable_async_task_with_dependencies,
|
||||
durable_sync_task_with_dependencies,
|
||||
di_workflow,
|
||||
],
|
||||
)
|
||||
worker.start()
|
||||
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -71,4 +71,4 @@ async def test_durable_sleep_cancel_replay(hatchet: Hatchet) -> None:
|
||||
second_sleep_result = await first_sleep.aio_result()
|
||||
|
||||
"""We've already slept for a little bit by the time the task is cancelled"""
|
||||
assert second_sleep_result["runtime"] < SLEEP_TIME
|
||||
assert second_sleep_result["runtime"] <= SLEEP_TIME
|
||||
|
||||
@@ -2,8 +2,9 @@ import json
|
||||
from datetime import timedelta
|
||||
|
||||
from hatchet_sdk import Context, EmptyModel, Hatchet
|
||||
from hatchet_sdk.exceptions import TaskRunError
|
||||
|
||||
hatchet = Hatchet(debug=True)
|
||||
hatchet = Hatchet(debug=False)
|
||||
|
||||
ERROR_TEXT = "step1 failed"
|
||||
|
||||
@@ -49,14 +50,20 @@ def details_step1(input: EmptyModel, ctx: Context) -> None:
|
||||
|
||||
# 👀 After the workflow fails, this special step will run
|
||||
@on_failure_wf_with_details.on_failure_task()
|
||||
def details_on_failure(input: EmptyModel, ctx: Context) -> dict[str, str]:
|
||||
error = ctx.fetch_task_run_error(details_step1)
|
||||
def details_on_failure(input: EmptyModel, ctx: Context) -> dict[str, str | None]:
|
||||
error = ctx.get_task_run_error(details_step1)
|
||||
|
||||
if not error:
|
||||
return {"status": "unexpected success"}
|
||||
|
||||
# 👀 we can access the failure details here
|
||||
print(json.dumps(error, indent=2))
|
||||
assert isinstance(error, TaskRunError)
|
||||
|
||||
if error and error.startswith(ERROR_TEXT):
|
||||
return {"status": "success"}
|
||||
if "step1 failed" in error.exc:
|
||||
return {
|
||||
"status": "success",
|
||||
"failed_run_external_id": error.task_run_external_id,
|
||||
}
|
||||
|
||||
raise Exception("unexpected failure")
|
||||
|
||||
|
||||
76
examples/python/quickstart/poetry.lock
generated
76
examples/python/quickstart/poetry.lock
generated
@@ -1,4 +1,4 @@
|
||||
# This file is automatically @generated by Poetry 2.1.1 and should not be changed by hand.
|
||||
# This file is automatically @generated by Poetry 2.0.0 and should not be changed by hand.
|
||||
|
||||
[[package]]
|
||||
name = "aiohappyeyeballs"
|
||||
@@ -114,7 +114,7 @@ propcache = ">=0.2.0"
|
||||
yarl = ">=1.17.0,<2.0"
|
||||
|
||||
[package.extras]
|
||||
speedups = ["Brotli ; platform_python_implementation == \"CPython\"", "aiodns (>=3.2.0) ; sys_platform == \"linux\" or sys_platform == \"darwin\"", "brotlicffi ; platform_python_implementation != \"CPython\""]
|
||||
speedups = ["Brotli", "aiodns (>=3.2.0)", "brotlicffi"]
|
||||
|
||||
[[package]]
|
||||
name = "aiohttp-retry"
|
||||
@@ -199,12 +199,12 @@ files = [
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
benchmark = ["cloudpickle ; platform_python_implementation == \"CPython\"", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pympler", "pytest (>=4.3.0)", "pytest-codspeed", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-xdist[psutil]"]
|
||||
cov = ["cloudpickle ; platform_python_implementation == \"CPython\"", "coverage[toml] (>=5.3)", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-xdist[psutil]"]
|
||||
dev = ["cloudpickle ; platform_python_implementation == \"CPython\"", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pre-commit-uv", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-xdist[psutil]"]
|
||||
benchmark = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-codspeed", "pytest-mypy-plugins", "pytest-xdist[psutil]"]
|
||||
cov = ["cloudpickle", "coverage[toml] (>=5.3)", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"]
|
||||
dev = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pre-commit-uv", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"]
|
||||
docs = ["cogapp", "furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier"]
|
||||
tests = ["cloudpickle ; platform_python_implementation == \"CPython\"", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-xdist[psutil]"]
|
||||
tests-mypy = ["mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\""]
|
||||
tests = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"]
|
||||
tests-mypy = ["mypy (>=1.11.1)", "pytest-mypy-plugins"]
|
||||
|
||||
[[package]]
|
||||
name = "cel-python"
|
||||
@@ -460,14 +460,14 @@ setuptools = "*"
|
||||
|
||||
[[package]]
|
||||
name = "hatchet-sdk"
|
||||
version = "1.16.5"
|
||||
version = "1.0.0a1"
|
||||
description = ""
|
||||
optional = false
|
||||
python-versions = "<4.0,>=3.10"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "hatchet_sdk-1.16.5-py3-none-any.whl", hash = "sha256:3a21edf4d5f1655facaea3dcfabb7b00dafc35a0a593ff088cbe21d1eb7b4db8"},
|
||||
{file = "hatchet_sdk-1.16.5.tar.gz", hash = "sha256:c00e85a3a9b1789b85679e528deddd12a6d70ba321e16de9ec07e3fd1d373fb8"},
|
||||
{file = "hatchet_sdk-1.0.0a1-py3-none-any.whl", hash = "sha256:bfc84358c8842cecd0d95b30645109733b7292dff0db1a776ca862785ee93d7f"},
|
||||
{file = "hatchet_sdk-1.0.0a1.tar.gz", hash = "sha256:f0272bbaac6faed75ff727826e9f7b1ac42ae597f9b590e14d392aada9c9692f"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@@ -483,11 +483,13 @@ grpcio-tools = [
|
||||
{version = ">=1.64.1,<1.68.dev0 || >=1.69.dev0", markers = "python_version < \"3.13\""},
|
||||
{version = ">=1.69.0", markers = "python_version >= \"3.13\""},
|
||||
]
|
||||
prometheus-client = ">=0.21.1"
|
||||
protobuf = ">=5.29.5,<6.0.0"
|
||||
nest-asyncio = ">=1.6.0,<2.0.0"
|
||||
prometheus-client = ">=0.21.1,<0.22.0"
|
||||
protobuf = ">=5.29.1,<6.0.0"
|
||||
pydantic = ">=2.6.3,<3.0.0"
|
||||
pydantic-settings = ">=2.7.1,<3.0.0"
|
||||
python-dateutil = ">=2.9.0.post0,<3.0.0"
|
||||
pyyaml = ">=6.0.1,<7.0.0"
|
||||
tenacity = ">=8.4.1"
|
||||
urllib3 = ">=1.26.20"
|
||||
|
||||
@@ -643,6 +645,18 @@ files = [
|
||||
[package.dependencies]
|
||||
typing-extensions = {version = ">=4.1.0", markers = "python_version < \"3.11\""}
|
||||
|
||||
[[package]]
|
||||
name = "nest-asyncio"
|
||||
version = "1.6.0"
|
||||
description = "Patch asyncio to allow nested event loops"
|
||||
optional = false
|
||||
python-versions = ">=3.5"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "nest_asyncio-1.6.0-py3-none-any.whl", hash = "sha256:87af6efd6b5e897c81050477ef65c62e2b2f35d51703cae01aff2905b1852e1c"},
|
||||
{file = "nest_asyncio-1.6.0.tar.gz", hash = "sha256:6f172d5449aca15afd6c646851f4e31e02c598d553a667e38cafa997cfec55fe"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "prometheus-client"
|
||||
version = "0.21.1"
|
||||
@@ -768,23 +782,23 @@ files = [
|
||||
|
||||
[[package]]
|
||||
name = "protobuf"
|
||||
version = "5.29.5"
|
||||
version = "5.29.4"
|
||||
description = ""
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "protobuf-5.29.5-cp310-abi3-win32.whl", hash = "sha256:3f1c6468a2cfd102ff4703976138844f78ebd1fb45f49011afc5139e9e283079"},
|
||||
{file = "protobuf-5.29.5-cp310-abi3-win_amd64.whl", hash = "sha256:3f76e3a3675b4a4d867b52e4a5f5b78a2ef9565549d4037e06cf7b0942b1d3fc"},
|
||||
{file = "protobuf-5.29.5-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:e38c5add5a311f2a6eb0340716ef9b039c1dfa428b28f25a7838ac329204a671"},
|
||||
{file = "protobuf-5.29.5-cp38-abi3-manylinux2014_aarch64.whl", hash = "sha256:fa18533a299d7ab6c55a238bf8629311439995f2e7eca5caaff08663606e9015"},
|
||||
{file = "protobuf-5.29.5-cp38-abi3-manylinux2014_x86_64.whl", hash = "sha256:63848923da3325e1bf7e9003d680ce6e14b07e55d0473253a690c3a8b8fd6e61"},
|
||||
{file = "protobuf-5.29.5-cp38-cp38-win32.whl", hash = "sha256:ef91363ad4faba7b25d844ef1ada59ff1604184c0bcd8b39b8a6bef15e1af238"},
|
||||
{file = "protobuf-5.29.5-cp38-cp38-win_amd64.whl", hash = "sha256:7318608d56b6402d2ea7704ff1e1e4597bee46d760e7e4dd42a3d45e24b87f2e"},
|
||||
{file = "protobuf-5.29.5-cp39-cp39-win32.whl", hash = "sha256:6f642dc9a61782fa72b90878af134c5afe1917c89a568cd3476d758d3c3a0736"},
|
||||
{file = "protobuf-5.29.5-cp39-cp39-win_amd64.whl", hash = "sha256:470f3af547ef17847a28e1f47200a1cbf0ba3ff57b7de50d22776607cd2ea353"},
|
||||
{file = "protobuf-5.29.5-py3-none-any.whl", hash = "sha256:6cf42630262c59b2d8de33954443d94b746c952b01434fc58a417fdbd2e84bd5"},
|
||||
{file = "protobuf-5.29.5.tar.gz", hash = "sha256:bc1463bafd4b0929216c35f437a8e28731a2b7fe3d98bb77a600efced5a15c84"},
|
||||
{file = "protobuf-5.29.4-cp310-abi3-win32.whl", hash = "sha256:13eb236f8eb9ec34e63fc8b1d6efd2777d062fa6aaa68268fb67cf77f6839ad7"},
|
||||
{file = "protobuf-5.29.4-cp310-abi3-win_amd64.whl", hash = "sha256:bcefcdf3976233f8a502d265eb65ea740c989bacc6c30a58290ed0e519eb4b8d"},
|
||||
{file = "protobuf-5.29.4-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:307ecba1d852ec237e9ba668e087326a67564ef83e45a0189a772ede9e854dd0"},
|
||||
{file = "protobuf-5.29.4-cp38-abi3-manylinux2014_aarch64.whl", hash = "sha256:aec4962f9ea93c431d5714ed1be1c93f13e1a8618e70035ba2b0564d9e633f2e"},
|
||||
{file = "protobuf-5.29.4-cp38-abi3-manylinux2014_x86_64.whl", hash = "sha256:d7d3f7d1d5a66ed4942d4fefb12ac4b14a29028b209d4bfb25c68ae172059922"},
|
||||
{file = "protobuf-5.29.4-cp38-cp38-win32.whl", hash = "sha256:1832f0515b62d12d8e6ffc078d7e9eb06969aa6dc13c13e1036e39d73bebc2de"},
|
||||
{file = "protobuf-5.29.4-cp38-cp38-win_amd64.whl", hash = "sha256:476cb7b14914c780605a8cf62e38c2a85f8caff2e28a6a0bad827ec7d6c85d68"},
|
||||
{file = "protobuf-5.29.4-cp39-cp39-win32.whl", hash = "sha256:fd32223020cb25a2cc100366f1dedc904e2d71d9322403224cdde5fdced0dabe"},
|
||||
{file = "protobuf-5.29.4-cp39-cp39-win_amd64.whl", hash = "sha256:678974e1e3a9b975b8bc2447fca458db5f93a2fb6b0c8db46b6675b5b5346812"},
|
||||
{file = "protobuf-5.29.4-py3-none-any.whl", hash = "sha256:3fde11b505e1597f71b875ef2fc52062b6a9740e5f7c8997ce878b6009145862"},
|
||||
{file = "protobuf-5.29.4.tar.gz", hash = "sha256:4f1dfcd7997b31ef8f53ec82781ff434a28bf71d9102ddde14d076adcfc78c99"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -806,7 +820,7 @@ typing-extensions = ">=4.12.2"
|
||||
|
||||
[package.extras]
|
||||
email = ["email-validator (>=2.0.0)"]
|
||||
timezone = ["tzdata ; python_version >= \"3.9\" and platform_system == \"Windows\""]
|
||||
timezone = ["tzdata"]
|
||||
|
||||
[[package]]
|
||||
name = "pydantic-core"
|
||||
@@ -1048,13 +1062,13 @@ files = [
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1) ; sys_platform != \"cygwin\"", "ruff (>=0.8.0) ; sys_platform != \"cygwin\""]
|
||||
core = ["importlib_metadata (>=6) ; python_version < \"3.10\"", "jaraco.functools (>=4)", "jaraco.text (>=3.7)", "more_itertools", "more_itertools (>=8.8)", "packaging (>=24.2)", "platformdirs (>=4.2.2)", "tomli (>=2.0.1) ; python_version < \"3.11\"", "wheel (>=0.43.0)"]
|
||||
check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1)", "ruff (>=0.8.0)"]
|
||||
core = ["importlib_metadata (>=6)", "jaraco.functools (>=4)", "jaraco.text (>=3.7)", "more_itertools", "more_itertools (>=8.8)", "packaging (>=24.2)", "platformdirs (>=4.2.2)", "tomli (>=2.0.1)", "wheel (>=0.43.0)"]
|
||||
cover = ["pytest-cov"]
|
||||
doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "pyproject-hooks (!=1.1)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier", "towncrier (<24.7)"]
|
||||
enabler = ["pytest-enabler (>=2.2)"]
|
||||
test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21) ; python_version >= \"3.9\" and sys_platform != \"cygwin\"", "jaraco.envs (>=2.2)", "jaraco.path (>=3.7.2)", "jaraco.test (>=5.5)", "packaging (>=24.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-home (>=0.5)", "pytest-perf ; sys_platform != \"cygwin\"", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel (>=0.44.0)"]
|
||||
type = ["importlib_metadata (>=7.0.2) ; python_version < \"3.10\"", "jaraco.develop (>=7.21) ; sys_platform != \"cygwin\"", "mypy (==1.14.*)", "pytest-mypy"]
|
||||
test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.7.2)", "jaraco.test (>=5.5)", "packaging (>=24.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-home (>=0.5)", "pytest-perf", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel (>=0.44.0)"]
|
||||
type = ["importlib_metadata (>=7.0.2)", "jaraco.develop (>=7.21)", "mypy (==1.14.*)", "pytest-mypy"]
|
||||
|
||||
[[package]]
|
||||
name = "six"
|
||||
@@ -1133,7 +1147,7 @@ files = [
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
brotli = ["brotli (>=1.0.9) ; platform_python_implementation == \"CPython\"", "brotlicffi (>=0.8.0) ; platform_python_implementation != \"CPython\""]
|
||||
brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"]
|
||||
h2 = ["h2 (>=4,<5)"]
|
||||
socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"]
|
||||
zstd = ["zstandard (>=0.18.0)"]
|
||||
@@ -1238,4 +1252,4 @@ propcache = ">=0.2.0"
|
||||
[metadata]
|
||||
lock-version = "2.1"
|
||||
python-versions = "^3.10"
|
||||
content-hash = "06949f41c097b940db1cb406e6ea99dec9c1bad09389ff5d08cd2d5b16f053a4"
|
||||
content-hash = "74c12e499aa797ca5c8559af579f1212b0e4e3a77f068f9385db39d70ba304e0"
|
||||
|
||||
@@ -15,6 +15,13 @@ from examples.concurrency_workflow_level.worker import (
|
||||
from examples.conditions.worker import task_condition_workflow
|
||||
from examples.dag.worker import dag_workflow
|
||||
from examples.dedupe.worker import dedupe_child_wf, dedupe_parent_wf
|
||||
from examples.dependency_injection.worker import (
|
||||
async_task_with_dependencies,
|
||||
di_workflow,
|
||||
durable_async_task_with_dependencies,
|
||||
durable_sync_task_with_dependencies,
|
||||
sync_task_with_dependencies,
|
||||
)
|
||||
from examples.durable.worker import durable_workflow, wait_for_sleep_twice
|
||||
from examples.events.worker import event_workflow
|
||||
from examples.fanout.worker import child_wf, parent_wf
|
||||
@@ -61,6 +68,7 @@ def main() -> None:
|
||||
sync_fanout_child,
|
||||
non_retryable_workflow,
|
||||
concurrency_workflow_level_workflow,
|
||||
di_workflow,
|
||||
lifespan_task,
|
||||
simple,
|
||||
simple_durable,
|
||||
@@ -70,6 +78,10 @@ def main() -> None:
|
||||
webhook,
|
||||
return_exceptions_task,
|
||||
wait_for_sleep_twice,
|
||||
async_task_with_dependencies,
|
||||
sync_task_with_dependencies,
|
||||
durable_async_task_with_dependencies,
|
||||
durable_sync_task_with_dependencies,
|
||||
],
|
||||
lifespan=lifespan,
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user