From f7725b5b08411309243d18abf1589259fe2dbeb3 Mon Sep 17 00:00:00 2001 From: Sergio Herrera <627709+seherv@users.noreply.github.com> Date: Mon, 25 May 2026 10:57:59 +0200 Subject: [PATCH 1/2] Merge extensions into core package as PEP 771 extras Signed-off-by: Sergio Herrera <627709+seherv@users.noreply.github.com> --- .codecov.yml | 3 +- .github/ISSUE_TEMPLATE/bug_report.md | 2 +- .github/ISSUE_TEMPLATE/feature_request.md | 2 +- .github/ISSUE_TEMPLATE/workflow_bug_report.md | 2 +- .../workflow_feature_request.md | 2 +- .github/workflows/build-tag.yaml | 56 +---- .github/workflows/build.yaml | 2 +- AGENTS.md | 94 +++---- README.md | 55 +++-- RELEASE.md | 39 ++- dapr/__init__.py | 184 ++++++++++++++ .../ext/fastapi}/AGENTS.md | 34 +-- dapr/ext/fastapi/README.md | 15 ++ .../dapr => dapr}/ext/fastapi/__init__.py | 10 +- .../dapr => dapr}/ext/fastapi/actor.py | 0 .../dapr => dapr}/ext/fastapi/app.py | 0 .../dapr => dapr}/ext/fastapi/py.typed | 0 {ext/flask_dapr => dapr/ext/flask}/AGENTS.md | 46 ++-- dapr/ext/flask/README.md | 25 ++ .../flask_dapr => dapr/ext/flask}/__init__.py | 10 +- .../flask_dapr => dapr/ext/flask}/actor.py | 3 +- .../flask_dapr => dapr/ext/flask}/app.py | 0 .../dapr/ext/grpc => dapr/ext/flask}/py.typed | 0 .../dapr-ext-grpc => dapr/ext/grpc}/AGENTS.md | 37 +-- dapr/ext/grpc/README.md | 16 ++ .../dapr => dapr}/ext/grpc/__init__.py | 10 +- .../ext/grpc/_health_servicer.py | 0 .../dapr => dapr}/ext/grpc/_servicer.py | 0 .../dapr => dapr}/ext/grpc/app.py | 5 +- .../ext/langgraph => dapr/ext/grpc}/py.typed | 0 .../ext/langgraph}/AGENTS.md | 34 +-- dapr/ext/langgraph/README.md | 15 ++ .../dapr => dapr}/ext/langgraph/__init__.py | 9 +- .../ext/langgraph/dapr_checkpointer.py | 0 .../workflow => dapr/ext/langgraph}/py.typed | 0 .../ext/strands}/AGENTS.md | 34 +-- dapr/ext/strands/README.md | 15 ++ .../dapr => dapr}/ext/strands/__init__.py | 9 +- .../ext/strands/dapr_session_manager.py | 0 .../ext/workflow}/AGENTS.md | 56 +++-- dapr/ext/workflow/README.md | 15 ++ .../dapr => dapr}/ext/workflow/__init__.py | 0 .../ext/workflow/_durabletask/__init__.py | 2 +- .../ext/workflow/_durabletask/aio/__init__.py | 0 .../ext/workflow/_durabletask/aio/client.py | 5 +- .../_durabletask/aio/internal}/__init__.py | 0 .../aio/internal/grpc_interceptor.py | 0 .../_durabletask/aio/internal/shared.py | 5 +- .../ext/workflow/_durabletask/client.py | 5 +- .../workflow/_durabletask/deterministic.py | 0 .../internal/PROTO_SOURCE_COMMIT_HASH | 0 .../_durabletask/internal}/__init__.py | 0 .../_durabletask/internal/attestation_pb2.py | 0 .../_durabletask/internal/attestation_pb2.pyi | 0 .../internal/attestation_pb2_grpc.py | 0 .../internal/backend_service_pb2.py | 0 .../internal/backend_service_pb2.pyi | 0 .../internal/backend_service_pb2_grpc.py | 0 .../_durabletask/internal/grpc_interceptor.py | 0 .../workflow/_durabletask/internal/helpers.py | 3 +- .../internal/history_events_pb2.py | 0 .../internal/history_events_pb2.pyi | 0 .../internal/history_events_pb2_grpc.py | 0 .../internal/orchestration_pb2.py | 0 .../internal/orchestration_pb2.pyi | 0 .../internal/orchestration_pb2_grpc.py | 0 .../internal/orchestrator_actions_pb2.py | 0 .../internal/orchestrator_actions_pb2.pyi | 0 .../internal/orchestrator_actions_pb2_grpc.py | 0 .../internal/orchestrator_service_pb2.py | 0 .../internal/orchestrator_service_pb2.pyi | 0 .../internal/orchestrator_service_pb2_grpc.py | 0 .../workflow/_durabletask/internal/protos.py | 0 .../internal/runtime_state_pb2.py | 0 .../internal/runtime_state_pb2.pyi | 0 .../internal/runtime_state_pb2_grpc.py | 0 .../workflow/_durabletask/internal/shared.py | 1 + .../workflow/_durabletask/internal/timer.py | 3 +- .../ext/workflow/_durabletask/task.py | 0 .../ext/workflow/_durabletask/worker.py | 5 +- .../ext/workflow/_model_protocol.py | 0 .../ext/workflow/aio/__init__.py | 0 .../ext/workflow/aio/dapr_workflow_client.py | 12 +- .../dapr => dapr}/ext/workflow/aio/mcp.py | 0 .../ext/workflow/dapr_workflow_client.py | 10 +- .../ext/workflow/dapr_workflow_context.py | 0 .../ext/workflow/logger/__init__.py | 0 .../ext/workflow/logger/logger.py | 0 .../ext/workflow/logger/options.py | 0 .../dapr => dapr}/ext/workflow/mcp.py | 0 .../dapr => dapr}/ext/workflow/mcp_schema.py | 0 .../dapr => dapr}/ext/workflow/propagation.py | 0 .../flask_dapr => dapr/ext/workflow}/py.typed | 0 .../ext/workflow/retry_policy.py | 0 .../dapr => dapr}/ext/workflow/util.py | 0 .../ext/workflow/workflow_activity_context.py | 0 .../ext/workflow/workflow_context.py | 0 .../ext/workflow/workflow_runtime.py | 12 +- .../ext/workflow/workflow_state.py | 0 examples/AGENTS.md | 36 +-- examples/configuration/README.md | 2 +- .../demo_actor/demo_actor/demo_actor_flask.py | 2 +- .../demo_actor/demo_actor_service.py | 2 +- .../demo_actor/demo_actor/requirements.txt | 2 +- examples/distributed_lock/README.md | 2 +- examples/error_handling/README.md | 2 +- examples/grpc_proxying/README.md | 2 +- examples/grpc_proxying/invoke-receiver.py | 3 +- examples/invoke-binding/README.md | 2 +- examples/invoke-custom-data/README.md | 2 +- .../invoke-custom-data/invoke-receiver.py | 1 + examples/invoke-simple/README.md | 2 +- examples/invoke-simple/requirements.txt | 3 +- examples/jobs/README.md | 2 +- examples/jobs/job_processing.py | 3 +- examples/langgraph-checkpointer/agent.py | 3 +- examples/mcp/mcp_tool_discovery.py | 3 +- examples/mcp/requirements.txt | 4 +- examples/metadata/README.md | 2 +- examples/pubsub-simple/README.md | 2 +- examples/pubsub-simple/subscriber.py | 2 +- examples/secret_store/README.md | 2 +- examples/state_store/README.md | 2 +- examples/state_store_query/README.md | 2 +- examples/w3c-tracing/invoke-receiver.py | 2 +- examples/w3c-tracing/requirements.txt | 5 +- examples/workflow/human_approval.py | 1 - examples/workflow/pydantic_models.py | 3 +- examples/workflow/requirements.txt | 5 +- examples/workflow/simple.py | 5 +- examples/workflow/simple_aio_client.py | 5 +- ext/dapr-ext-fastapi/LICENSE | 203 ---------------- ext/dapr-ext-fastapi/README.rst | 22 -- ext/dapr-ext-fastapi/pyproject.toml | 44 ---- ext/dapr-ext-grpc/LICENSE | 203 ---------------- ext/dapr-ext-grpc/README.rst | 22 -- ext/dapr-ext-grpc/pyproject.toml | 43 ---- ext/dapr-ext-langgraph/LICENSE | 203 ---------------- ext/dapr-ext-langgraph/README.rst | 22 -- ext/dapr-ext-langgraph/pyproject.toml | 46 ---- ext/dapr-ext-strands/LICENSE | 203 ---------------- ext/dapr-ext-strands/README.rst | 22 -- ext/dapr-ext-strands/pyproject.toml | 46 ---- ext/dapr-ext-workflow/LICENSE | 203 ---------------- ext/dapr-ext-workflow/README.rst | 23 -- ext/dapr-ext-workflow/pyproject.toml | 42 ---- ext/flask_dapr/LICENSE | 203 ---------------- ext/flask_dapr/README.rst | 39 --- ext/flask_dapr/pyproject.toml | 43 ---- flask_dapr/__init__.py | 39 +++ dapr/__init__.pyi => flask_dapr/py.typed | 0 pyproject.toml | 84 ++++++- tests/actor/test_actor_reentrancy.py | 5 +- .../aio/internal => tests/ext}/__init__.py | 0 .../ext/fastapi}/__init__.py | 0 .../tests => tests/ext/fastapi}/test_app.py | 3 +- .../ext/fastapi}/test_dapractor.py | 3 +- .../ext/flask}/__init__.py | 0 .../tests => tests/ext/flask}/test_app.py | 3 +- tests/ext/flask/test_shim_deprecation.py | 30 +++ tests/ext/grpc/__init__.py | 0 .../tests => tests/ext/grpc}/test_app.py | 2 +- .../ext/grpc}/test_health_servicer.py | 0 .../ext/grpc}/test_servicier.py | 2 +- .../ext/grpc}/test_topic_event_response.py | 0 .../tests => tests/ext/langgraph}/__init__.py | 0 .../ext/langgraph}/test_checkpointer.py | 3 +- .../tests => tests/ext/strands}/__init__.py | 0 .../ext/strands}/test_session_manager.py | 3 +- .../tests => tests/ext/workflow}/__init__.py | 0 tests/ext/workflow/durabletask/__init__.py | 0 .../durabletask/test_activity_executor.py | 0 .../ext/workflow}/durabletask/test_client.py | 0 .../durabletask/test_client_async.py | 0 .../durabletask/test_concurrency_options.py | 0 .../durabletask/test_deterministic.py | 1 + .../durabletask/test_orchestration_e2e.py | 1 + .../test_orchestration_e2e_async.py | 1 + .../test_orchestration_executor.py | 3 +- .../durabletask/test_orchestration_wait.py | 1 + .../workflow}/durabletask/test_propagation.py | 5 +- .../durabletask/test_propagation_wiring.py | 0 .../workflow}/durabletask/test_registry.py | 1 + .../durabletask/test_serialization.py | 3 +- .../ext/workflow}/durabletask/test_task.py | 3 +- .../test_worker_concurrency_loop.py | 0 .../test_worker_concurrency_loop_async.py | 0 .../workflow}/durabletask/test_worker_stop.py | 1 + .../workflow}/test_dapr_workflow_context.py | 0 .../ext/workflow}/test_mcp_client.py | 0 .../ext/workflow}/test_mcp_schema.py | 3 +- .../ext/workflow}/test_model_protocol.py | 3 +- .../test_workflow_activity_context.py | 0 .../ext/workflow}/test_workflow_client.py | 3 +- .../ext/workflow}/test_workflow_client_aio.py | 3 +- .../ext/workflow}/test_workflow_runtime.py | 3 +- .../ext/workflow}/test_workflow_util.py | 3 +- tests/integration/AGENTS.md | 2 +- tests/integration/apps/pubsub_subscriber.py | 2 +- tools/regen_durabletask_protos.sh | 6 +- uv.lock | 229 +++++++++--------- 201 files changed, 994 insertions(+), 2110 deletions(-) create mode 100644 dapr/__init__.py rename {ext/dapr-ext-fastapi => dapr/ext/fastapi}/AGENTS.md (77%) create mode 100644 dapr/ext/fastapi/README.md rename {ext/dapr-ext-fastapi/dapr => dapr}/ext/fastapi/__init__.py (69%) rename {ext/dapr-ext-fastapi/dapr => dapr}/ext/fastapi/actor.py (100%) rename {ext/dapr-ext-fastapi/dapr => dapr}/ext/fastapi/app.py (100%) rename {ext/dapr-ext-fastapi/dapr => dapr}/ext/fastapi/py.typed (100%) rename {ext/flask_dapr => dapr/ext/flask}/AGENTS.md (58%) create mode 100644 dapr/ext/flask/README.md rename {ext/flask_dapr/flask_dapr => dapr/ext/flask}/__init__.py (69%) rename {ext/flask_dapr/flask_dapr => dapr/ext/flask}/actor.py (99%) rename {ext/flask_dapr/flask_dapr => dapr/ext/flask}/app.py (100%) rename {ext/dapr-ext-grpc/dapr/ext/grpc => dapr/ext/flask}/py.typed (100%) rename {ext/dapr-ext-grpc => dapr/ext/grpc}/AGENTS.md (84%) create mode 100644 dapr/ext/grpc/README.md rename {ext/dapr-ext-grpc/dapr => dapr}/ext/grpc/__init__.py (80%) rename {ext/dapr-ext-grpc/dapr => dapr}/ext/grpc/_health_servicer.py (100%) rename {ext/dapr-ext-grpc/dapr => dapr}/ext/grpc/_servicer.py (100%) rename {ext/dapr-ext-grpc/dapr => dapr}/ext/grpc/app.py (99%) rename {ext/dapr-ext-langgraph/dapr/ext/langgraph => dapr/ext/grpc}/py.typed (100%) rename {ext/dapr-ext-langgraph => dapr/ext/langgraph}/AGENTS.md (80%) create mode 100644 dapr/ext/langgraph/README.md rename {ext/dapr-ext-langgraph/dapr => dapr}/ext/langgraph/__init__.py (68%) rename {ext/dapr-ext-langgraph/dapr => dapr}/ext/langgraph/dapr_checkpointer.py (100%) rename {ext/dapr-ext-workflow/dapr/ext/workflow => dapr/ext/langgraph}/py.typed (100%) rename {ext/dapr-ext-strands => dapr/ext/strands}/AGENTS.md (82%) create mode 100644 dapr/ext/strands/README.md rename {ext/dapr-ext-strands/dapr => dapr}/ext/strands/__init__.py (68%) rename {ext/dapr-ext-strands/dapr => dapr}/ext/strands/dapr_session_manager.py (100%) rename {ext/dapr-ext-workflow => dapr/ext/workflow}/AGENTS.md (85%) create mode 100644 dapr/ext/workflow/README.md rename {ext/dapr-ext-workflow/dapr => dapr}/ext/workflow/__init__.py (100%) rename {ext/dapr-ext-workflow/dapr => dapr}/ext/workflow/_durabletask/__init__.py (90%) rename {ext/dapr-ext-workflow/dapr => dapr}/ext/workflow/_durabletask/aio/__init__.py (100%) rename {ext/dapr-ext-workflow/dapr => dapr}/ext/workflow/_durabletask/aio/client.py (99%) rename {ext/dapr-ext-fastapi/tests => dapr/ext/workflow/_durabletask/aio/internal}/__init__.py (100%) rename {ext/dapr-ext-workflow/dapr => dapr}/ext/workflow/_durabletask/aio/internal/grpc_interceptor.py (100%) rename {ext/dapr-ext-workflow/dapr => dapr}/ext/workflow/_durabletask/aio/internal/shared.py (99%) rename {ext/dapr-ext-workflow/dapr => dapr}/ext/workflow/_durabletask/client.py (99%) rename {ext/dapr-ext-workflow/dapr => dapr}/ext/workflow/_durabletask/deterministic.py (100%) rename {ext/dapr-ext-workflow/dapr => dapr}/ext/workflow/_durabletask/internal/PROTO_SOURCE_COMMIT_HASH (100%) rename {ext/dapr-ext-grpc/tests => dapr/ext/workflow/_durabletask/internal}/__init__.py (100%) rename {ext/dapr-ext-workflow/dapr => dapr}/ext/workflow/_durabletask/internal/attestation_pb2.py (100%) rename {ext/dapr-ext-workflow/dapr => dapr}/ext/workflow/_durabletask/internal/attestation_pb2.pyi (100%) rename {ext/dapr-ext-workflow/dapr => dapr}/ext/workflow/_durabletask/internal/attestation_pb2_grpc.py (100%) rename {ext/dapr-ext-workflow/dapr => dapr}/ext/workflow/_durabletask/internal/backend_service_pb2.py (100%) rename {ext/dapr-ext-workflow/dapr => dapr}/ext/workflow/_durabletask/internal/backend_service_pb2.pyi (100%) rename {ext/dapr-ext-workflow/dapr => dapr}/ext/workflow/_durabletask/internal/backend_service_pb2_grpc.py (100%) rename {ext/dapr-ext-workflow/dapr => dapr}/ext/workflow/_durabletask/internal/grpc_interceptor.py (100%) rename {ext/dapr-ext-workflow/dapr => dapr}/ext/workflow/_durabletask/internal/helpers.py (99%) rename {ext/dapr-ext-workflow/dapr => dapr}/ext/workflow/_durabletask/internal/history_events_pb2.py (100%) rename {ext/dapr-ext-workflow/dapr => dapr}/ext/workflow/_durabletask/internal/history_events_pb2.pyi (100%) rename {ext/dapr-ext-workflow/dapr => dapr}/ext/workflow/_durabletask/internal/history_events_pb2_grpc.py (100%) rename {ext/dapr-ext-workflow/dapr => dapr}/ext/workflow/_durabletask/internal/orchestration_pb2.py (100%) rename {ext/dapr-ext-workflow/dapr => dapr}/ext/workflow/_durabletask/internal/orchestration_pb2.pyi (100%) rename {ext/dapr-ext-workflow/dapr => dapr}/ext/workflow/_durabletask/internal/orchestration_pb2_grpc.py (100%) rename {ext/dapr-ext-workflow/dapr => dapr}/ext/workflow/_durabletask/internal/orchestrator_actions_pb2.py (100%) rename {ext/dapr-ext-workflow/dapr => dapr}/ext/workflow/_durabletask/internal/orchestrator_actions_pb2.pyi (100%) rename {ext/dapr-ext-workflow/dapr => dapr}/ext/workflow/_durabletask/internal/orchestrator_actions_pb2_grpc.py (100%) rename {ext/dapr-ext-workflow/dapr => dapr}/ext/workflow/_durabletask/internal/orchestrator_service_pb2.py (100%) rename {ext/dapr-ext-workflow/dapr => dapr}/ext/workflow/_durabletask/internal/orchestrator_service_pb2.pyi (100%) rename {ext/dapr-ext-workflow/dapr => dapr}/ext/workflow/_durabletask/internal/orchestrator_service_pb2_grpc.py (100%) rename {ext/dapr-ext-workflow/dapr => dapr}/ext/workflow/_durabletask/internal/protos.py (100%) rename {ext/dapr-ext-workflow/dapr => dapr}/ext/workflow/_durabletask/internal/runtime_state_pb2.py (100%) rename {ext/dapr-ext-workflow/dapr => dapr}/ext/workflow/_durabletask/internal/runtime_state_pb2.pyi (100%) rename {ext/dapr-ext-workflow/dapr => dapr}/ext/workflow/_durabletask/internal/runtime_state_pb2_grpc.py (100%) rename {ext/dapr-ext-workflow/dapr => dapr}/ext/workflow/_durabletask/internal/shared.py (99%) rename {ext/dapr-ext-workflow/dapr => dapr}/ext/workflow/_durabletask/internal/timer.py (99%) rename {ext/dapr-ext-workflow/dapr => dapr}/ext/workflow/_durabletask/task.py (100%) rename {ext/dapr-ext-workflow/dapr => dapr}/ext/workflow/_durabletask/worker.py (99%) rename {ext/dapr-ext-workflow/dapr => dapr}/ext/workflow/_model_protocol.py (100%) rename {ext/dapr-ext-workflow/dapr => dapr}/ext/workflow/aio/__init__.py (100%) rename {ext/dapr-ext-workflow/dapr => dapr}/ext/workflow/aio/dapr_workflow_client.py (100%) rename {ext/dapr-ext-workflow/dapr => dapr}/ext/workflow/aio/mcp.py (100%) rename {ext/dapr-ext-workflow/dapr => dapr}/ext/workflow/dapr_workflow_client.py (100%) rename {ext/dapr-ext-workflow/dapr => dapr}/ext/workflow/dapr_workflow_context.py (100%) rename {ext/dapr-ext-workflow/dapr => dapr}/ext/workflow/logger/__init__.py (100%) rename {ext/dapr-ext-workflow/dapr => dapr}/ext/workflow/logger/logger.py (100%) rename {ext/dapr-ext-workflow/dapr => dapr}/ext/workflow/logger/options.py (100%) rename {ext/dapr-ext-workflow/dapr => dapr}/ext/workflow/mcp.py (100%) rename {ext/dapr-ext-workflow/dapr => dapr}/ext/workflow/mcp_schema.py (100%) rename {ext/dapr-ext-workflow/dapr => dapr}/ext/workflow/propagation.py (100%) rename {ext/flask_dapr/flask_dapr => dapr/ext/workflow}/py.typed (100%) rename {ext/dapr-ext-workflow/dapr => dapr}/ext/workflow/retry_policy.py (100%) rename {ext/dapr-ext-workflow/dapr => dapr}/ext/workflow/util.py (100%) rename {ext/dapr-ext-workflow/dapr => dapr}/ext/workflow/workflow_activity_context.py (100%) rename {ext/dapr-ext-workflow/dapr => dapr}/ext/workflow/workflow_context.py (100%) rename {ext/dapr-ext-workflow/dapr => dapr}/ext/workflow/workflow_runtime.py (100%) rename {ext/dapr-ext-workflow/dapr => dapr}/ext/workflow/workflow_state.py (100%) delete mode 100644 ext/dapr-ext-fastapi/LICENSE delete mode 100644 ext/dapr-ext-fastapi/README.rst delete mode 100644 ext/dapr-ext-fastapi/pyproject.toml delete mode 100644 ext/dapr-ext-grpc/LICENSE delete mode 100644 ext/dapr-ext-grpc/README.rst delete mode 100644 ext/dapr-ext-grpc/pyproject.toml delete mode 100644 ext/dapr-ext-langgraph/LICENSE delete mode 100644 ext/dapr-ext-langgraph/README.rst delete mode 100644 ext/dapr-ext-langgraph/pyproject.toml delete mode 100644 ext/dapr-ext-strands/LICENSE delete mode 100644 ext/dapr-ext-strands/README.rst delete mode 100644 ext/dapr-ext-strands/pyproject.toml delete mode 100644 ext/dapr-ext-workflow/LICENSE delete mode 100644 ext/dapr-ext-workflow/README.rst delete mode 100644 ext/dapr-ext-workflow/pyproject.toml delete mode 100644 ext/flask_dapr/LICENSE delete mode 100644 ext/flask_dapr/README.rst delete mode 100644 ext/flask_dapr/pyproject.toml create mode 100644 flask_dapr/__init__.py rename dapr/__init__.pyi => flask_dapr/py.typed (100%) rename {ext/dapr-ext-workflow/dapr/ext/workflow/_durabletask/aio/internal => tests/ext}/__init__.py (100%) rename {ext/dapr-ext-workflow/dapr/ext/workflow/_durabletask/internal => tests/ext/fastapi}/__init__.py (100%) rename {ext/dapr-ext-fastapi/tests => tests/ext/fastapi}/test_app.py (99%) rename {ext/dapr-ext-fastapi/tests => tests/ext/fastapi}/test_dapractor.py (99%) rename {ext/dapr-ext-workflow/tests/durabletask => tests/ext/flask}/__init__.py (100%) rename {ext/flask_dapr/tests => tests/ext/flask}/test_app.py (99%) create mode 100644 tests/ext/flask/test_shim_deprecation.py create mode 100644 tests/ext/grpc/__init__.py rename {ext/dapr-ext-grpc/tests => tests/ext/grpc}/test_app.py (100%) rename {ext/dapr-ext-grpc/tests => tests/ext/grpc}/test_health_servicer.py (100%) rename {ext/dapr-ext-grpc/tests => tests/ext/grpc}/test_servicier.py (100%) rename {ext/dapr-ext-grpc/tests => tests/ext/grpc}/test_topic_event_response.py (100%) rename {ext/dapr-ext-langgraph/tests => tests/ext/langgraph}/__init__.py (100%) rename {ext/dapr-ext-langgraph/tests => tests/ext/langgraph}/test_checkpointer.py (99%) rename {ext/dapr-ext-strands/tests => tests/ext/strands}/__init__.py (100%) rename {ext/dapr-ext-strands/tests => tests/ext/strands}/test_session_manager.py (99%) rename {ext/dapr-ext-workflow/tests => tests/ext/workflow}/__init__.py (100%) create mode 100644 tests/ext/workflow/durabletask/__init__.py rename {ext/dapr-ext-workflow/tests => tests/ext/workflow}/durabletask/test_activity_executor.py (100%) rename {ext/dapr-ext-workflow/tests => tests/ext/workflow}/durabletask/test_client.py (100%) rename {ext/dapr-ext-workflow/tests => tests/ext/workflow}/durabletask/test_client_async.py (100%) rename {ext/dapr-ext-workflow/tests => tests/ext/workflow}/durabletask/test_concurrency_options.py (100%) rename {ext/dapr-ext-workflow/tests => tests/ext/workflow}/durabletask/test_deterministic.py (99%) rename {ext/dapr-ext-workflow/tests => tests/ext/workflow}/durabletask/test_orchestration_e2e.py (99%) rename {ext/dapr-ext-workflow/tests => tests/ext/workflow}/durabletask/test_orchestration_e2e_async.py (99%) rename {ext/dapr-ext-workflow/tests => tests/ext/workflow}/durabletask/test_orchestration_executor.py (99%) rename {ext/dapr-ext-workflow/tests => tests/ext/workflow}/durabletask/test_orchestration_wait.py (99%) rename {ext/dapr-ext-workflow/tests => tests/ext/workflow}/durabletask/test_propagation.py (99%) rename {ext/dapr-ext-workflow/tests => tests/ext/workflow}/durabletask/test_propagation_wiring.py (100%) rename {ext/dapr-ext-workflow/tests => tests/ext/workflow}/durabletask/test_registry.py (99%) rename {ext/dapr-ext-workflow/tests => tests/ext/workflow}/durabletask/test_serialization.py (99%) rename {ext/dapr-ext-workflow/tests => tests/ext/workflow}/durabletask/test_task.py (99%) rename {ext/dapr-ext-workflow/tests => tests/ext/workflow}/durabletask/test_worker_concurrency_loop.py (100%) rename {ext/dapr-ext-workflow/tests => tests/ext/workflow}/durabletask/test_worker_concurrency_loop_async.py (100%) rename {ext/dapr-ext-workflow/tests => tests/ext/workflow}/durabletask/test_worker_stop.py (99%) rename {ext/dapr-ext-workflow/tests => tests/ext/workflow}/test_dapr_workflow_context.py (100%) rename {ext/dapr-ext-workflow/tests => tests/ext/workflow}/test_mcp_client.py (100%) rename {ext/dapr-ext-workflow/tests => tests/ext/workflow}/test_mcp_schema.py (99%) rename {ext/dapr-ext-workflow/tests => tests/ext/workflow}/test_model_protocol.py (99%) rename {ext/dapr-ext-workflow/tests => tests/ext/workflow}/test_workflow_activity_context.py (100%) rename {ext/dapr-ext-workflow/tests => tests/ext/workflow}/test_workflow_client.py (99%) rename {ext/dapr-ext-workflow/tests => tests/ext/workflow}/test_workflow_client_aio.py (99%) rename {ext/dapr-ext-workflow/tests => tests/ext/workflow}/test_workflow_runtime.py (99%) rename {ext/dapr-ext-workflow/tests => tests/ext/workflow}/test_workflow_util.py (99%) diff --git a/.codecov.yml b/.codecov.yml index 3a4aa761d..0ca88d7f8 100644 --- a/.codecov.yml +++ b/.codecov.yml @@ -8,6 +8,5 @@ coverage: ignore: - dapr/proto # - Generated GRPC client - - tests # - tests + - tests # - tests (includes tests/ext// for all extensions) - .venv # - environment - - ext/dapr-ext-fastapi/tests # - fastapi extention tests diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index d340614ca..59f77f972 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -1,6 +1,6 @@ --- name: Python Dapr Client SDK Bug report (not workflow SDK) -about: Report a bug in python-sdk (not dapr-ext-workflow) +about: Report a bug in python-sdk (not dapr.ext.workflow) title: "[BUG] " labels: kind/bug assignees: '' diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index d0fbedfa4..1d37b2a46 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -1,6 +1,6 @@ --- name: Python Dapr Client SDK Feature Request (not workflow) -about: Create a Feature Request for python-sdk (not dapr-ext-workflow) +about: Create a Feature Request for python-sdk (not dapr.ext.workflow) title: "[FEATURE REQUEST] <title>" labels: kind/enhancement assignees: '' diff --git a/.github/ISSUE_TEMPLATE/workflow_bug_report.md b/.github/ISSUE_TEMPLATE/workflow_bug_report.md index 8713bc2cd..65f5911c9 100644 --- a/.github/ISSUE_TEMPLATE/workflow_bug_report.md +++ b/.github/ISSUE_TEMPLATE/workflow_bug_report.md @@ -1,6 +1,6 @@ --- name: WORKFLOW SDK Bug report -about: Report a bug in dapr-ext-workflow +about: Report a bug in dapr.ext.workflow title: "[WORKFLOW SDK BUG] <title>" labels: dapr-ext-workflow, kind/enhancement assignees: '' diff --git a/.github/ISSUE_TEMPLATE/workflow_feature_request.md b/.github/ISSUE_TEMPLATE/workflow_feature_request.md index ea38b9542..0dcb92ddb 100644 --- a/.github/ISSUE_TEMPLATE/workflow_feature_request.md +++ b/.github/ISSUE_TEMPLATE/workflow_feature_request.md @@ -1,6 +1,6 @@ --- name: WORKFLOW SDK Feature Request -about: Create a Feature Request for dapr-ext-workflow +about: Create a Feature Request for dapr.ext.workflow title: "[WORKFLOW SDK FEATURE REQUEST] <title>" labels: dapr-ext-workflow, kind/enhancement assignees: '' diff --git a/.github/workflows/build-tag.yaml b/.github/workflows/build-tag.yaml index 31bbc69ba..ade30aee8 100644 --- a/.github/workflows/build-tag.yaml +++ b/.github/workflows/build-tag.yaml @@ -68,7 +68,7 @@ jobs: run: uv run mypy - name: Run unit-tests run: | - uv run coverage run -m pytest tests ext -m "not e2e" --ignore=tests/integration --ignore=tests/examples --import-mode=importlib + uv run coverage run -m pytest tests -m "not e2e" --ignore=tests/integration --ignore=tests/examples --import-mode=importlib uv run coverage xml - name: Upload test coverage uses: codecov/codecov-action@v6 @@ -93,46 +93,14 @@ jobs: TWINE_PASSWORD: ${{ secrets.PYPI_UPLOAD_PASS }} run: | python -m build --wheel - twine upload dist/* - - name: Build and publish dapr-ext-workflow - env: - TWINE_PASSWORD: ${{ secrets.PYPI_UPLOAD_PASS }} - run: | - cd ext/dapr-ext-workflow - python -m build --wheel - twine upload dist/* - - name: Build and publish Dapr Flask Extension - env: - TWINE_PASSWORD: ${{ secrets.PYPI_UPLOAD_PASS }} - run: | - cd ext/flask_dapr - python -m build --wheel - twine upload dist/* - - name: Build and publish dapr-ext-grpc - env: - TWINE_PASSWORD: ${{ secrets.PYPI_UPLOAD_PASS }} - run: | - cd ext/dapr-ext-grpc - python -m build --wheel - twine upload dist/* - - name: Build and publish dapr-ext-fastapi - env: - TWINE_PASSWORD: ${{ secrets.PYPI_UPLOAD_PASS }} - run: | - cd ext/dapr-ext-fastapi - python -m build --wheel - twine upload dist/* - - name: Build and publish dapr-ext-langgraph - env: - TWINE_PASSWORD: ${{ secrets.PYPI_UPLOAD_PASS }} - run: | - cd ext/dapr-ext-langgraph - python -m build --wheel - twine upload dist/* - - name: Build and publish dapr-ext-strands - env: - TWINE_PASSWORD: ${{ secrets.PYPI_UPLOAD_PASS }} - run: | - cd ext/dapr-ext-strands - python -m build --wheel - twine upload dist/* + # --skip-existing makes the step retry-safe: if a previous attempt + # partially succeeded and the workflow is re-run, twine treats an + # already-uploaded file as success instead of failing the step. + twine upload --skip-existing dist/* + # The previously-separate distributions (dapr-ext-fastapi, dapr-ext-grpc, + # dapr-ext-langgraph, dapr-ext-strands, dapr-ext-workflow, flask-dapr) + # are intentionally NOT republished. Bundling the extension code into + # the `dapr` wheel means publishing a forwarding stub would leave files + # under `dapr/ext/<name>/` claimed by both distributions, and `pip + # uninstall <legacy>` would delete files that core dapr now provides. + # See RELEASE.md and the runtime warning in dapr/__init__.py. diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 34e03578a..bd24effdf 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -96,7 +96,7 @@ jobs: run: uv run mypy - name: Run unit-tests run: | - uv run coverage run -m pytest tests ext -m "not e2e" --ignore=tests/integration --ignore=tests/examples --import-mode=importlib + uv run coverage run -m pytest tests -m "not e2e" --ignore=tests/integration --ignore=tests/examples --import-mode=importlib uv run coverage xml - name: Upload test coverage uses: codecov/codecov-action@v6 diff --git a/AGENTS.md b/AGENTS.md index 02f057679..707f1ffa8 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -14,7 +14,7 @@ License: Apache 2.0 ## Project structure ``` -dapr/ # Core SDK package +dapr/ # Core SDK package (single PyPI dist: `pip install dapr`) ├── actor/ # Actor framework (virtual actor model) ├── aio/ # Async I/O modules ├── clients/ # Dapr clients (gRPC and HTTP) @@ -22,19 +22,21 @@ dapr/ # Core SDK package ├── conf/ # Configuration (settings, environment) ├── proto/ # Auto-generated gRPC protobuf stubs (DO NOT EDIT) ├── serializers/ # JSON and pluggable serializers -└── version/ # Version metadata +├── version/ # Version metadata +└── ext/ # Extensions, installable as extras to the base package + ├── fastapi/ # FastAPI integration ← see dapr/ext/fastapi/AGENTS.md (`pip install dapr[fastapi]`) + ├── flask/ # Flask integration ← see dapr/ext/flask/AGENTS.md (`pip install dapr[flask]`) + ├── grpc/ # gRPC App extension ← see dapr/ext/grpc/AGENTS.md (`pip install dapr[grpc]`) + ├── langgraph/ # LangGraph checkpointer ← see dapr/ext/langgraph/AGENTS.md (`pip install dapr[langgraph]`) + ├── strands/ # Strands agent sessions ← see dapr/ext/strands/AGENTS.md (`pip install dapr[strands]`) + └── workflow/ # Workflow authoring ← see dapr/ext/workflow/AGENTS.md (`pip install dapr[workflow]`) -ext/ # Extension packages (each is a separate PyPI package) -├── dapr-ext-workflow/ # Workflow authoring ← see ext/dapr-ext-workflow/AGENTS.md -├── dapr-ext-grpc/ # gRPC App extension ← see ext/dapr-ext-grpc/AGENTS.md -├── dapr-ext-fastapi/ # FastAPI integration ← see ext/dapr-ext-fastapi/AGENTS.md -├── dapr-ext-langgraph/ # LangGraph checkpointer ← see ext/dapr-ext-langgraph/AGENTS.md -├── dapr-ext-strands/ # Strands agent sessions ← see ext/dapr-ext-strands/AGENTS.md -└── flask_dapr/ # Flask integration ← see ext/flask_dapr/AGENTS.md +flask_dapr/ # Deprecation shim: re-exports dapr.ext.flask with FutureWarning tests/ # Unit tests (mirrors dapr/ package structure) -├── examples/ # Output-based tests that run examples and check stdout -├── integration/ # Programmatic SDK tests using DaprClient directly +├── ext/ # Extension tests, one subdir per extension +├── examples/ # Output-based tests that run examples and check stdout +├── integration/ # Programmatic SDK tests using DaprClient directly examples/ # User-facing example applications ← see examples/AGENTS.md docs/ # Sphinx documentation source tools/ # Build and release scripts @@ -42,7 +44,7 @@ tools/ # Build and release scripts ## Key architectural patterns -- **Namespace packages**: The `dapr` namespace is shared across the core SDK and extensions via `find_namespace_packages`. Extensions live in `ext/` but install into the `dapr.ext.*` namespace. Do not add `__init__.py` to namespace package roots in extensions. +- **Namespace packages**: `dapr.ext` is an implicit PEP 420 namespace package. See the Gotchas section below before adding anything at that path. - **Client architecture**: `DaprGrpcClient` (primary, high-performance) and HTTP-based clients. Both implement shared interfaces. - **Actor model**: `Actor` base class, `ActorInterface` with `@actormethod` decorator, `ActorProxy`/`ActorProxyFactory` for client-side references, `ActorRuntime` for server-side hosting. - **Serialization**: Pluggable via `Serializer` base class. `DefaultJSONSerializer` is the default. @@ -50,16 +52,18 @@ tools/ # Build and release scripts ## Extension overview -Each extension is a **separate PyPI package** with its own `pyproject.toml`, `setup.py`, `tests/`, and `AGENTS.md`. +Extensions are bundled into the core `dapr` wheel and exposed as installable extras. Each one lives under `dapr/ext/<name>/` with its own `AGENTS.md`. -| Extension | Package | Purpose | Active development | -|-----------|---------|---------|-------------------| -| `dapr-ext-workflow` | `dapr.ext.workflow` | Durable workflow orchestration (durabletask vendored internally) | **High** — major focus area | -| `dapr-ext-grpc` | `dapr.ext.grpc` | gRPC server for Dapr callbacks (methods, pub/sub, bindings, jobs) | Moderate | -| `dapr-ext-fastapi` | `dapr.ext.fastapi` | FastAPI integration for pub/sub and actors | Moderate | -| `flask_dapr` | `flask_dapr` | Flask integration for pub/sub and actors | Low | -| `dapr-ext-langgraph` | `dapr.ext.langgraph` | LangGraph checkpoint persistence to Dapr state store | Moderate | -| `dapr-ext-strands` | `dapr.ext.strands` | Strands agent session management via Dapr state store | New | +| Extra | Import path | Purpose | Active development | +|-------|-------------|---------|--------------------| +| `dapr[workflow]` | `dapr.ext.workflow` | Durable workflow orchestration (durabletask vendored internally) | **High**, major focus area | +| `dapr[grpc]` | `dapr.ext.grpc` | gRPC server for Dapr callbacks (methods, pub/sub, bindings, jobs) | Moderate | +| `dapr[fastapi]` | `dapr.ext.fastapi` | FastAPI integration for pub/sub and actors | Moderate | +| `dapr[flask]` | `dapr.ext.flask` | Flask integration for pub/sub and actors (legacy `flask_dapr` import path is a deprecated shim) | Low | +| `dapr[langgraph]` | `dapr.ext.langgraph` | LangGraph checkpoint persistence to Dapr state store | Moderate | +| `dapr[strands]` | `dapr.ext.strands` | Strands agent session management via Dapr state store | New | + +The previously-separate distributions (`dapr-ext-*`, `flask-dapr`) are no longer published. `dapr/__init__.py` emits a `FutureWarning` if it detects a legacy install at import time; see `RELEASE.md` for the migration recipe. ## Examples and testing @@ -95,17 +99,20 @@ uv sync --all-packages --group dev Tests use Python's built-in `unittest` framework with `coverage`. The vendored durabletask tests use `pytest`. ```bash -# Run all unit tests -uv run python -m unittest discover -v ./tests - -# Extension tests (run each separately) -uv run python -m unittest discover -v ./ext/dapr-ext-workflow/tests -uv run pytest -m "not e2e" ./ext/dapr-ext-workflow/tests/durabletask/ -uv run python -m unittest discover -v ./ext/dapr-ext-grpc/tests -uv run python -m unittest discover -v ./ext/dapr-ext-fastapi/tests -uv run python -m unittest discover -v ./ext/dapr-ext-langgraph/tests -uv run python -m unittest discover -v ./ext/dapr-ext-strands/tests -uv run python -m unittest discover -v ./ext/flask_dapr/tests +# All unit tests. pytest is required: `unittest discover` silently skips the +# pytest-style tests under tests/ext/flask and tests/ext/workflow/durabletask. +uv run pytest -m "not e2e" ./tests --ignore=tests/integration --ignore=tests/examples + +# Single extension (unittest discover works for these — no pytest-style tests): +uv run python -m unittest discover -v ./tests/ext/workflow +uv run python -m unittest discover -v ./tests/ext/grpc +uv run python -m unittest discover -v ./tests/ext/fastapi +uv run python -m unittest discover -v ./tests/ext/langgraph +uv run python -m unittest discover -v ./tests/ext/strands + +# pytest-style suites: +uv run pytest -m "not e2e" ./tests/ext/workflow/durabletask/ +uv run pytest ./tests/ext/flask/test_shim_deprecation.py # Run linting and formatting uv run ruff check --fix && uv run ruff format @@ -143,7 +150,7 @@ uv run ruff check --fix && uv run ruff format uv run mypy ``` -MyPy is configured to check: `dapr/actor/`, `dapr/aio/`, `dapr/clients/`, `dapr/conf/`, `dapr/serializers/`, `ext/dapr-ext-grpc/`, `ext/dapr-ext-fastapi/`, `ext/flask_dapr/`, and `examples/demo_actor/`. Proto stubs (`dapr.proto.*`) have errors ignored. Configuration lives in `pyproject.toml` under `[tool.mypy]`. +MyPy checks the `dapr` and `flask_dapr` packages (covering all bundled extensions under `dapr.ext.*`). Proto stubs (`dapr.proto.*`) have errors ignored, and unstubbed third-party libs (`langgraph.*`, `langchain.*`, `strands.*`, `strands_agents.*`, `grpc.aio`) are marked `ignore_missing_imports`. Configuration in `pyproject.toml` under `[tool.mypy]`. ## Commit and PR conventions @@ -171,14 +178,14 @@ When completing any task on this project, work through this checklist. Not every ### Unit tests -- [ ] Add or update unit tests under `tests/` (core SDK) or `ext/*/tests/` (extensions) -- [ ] Tests use `unittest` — follow the existing test patterns in the relevant directory -- [ ] Verify tests pass: `python -m unittest discover -v ./tests` (or the relevant test directory) +- [ ] Add or update unit tests under `tests/` (core SDK) or `tests/ext/<name>/` (extensions) +- [ ] Tests are predominantly `unittest.TestCase`; follow the existing patterns in the relevant directory. A few pytest-style tests exist for fixture-dependent scenarios (e.g. `pytest.warns` for the `flask_dapr` shim). +- [ ] Verify tests pass: `uv run pytest -m "not e2e" ./tests --ignore=tests/integration --ignore=tests/examples` (must use pytest; `unittest discover` silently skips pytest-style tests) ### Linting and type checking - [ ] Run `uv run ruff check --fix && uv run ruff format` and fix any remaining issues -- [ ] Run `uv run mypy` if you changed files covered by mypy (actor, aio, clients, conf, serializers, ext-grpc, ext-fastapi, flask_dapr) +- [ ] Run `uv run mypy` if you changed files covered by mypy (the `dapr` and `flask_dapr` packages, which includes all bundled extensions under `dapr.ext.*`) ### Examples (integration tests) @@ -195,7 +202,7 @@ When completing any task on this project, work through this checklist. Not every ### Final verification - [ ] Run `uv run ruff check --fix && uv run ruff format` — linting must be clean -- [ ] Run `uv run python -m unittest discover -v ./tests` — all unit tests must pass +- [ ] Run `uv run pytest -m "not e2e" ./tests --ignore=tests/integration --ignore=tests/examples` — all unit tests must pass - [ ] If you touched examples: `uv run pytest tests/examples/test_<example-name>.py` to validate locally - [ ] Commits must be signed off for DCO: `git commit -s` @@ -203,21 +210,20 @@ When completing any task on this project, work through this checklist. Not every | File | Purpose | |------|---------| -| `pyproject.toml` | Package metadata, dependencies, ruff, mypy, and uv workspace config | +| `pyproject.toml` | Package metadata, extras, dependencies, ruff, mypy, and uv workspace config | | `uv.lock` | Locked dependency versions (reproducible installs) | -| `setup.py` | PyPI publish helper (handles dev version suffixing) | -| `ext/*/pyproject.toml` | Extension package metadata and dependencies | +| `dapr/__init__.py` | Imports `_detect_legacy_extension_dists` to warn about legacy `dapr-ext-*` / `flask-dapr` installs that collide with the bundled extension files | | `dapr/version/version.py` | SDK version string | | `tests/examples/` | Output-based tests that validate examples by checking stdout | | `tests/integration/` | Programmatic SDK tests using DaprClient directly | ## Gotchas -- **Namespace packages**: Do not add `__init__.py` to the top-level `dapr/` directory in extensions — it will break namespace package resolution. +- **Namespace packages**: `dapr.ext` is a PEP 420 implicit namespace package. Do **not** create `dapr/ext/__init__.py`; that would block any future externally-published `dapr.ext.*` distribution from coexisting with the core wheel on install. - **Proto files**: Never manually edit anything under `dapr/proto/`. These are generated. -- **Extension independence**: Each extension is a separate PyPI package. Core SDK changes should not break extensions; extension changes should not require core SDK changes unless intentional. +- **Bundled extensions**: live under `dapr/ext/<name>/`, opted in via extras (`dapr[fastapi]`, etc.). The legacy `dapr-ext-*` and `flask-dapr` distributions are no longer published; legacy installs must be uninstalled before upgrading or `import dapr` will emit a `FutureWarning`. - **DCO signoff**: PRs will be blocked by the DCO bot if commits lack `Signed-off-by`. Always use `git commit -s`. - **Ruff version pinned**: `pyproject.toml` pins `ruff==0.14.1` in `[dependency-groups].dev`. Use `uv sync --all-packages --group dev` to get the exact version. - **Examples are tested by output matching**: Changing output format (log messages, print statements) can break `tests/examples/`. Always check expected output there when modifying user-visible output. - **Background processes in examples**: Examples that start background services (servers, subscribers) must include a cleanup step to stop them, or CI will hang. -- **Workflow is the most active area**: See `ext/dapr-ext-workflow/AGENTS.md` for workflow-specific architecture and constraints. +- **Workflow is the most active area**: See `dapr/ext/workflow/AGENTS.md` for workflow-specific architecture and constraints. diff --git a/README.md b/README.md index 44bfa49e0..b1ccf01db 100644 --- a/README.md +++ b/README.md @@ -23,9 +23,15 @@ This includes the following packages: * [dapr.conf](./dapr/conf): Configuration * [dapr.serializers](./dapr/serializers): serializer/deserializer * [dapr.proto](./dapr/proto): Dapr gRPC autogenerated gRPC clients -* [dapr.ext.grpc](./ext/dapr-ext-grpc): gRPC extension for Dapr -* [dapr.ext.fastapi](./ext/dapr-ext-fastapi): FastAPI extension (actor) for Dapr -* [flask.dapr](./ext/flask_dapr): Flask extension (actor) for Dapr + +And the following extensions, installed as extras on the core `dapr` package: + +* [dapr.ext.fastapi](./dapr/ext/fastapi): FastAPI integration (actors, pub/sub) — `pip install "dapr[fastapi]"` +* [dapr.ext.flask](./dapr/ext/flask): Flask integration (actors, pub/sub) — `pip install "dapr[flask]"` +* [dapr.ext.grpc](./dapr/ext/grpc): gRPC AppCallback server — `pip install "dapr[grpc]"` +* [dapr.ext.langgraph](./dapr/ext/langgraph): LangGraph checkpoint persistence — `pip install "dapr[langgraph]"` +* [dapr.ext.strands](./dapr/ext/strands): Strands agent session management — `pip install "dapr[strands]"` +* [dapr.ext.workflow](./dapr/ext/workflow): Durable workflow authoring — `pip install "dapr[workflow]"` ## Getting started @@ -39,16 +45,38 @@ This includes the following packages: * Official package ```sh -# Install Dapr client sdk +# Install the Dapr client SDK pip3 install dapr -# Install Dapr gRPC AppCallback service extension -pip3 install dapr-ext-grpc +# Install one or more extensions as extras +pip3 install "dapr[fastapi]" +pip3 install "dapr[grpc,workflow]" -# Install Dapr Fast Api extension for Actor -pip3 install dapr-ext-fastapi +# Or install everything +pip3 install "dapr[all]" ``` +> **Migration from legacy distributions.** The previously-separate packages +> (`dapr-ext-fastapi`, `dapr-ext-grpc`, `dapr-ext-langgraph`, `dapr-ext-strands`, +> `dapr-ext-workflow`, `flask-dapr`) are now extras on the core `dapr` package +> and are no longer published standalone. Import paths under `dapr.ext.*` are +> unchanged. +> +> Existing installs must run all three steps below in order so pip rewrites +> the bundled files the legacy uninstall removes, without churning pinned +> transitive deps (fastapi, uvicorn, langchain, etc.): +> +> ```sh +> pip uninstall -y dapr-ext-fastapi dapr-ext-grpc dapr-ext-langgraph dapr-ext-strands dapr-ext-workflow flask-dapr +> pip install --force-reinstall --no-deps dapr +> pip install "dapr[fastapi,workflow]" +> ``` +> +> `import dapr` emits a `FutureWarning` with the recovery command if the +> migration is skipped. Suppress with `DAPR_SKIP_LEGACY_CHECK=1`. The +> legacy `flask_dapr` top-level import remains as a thin shim that also +> emits a `FutureWarning`; the canonical path is `dapr.ext.flask`. + * In-development version Only tagged releases are published to PyPI. To install the in-development @@ -58,11 +86,8 @@ version (the current state of `main`), point pip at the GitHub repository: # Install the latest dev build of the Dapr client sdk pip3 install "dapr @ git+https://github.com/dapr/python-sdk.git@main" -# Install the latest dev build of the gRPC AppCallback service extension -pip3 install "dapr-ext-grpc @ git+https://github.com/dapr/python-sdk.git@main#subdirectory=ext/dapr-ext-grpc" - -# Install the latest dev build of the FastAPI extension for Actor -pip3 install "dapr-ext-fastapi @ git+https://github.com/dapr/python-sdk.git@main#subdirectory=ext/dapr-ext-fastapi" +# Install the latest dev build of the gRPC AppCallback and FastAPI for Actor extensions +pip3 install "dapr[grpc,fastapi] @ git+https://github.com/dapr/python-sdk.git@main" ``` Replace `@main` with a commit SHA or release branch (e.g. `@release-1.17`) @@ -100,7 +125,9 @@ uv run ruff check --fix && uv run ruff format 5. Run unit tests ```bash -uv run python -m unittest discover -v ./tests +# pytest is required: `unittest discover` silently skips the pytest-style +# tests under tests/ext/flask and tests/ext/workflow/durabletask. +uv run pytest -m "not e2e" ./tests --ignore=tests/integration --ignore=tests/examples ``` 6. Run type check diff --git a/RELEASE.md b/RELEASE.md index c3fe5476d..5e94a6a8c 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -2,17 +2,34 @@ This document describes the release process for the Dapr Python SDK. -A single tag (`v*`) triggers the release of **all packages** published from this repository: - -| PyPI package | -|---| -| `dapr` (core SDK) | -| `dapr-ext-workflow` | -| `dapr-ext-grpc` | -| `dapr-ext-fastapi` | -| `flask_dapr` | -| `dapr-ext-langgraph` | -| `dapr-ext-strands` | +A single tag (`v*`) triggers the release of the core SDK only: + +| PyPI package | Notes | +|---|---| +| `dapr` (core SDK) | Includes every extension under `dapr.ext.*`. Users opt in to per-extension third-party deps via extras: `pip install "dapr[fastapi]"`, etc. The legacy top-level `flask_dapr` import path remains available as a thin shim inside this wheel and emits `FutureWarning`. | + +**The previously-separate distributions** — `dapr-ext-fastapi`, `dapr-ext-grpc`, +`dapr-ext-langgraph`, `dapr-ext-strands`, `dapr-ext-workflow`, `flask-dapr` — +are **no longer published**. Republishing them as `dapr-ext-name` shims that +depend on `dapr[name]` was considered but rejected: any shim that doesn't carry +the actual extension code creates a `RECORD` ownership conflict with the legacy +versions in existing user environments, and `pip uninstall` of a legacy package would +delete files that core `dapr` now provides. + +Existing installs must migrate explicitly: + +```sh +pip uninstall -y dapr-ext-fastapi dapr-ext-grpc dapr-ext-langgraph dapr-ext-strands dapr-ext-workflow flask-dapr +pip install --force-reinstall --no-deps dapr +pip install "dapr[<extras>]" +``` + +`--force-reinstall --no-deps dapr` rewrites the `dapr/ext/<name>/` files the +legacy uninstall removed; keeping it separate from the extras install avoids +churning user-pinned versions of fastapi, uvicorn, langchain, etc. +`dapr/__init__.py` detects both the legacy-installed and post-uninstall +states at import time and prints the recovery command as a `FutureWarning`. +Suppress with `DAPR_SKIP_LEGACY_CHECK=1`. You can also create the tag via a **GitHub Release**, which auto-creates the tag and provides a changelog UI. diff --git a/dapr/__init__.py b/dapr/__init__.py new file mode 100644 index 000000000..4f46a0983 --- /dev/null +++ b/dapr/__init__.py @@ -0,0 +1,184 @@ +# -*- coding: utf-8 -*- + +""" +Copyright 2026 The Dapr Authors +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +""" + +# On import, checks for two states a legacy dapr-ext-* install could leave +# the environment in. +# +# 1. Legacy `dapr-ext-*` or `flask-dapr` dist still installed alongside +# core dapr. +# Pre-1.19 each extension was its own dist owning files under +# `dapr/ext/<name>/`, the new core wheel ships those same files. +# pip has no cross-dist ownership awareness, so `pip uninstall <legacy>` +# walks the legacy RECORD and deletes `dapr/ext/<name>/*.py` from disk. End +# state: `pip show dapr` reports OK, but `from dapr.ext.<name> import ...` +# raises ModuleNotFoundError. +# +# 2. Legacy already uninstalled with no follow-up `--force-reinstall dapr`, +# leaving the bundled paths missing on disk (the #1 failure mode, after +# the fact). +# +# Both checks swallow exceptions so unrelated metadata quirks cannot break +# `import dapr`. Set `DAPR_SKIP_LEGACY_CHECK=1` to suppress. + +from __future__ import annotations + +import importlib.metadata +import os +import sys +import warnings +from pathlib import Path + +# Legacy dist name -> directory it shipped under in its pre-1.19 wheel layout. +_LEGACY_DISTS_WITH_BUNDLED_PATHS: dict[str, str] = { + 'dapr-ext-fastapi': 'dapr/ext/fastapi', + 'dapr-ext-grpc': 'dapr/ext/grpc', + 'dapr-ext-langgraph': 'dapr/ext/langgraph', + 'dapr-ext-strands': 'dapr/ext/strands', + 'dapr-ext-workflow': 'dapr/ext/workflow', + 'flask-dapr': 'flask_dapr', +} + + +def _safe_dist_version(dist: importlib.metadata.Distribution) -> str: + try: + return dist.version + except Exception: + return '<unknown>' + + +def _detect_legacy_extension_dists() -> list[str]: + """Return `name==version` for installed legacy ext distributions. + + Confirms legacy status by checking that the dist actually owns files + under the bundled path. When RECORD is missing (Debian python3-*, some + conda channels, sdist --no-binary), conservatively flag the install. + """ + legacy: list[str] = [] + for dist_name, bundled_path_prefix in _LEGACY_DISTS_WITH_BUNDLED_PATHS.items(): + try: + dist = importlib.metadata.distribution(dist_name) + except importlib.metadata.PackageNotFoundError: + continue + except Exception: + continue + + try: + files = dist.files + except Exception: + files = None + + if files is None: + legacy.append(f'{dist_name}=={_safe_dist_version(dist)}') + continue + + ships_bundled_path = any( + str(installed_file).startswith(bundled_path_prefix + '/') for installed_file in files + ) + if ships_bundled_path: + legacy.append(f'{dist_name}=={_safe_dist_version(dist)}') + return legacy + + +def _detect_missing_bundled_files() -> list[str]: + """Return bundled extension dirs whose `__init__.py` is missing on disk. + + Catches the post-uninstall, pre-reinstall state. Bails out when dapr is + loaded from a non-filesystem source (zipapp, frozen bundle) to avoid + false positives from custom loaders. + """ + try: + dapr_root = Path(__file__).resolve().parent + except OSError: + return [] + if not dapr_root.is_dir(): + # dapr is loaded from a zipapp / frozen / non-filesystem source; + # the filesystem layout assumption doesn't apply. + return [] + + site_root = dapr_root.parent + missing: list[str] = [] + for bundled_path_prefix in _LEGACY_DISTS_WITH_BUNDLED_PATHS.values(): + # `dapr/ext/<name>` lives under our package; `flask_dapr` is a sibling + # top-level shim at the site-packages root. + if bundled_path_prefix.startswith('dapr/'): + init_file = dapr_root / bundled_path_prefix[len('dapr/') :] / '__init__.py' + else: + init_file = site_root / bundled_path_prefix / '__init__.py' + try: + if not init_file.is_file(): + missing.append(bundled_path_prefix) + except OSError: + continue + return missing + + +def _emit_legacy_warning(message: str) -> None: + """Emit a FutureWarning, falling back to stderr under `-W error`. + + Some CI environments set `PYTHONWARNINGS=error`, which would otherwise + crash `import dapr`. stacklevel=4 lands on the user's `import dapr`: + warn -> _emit -> _check -> module body. + """ + try: + warnings.warn(message, FutureWarning, stacklevel=4) + except FutureWarning: + # `-W error::FutureWarning` (or broader) escalated the warning. + # Fall back to stderr so the user still sees the migration recipe. + print(f'dapr: FutureWarning: {message}', file=sys.stderr) + + +def _check_for_legacy_extension_issues() -> None: + """Run both detectors and emit at most one warning.""" + if os.environ.get('DAPR_SKIP_LEGACY_CHECK', '').strip().lower() in {'1', 'true', 'yes', 'on'}: + return + + try: + legacy_installs = _detect_legacy_extension_dists() + except Exception: + legacy_installs = [] + + if legacy_installs: + legacy_names = ' '.join(spec.split('==', 1)[0] for spec in legacy_installs) + _emit_legacy_warning( + f'Legacy Dapr extension distributions installed alongside core dapr: ' + f'{", ".join(legacy_installs)}. As of dapr 1.19 these ship inside the ' + f'core `dapr` wheel under `dapr.ext.*` and are opt-in via extras. ' + f'To migrate:\n' + f' pip uninstall -y {legacy_names}\n' + f' pip install --force-reinstall --no-deps dapr\n' + f' pip install "dapr[<extras>]"' + ) + return + + try: + missing_paths = _detect_missing_bundled_files() + except Exception: + missing_paths = [] + + if missing_paths: + _emit_legacy_warning( + f'Bundled Dapr extension paths missing on disk: {", ".join(missing_paths)}. ' + f'A prior `pip uninstall dapr-ext-*` removed files now owned by core ' + f'`dapr`. Restore with:\n' + f' pip install --force-reinstall --no-deps dapr\n' + f' pip install "dapr[<extras>]"' + ) + + +try: + _check_for_legacy_extension_issues() +except Exception: + # Never break `import dapr` for unrelated metadata quirks. + pass diff --git a/ext/dapr-ext-fastapi/AGENTS.md b/dapr/ext/fastapi/AGENTS.md similarity index 77% rename from ext/dapr-ext-fastapi/AGENTS.md rename to dapr/ext/fastapi/AGENTS.md index 1651ccec2..2996230f8 100644 --- a/ext/dapr-ext-fastapi/AGENTS.md +++ b/dapr/ext/fastapi/AGENTS.md @@ -1,23 +1,23 @@ -# AGENTS.md — dapr-ext-fastapi +# AGENTS.md — dapr.ext.fastapi The FastAPI extension provides two integration classes for building Dapr applications with [FastAPI](https://fastapi.tiangolo.com/): `DaprApp` for pub/sub subscriptions and `DaprActor` for actor hosting. ## Source layout ``` -ext/dapr-ext-fastapi/ -├── pyproject.toml # Deps: dapr, uvicorn, fastapi -├── setup.py -├── tests/ -│ ├── test_app.py # DaprApp pub/sub tests -│ └── test_dapractor.py # DaprActor response wrapping + route tests -└── dapr/ext/fastapi/ - ├── __init__.py # Exports: DaprApp, DaprActor - ├── app.py # DaprApp — pub/sub subscription handler - ├── actor.py # DaprActor — actor runtime HTTP adapter - └── version.py +dapr/ext/fastapi/ +├── __init__.py # Exports: DaprApp, DaprActor +├── app.py # DaprApp — pub/sub subscription handler +├── actor.py # DaprActor — actor runtime HTTP adapter +└── py.typed + +tests/ext/fastapi/ +├── test_app.py # DaprApp pub/sub tests +└── test_dapractor.py # DaprActor response wrapping + route tests ``` +Installed via the `fastapi` extra: `pip install "dapr[fastapi]"`. See `RELEASE.md` for migration from the legacy `dapr-ext-fastapi` distribution. + ## Public API ```python @@ -71,16 +71,16 @@ Method invocation extracts `Dapr-Reentrancy-Id` header for reentrant actor calls **Error handling**: Catches `DaprInternalError` and generic `Exception`, returns 500 with error details. -## Dependencies +## Dependencies (declared via the `fastapi` extra in the root `pyproject.toml`) -- `dapr >= 1.17.0.dev` -- `fastapi >= 0.60.1` -- `uvicorn >= 0.11.6` +- `dapr` (core, same wheel as this extension) +- `fastapi >= 0.60.1, < 1.0.0` +- `uvicorn >= 0.11.6, < 1.0.0` ## Testing ```bash -python -m unittest discover -v ./ext/dapr-ext-fastapi/tests +uv run python -m unittest discover -v ./tests/ext/fastapi ``` - `test_app.py` — uses FastAPI `TestClient` for HTTP-level testing: subscription registration, custom routes, metadata, dead letter topics, router tags diff --git a/dapr/ext/fastapi/README.md b/dapr/ext/fastapi/README.md new file mode 100644 index 000000000..7b6d8dbef --- /dev/null +++ b/dapr/ext/fastapi/README.md @@ -0,0 +1,15 @@ +# dapr.ext.fastapi + +FastAPI integration for the Dapr Python SDK. Provides `DaprApp` for pub/sub +subscriptions and `DaprActor` for actor hosting. + +```sh +pip install "dapr[fastapi]" +``` + +```python +from dapr.ext.fastapi import DaprApp, DaprActor +``` + +See the root [README](../../../README.md) for migration steps from the legacy +`dapr-ext-fastapi` distribution. \ No newline at end of file diff --git a/ext/dapr-ext-fastapi/dapr/ext/fastapi/__init__.py b/dapr/ext/fastapi/__init__.py similarity index 69% rename from ext/dapr-ext-fastapi/dapr/ext/fastapi/__init__.py rename to dapr/ext/fastapi/__init__.py index e43df65c9..ac9c49002 100644 --- a/ext/dapr-ext-fastapi/dapr/ext/fastapi/__init__.py +++ b/dapr/ext/fastapi/__init__.py @@ -13,7 +13,13 @@ limitations under the License. """ -from .actor import DaprActor -from .app import DaprApp +try: + from .actor import DaprActor + from .app import DaprApp +except ImportError as exc: + raise ImportError( + f'dapr.ext.fastapi is missing an optional dependency ({exc.name!r}). ' + f'Install the extension with: pip install "dapr[fastapi]"' + ) from exc __all__ = ['DaprActor', 'DaprApp'] diff --git a/ext/dapr-ext-fastapi/dapr/ext/fastapi/actor.py b/dapr/ext/fastapi/actor.py similarity index 100% rename from ext/dapr-ext-fastapi/dapr/ext/fastapi/actor.py rename to dapr/ext/fastapi/actor.py diff --git a/ext/dapr-ext-fastapi/dapr/ext/fastapi/app.py b/dapr/ext/fastapi/app.py similarity index 100% rename from ext/dapr-ext-fastapi/dapr/ext/fastapi/app.py rename to dapr/ext/fastapi/app.py diff --git a/ext/dapr-ext-fastapi/dapr/ext/fastapi/py.typed b/dapr/ext/fastapi/py.typed similarity index 100% rename from ext/dapr-ext-fastapi/dapr/ext/fastapi/py.typed rename to dapr/ext/fastapi/py.typed diff --git a/ext/flask_dapr/AGENTS.md b/dapr/ext/flask/AGENTS.md similarity index 58% rename from ext/flask_dapr/AGENTS.md rename to dapr/ext/flask/AGENTS.md index 42a5429f2..8be3a6d55 100644 --- a/ext/flask_dapr/AGENTS.md +++ b/dapr/ext/flask/AGENTS.md @@ -1,28 +1,29 @@ -# AGENTS.md — flask_dapr +# AGENTS.md — dapr.ext.flask The Flask extension provides two integration classes for building Dapr applications with [Flask](https://flask.palletsprojects.com/): `DaprApp` for pub/sub subscriptions and `DaprActor` for actor hosting. It mirrors the FastAPI extension's functionality but uses Flask's routing and request model. ## Source layout ``` -ext/flask_dapr/ -├── pyproject.toml # Deps: dapr, Flask -├── setup.py -├── tests/ -│ └── test_app.py # DaprApp pub/sub tests -└── flask_dapr/ - ├── __init__.py # Exports: DaprApp, DaprActor - ├── app.py # DaprApp — pub/sub subscription handler - ├── actor.py # DaprActor — actor runtime HTTP adapter - └── version.py +dapr/ext/flask/ +├── __init__.py # Exports: DaprApp, DaprActor +├── app.py # DaprApp — pub/sub subscription handler +├── actor.py # DaprActor — actor runtime HTTP adapter +└── py.typed + +tests/ext/flask/ +├── test_app.py # DaprApp pub/sub tests +└── test_shim_deprecation.py # Locks the legacy `flask_dapr` shim contract ``` -Note: Unlike other extensions, this package uses `flask_dapr` as its top-level namespace (not `dapr.ext.*`). +Installed via the `flask` extra on core dapr: `pip install "dapr[flask]"`. + +The legacy top-level import path (`from flask_dapr import DaprApp, DaprActor`) is still supported through a thin shim at the repo root that emits a `FutureWarning`. The shim is scheduled for removal one release after the bundling change ships. All new code and docs should use the canonical `from dapr.ext.flask import ...` path. ## Public API ```python -from flask_dapr import DaprApp, DaprActor +from dapr.ext.flask import DaprApp, DaprActor ``` ### DaprApp (`app.py`) @@ -34,7 +35,7 @@ app = Flask('myapp') dapr_app = DaprApp(app) @dapr_app.subscribe(pubsub='pubsub', topic='orders', route='/handle-order', - metadata={}, dead_letter_topic=None) + metadata={}, dead_letter_topic=None) def handle_order(): event_data = request.json return 'ok' @@ -65,24 +66,29 @@ Auto-registers six endpoints (same as FastAPI extension): **Response wrapping** (`wrap_response`): Same pattern as FastAPI extension — string → JSON, bytes → raw, dict → JSON. Error responses include `errorCode` field. -## Dependencies +## Dependencies (declared via the `flask` extra in the root `pyproject.toml`) -- `dapr >= 1.17.0.dev` -- `Flask >= 1.1` +- `dapr` (core, same wheel as this extension) +- `Flask >= 1.1.4, < 4.0.0` ## Testing ```bash -python -m unittest discover -v ./ext/flask_dapr/tests +# Unittest-style tests (test_app.py) +uv run python -m unittest discover -v ./tests/ext/flask + +# The shim deprecation test is pytest-style — run with pytest +uv run pytest tests/ext/flask ``` - `test_app.py` — uses Flask `test_client()` for HTTP-level testing: subscription registration, custom routes, metadata, dead letter topics +- `test_shim_deprecation.py` — asserts that `import flask_dapr` emits `FutureWarning` and re-exports `DaprApp`/`DaprActor` correctly Note: No tests for `DaprActor` in this extension (unlike FastAPI which tests `_wrap_response`). ## Key details - **Synchronous + asyncio bridge**: Flask is sync, but `ActorRuntime` is async. The extension uses `asyncio.run()` for each actor operation. -- **Different namespace**: This is `flask_dapr`, not `dapr.ext.flask`. Import as `from flask_dapr import DaprApp, DaprActor`. +- **Canonical import path**: Use `from dapr.ext.flask import DaprApp, DaprActor`. The legacy `flask_dapr` top-level path still works but emits `FutureWarning` and will be removed next cycle. - **Similar to FastAPI extension**: The two extensions have nearly identical functionality. When modifying one, check if the same change is needed in the other. -- **Reentrancy ID**: Actor method invocation extracts `Dapr-Reentrancy-Id` header, same as FastAPI extension. +- **Reentrancy ID**: Actor method invocation extracts `Dapr-Reentrancy-Id` header, same as FastAPI extension. \ No newline at end of file diff --git a/dapr/ext/flask/README.md b/dapr/ext/flask/README.md new file mode 100644 index 000000000..62990ad7c --- /dev/null +++ b/dapr/ext/flask/README.md @@ -0,0 +1,25 @@ +# dapr.ext.flask + +Flask integration for the Dapr Python SDK. Provides `DaprApp` for pub/sub +subscriptions and `DaprActor` for actor hosting. + +```sh +pip install "dapr[flask]" +``` + +```python +from flask import Flask, request +from dapr.ext.flask import DaprApp + +app = Flask('myapp') +dapr_app = DaprApp(app) + +@dapr_app.subscribe(pubsub='pubsub', topic='some_topic', route='/some_endpoint') +def my_event_handler(): + # request.data contains the pubsub event + pass +``` + +The legacy top-level `flask_dapr` import path is still available as a thin +shim that emits a `FutureWarning`. See the root [README](../../../README.md) +for migration steps from the legacy `flask-dapr` distribution. \ No newline at end of file diff --git a/ext/flask_dapr/flask_dapr/__init__.py b/dapr/ext/flask/__init__.py similarity index 69% rename from ext/flask_dapr/flask_dapr/__init__.py rename to dapr/ext/flask/__init__.py index e43df65c9..272f6e41a 100644 --- a/ext/flask_dapr/flask_dapr/__init__.py +++ b/dapr/ext/flask/__init__.py @@ -13,7 +13,13 @@ limitations under the License. """ -from .actor import DaprActor -from .app import DaprApp +try: + from .actor import DaprActor + from .app import DaprApp +except ImportError as exc: + raise ImportError( + f'dapr.ext.flask is missing an optional dependency ({exc.name!r}). ' + f'Install the extension with: pip install "dapr[flask]"' + ) from exc __all__ = ['DaprActor', 'DaprApp'] diff --git a/ext/flask_dapr/flask_dapr/actor.py b/dapr/ext/flask/actor.py similarity index 99% rename from ext/flask_dapr/flask_dapr/actor.py rename to dapr/ext/flask/actor.py index c8bdf1a50..f435efe0b 100644 --- a/ext/flask_dapr/flask_dapr/actor.py +++ b/dapr/ext/flask/actor.py @@ -16,11 +16,10 @@ import asyncio from typing import Any, Optional, Type -from flask import jsonify, make_response, request - from dapr.actor import Actor, ActorRuntime from dapr.clients.exceptions import ERROR_CODE_UNKNOWN, DaprInternalError from dapr.serializers import DefaultJSONSerializer +from flask import jsonify, make_response, request DEFAULT_CONTENT_TYPE = 'application/json; utf-8' DAPR_REENTRANCY_ID_HEADER = 'Dapr-Reentrancy-Id' diff --git a/ext/flask_dapr/flask_dapr/app.py b/dapr/ext/flask/app.py similarity index 100% rename from ext/flask_dapr/flask_dapr/app.py rename to dapr/ext/flask/app.py diff --git a/ext/dapr-ext-grpc/dapr/ext/grpc/py.typed b/dapr/ext/flask/py.typed similarity index 100% rename from ext/dapr-ext-grpc/dapr/ext/grpc/py.typed rename to dapr/ext/flask/py.typed diff --git a/ext/dapr-ext-grpc/AGENTS.md b/dapr/ext/grpc/AGENTS.md similarity index 84% rename from ext/dapr-ext-grpc/AGENTS.md rename to dapr/ext/grpc/AGENTS.md index b07bb043c..a802e6f5d 100644 --- a/ext/dapr-ext-grpc/AGENTS.md +++ b/dapr/ext/grpc/AGENTS.md @@ -1,26 +1,26 @@ -# AGENTS.md — dapr-ext-grpc +# AGENTS.md — dapr.ext.grpc The gRPC extension provides a **server-side callback framework** for Dapr applications. It enables Python apps to act as Dapr callback services using a decorator-based API, handling service invocation, pub/sub subscriptions, input bindings, job events, and health checks. ## Source layout ``` -ext/dapr-ext-grpc/ -├── pyproject.toml # Deps: dapr, cloudevents -├── setup.py -├── tests/ -│ ├── test_app.py # Decorator registration tests -│ ├── test_servicier.py # Routing, handlers, bulk events -│ ├── test_health_servicer.py # Health check tests -│ └── test_topic_event_response.py # Response status tests -└── dapr/ext/grpc/ - ├── __init__.py # Public API exports - ├── app.py # App class — main entry point - ├── _servicer.py # _CallbackServicer — internal routing - ├── _health_servicer.py # _HealthCheckServicer - └── version.py +dapr/ext/grpc/ +├── __init__.py # Public API exports +├── app.py # App class — main entry point +├── _servicer.py # _CallbackServicer — internal routing +├── _health_servicer.py # _HealthCheckServicer +└── py.typed + +tests/ext/grpc/ +├── test_app.py # Decorator registration tests +├── test_servicier.py # Routing, handlers, bulk events +├── test_health_servicer.py # Health check tests +└── test_topic_event_response.py # Response status tests ``` +Installed via the `grpc` extra on core dapr: `pip install "dapr[grpc]"`. + ## Public API ```python @@ -112,10 +112,15 @@ app.register_health_check(lambda: None) # Not a decorator — direct registrati **JobEvent**: `name` (str), `data` (bytes), `get_data_as_string(encoding='utf-8')` +## Dependencies (declared via the `grpc` extra in the root `pyproject.toml`) + +- `dapr` (core, same wheel as this extension) +- `cloudevents >= 1.0.0, < 2.0.0` + ## Testing ```bash -python -m unittest discover -v ./ext/dapr-ext-grpc/tests +uv run python -m unittest discover -v ./tests/ext/grpc ``` Test patterns: diff --git a/dapr/ext/grpc/README.md b/dapr/ext/grpc/README.md new file mode 100644 index 000000000..ea92b1bf2 --- /dev/null +++ b/dapr/ext/grpc/README.md @@ -0,0 +1,16 @@ +# dapr.ext.grpc + +gRPC AppCallback server framework for Dapr Python SDK applications. Provides +decorator-based registration for service invocation, pub/sub, bindings, jobs, +and health checks. + +```sh +pip install "dapr[grpc]" +``` + +```python +from dapr.ext.grpc import App +``` + +See the root [README](../../../README.md) for migration steps from the legacy +`dapr-ext-grpc` distribution. \ No newline at end of file diff --git a/ext/dapr-ext-grpc/dapr/ext/grpc/__init__.py b/dapr/ext/grpc/__init__.py similarity index 80% rename from ext/dapr-ext-grpc/dapr/ext/grpc/__init__.py rename to dapr/ext/grpc/__init__.py index 5324c6175..5aaccf16c 100644 --- a/ext/dapr-ext-grpc/dapr/ext/grpc/__init__.py +++ b/dapr/ext/grpc/__init__.py @@ -13,12 +13,18 @@ limitations under the License. """ -from dapr.ext.grpc.app import App, Rule # type:ignore - from dapr.clients.grpc._jobs import ConstantFailurePolicy, DropFailurePolicy, FailurePolicy, Job from dapr.clients.grpc._request import BindingRequest, InvokeMethodRequest, JobEvent from dapr.clients.grpc._response import InvokeMethodResponse, TopicEventResponse +try: + from dapr.ext.grpc.app import App, Rule # type:ignore +except ImportError as exc: + raise ImportError( + f'dapr.ext.grpc is missing an optional dependency ({exc.name!r}). ' + f'Install the extension with: pip install "dapr[grpc]"' + ) from exc + __all__ = [ 'App', 'Rule', diff --git a/ext/dapr-ext-grpc/dapr/ext/grpc/_health_servicer.py b/dapr/ext/grpc/_health_servicer.py similarity index 100% rename from ext/dapr-ext-grpc/dapr/ext/grpc/_health_servicer.py rename to dapr/ext/grpc/_health_servicer.py diff --git a/ext/dapr-ext-grpc/dapr/ext/grpc/_servicer.py b/dapr/ext/grpc/_servicer.py similarity index 100% rename from ext/dapr-ext-grpc/dapr/ext/grpc/_servicer.py rename to dapr/ext/grpc/_servicer.py diff --git a/ext/dapr-ext-grpc/dapr/ext/grpc/app.py b/dapr/ext/grpc/app.py similarity index 99% rename from ext/dapr-ext-grpc/dapr/ext/grpc/app.py rename to dapr/ext/grpc/app.py index 9f68f7a9c..b45fb8b47 100644 --- a/ext/dapr-ext-grpc/dapr/ext/grpc/app.py +++ b/dapr/ext/grpc/app.py @@ -16,11 +16,10 @@ from concurrent import futures from typing import Dict, Optional -from dapr.ext.grpc._health_servicer import _HealthCheckServicer # type: ignore -from dapr.ext.grpc._servicer import Rule, _CallbackServicer # type: ignore - import grpc from dapr.conf import settings +from dapr.ext.grpc._health_servicer import _HealthCheckServicer # type: ignore +from dapr.ext.grpc._servicer import Rule, _CallbackServicer # type: ignore from dapr.proto import appcallback_service_v1 diff --git a/ext/dapr-ext-langgraph/dapr/ext/langgraph/py.typed b/dapr/ext/grpc/py.typed similarity index 100% rename from ext/dapr-ext-langgraph/dapr/ext/langgraph/py.typed rename to dapr/ext/grpc/py.typed diff --git a/ext/dapr-ext-langgraph/AGENTS.md b/dapr/ext/langgraph/AGENTS.md similarity index 80% rename from ext/dapr-ext-langgraph/AGENTS.md rename to dapr/ext/langgraph/AGENTS.md index d21a44d6e..1363fd4c8 100644 --- a/ext/dapr-ext-langgraph/AGENTS.md +++ b/dapr/ext/langgraph/AGENTS.md @@ -1,21 +1,21 @@ -# AGENTS.md — dapr-ext-langgraph +# AGENTS.md — dapr.ext.langgraph The LangGraph extension provides a Dapr-backed checkpoint saver for [LangGraph](https://langchain-ai.github.io/langgraph/) workflows, persisting workflow state to any Dapr state store. ## Source layout ``` -ext/dapr-ext-langgraph/ -├── pyproject.toml # Deps: dapr, langgraph, langchain, python-ulid, msgpack-python -├── setup.py -├── tests/ -│ └── test_checkpointer.py # Unit tests with mocked DaprClient -└── dapr/ext/langgraph/ - ├── __init__.py # Exports: DaprCheckpointer - ├── dapr_checkpointer.py # Main implementation (~420 lines) - └── version.py +dapr/ext/langgraph/ +├── __init__.py # Exports: DaprCheckpointer +├── dapr_checkpointer.py # Main implementation (~420 lines) +└── py.typed + +tests/ext/langgraph/ +└── test_checkpointer.py # Unit tests with mocked DaprClient ``` +Installed via the `langgraph` extra on core dapr: `pip install "dapr[langgraph]"`. + ## Public API ```python @@ -66,18 +66,18 @@ cp.delete_thread(config) | `checkpoint_latest:{thread_id}:{ns}` | Points to the latest checkpoint key | | `dapr_checkpoint_registry` | List of all checkpoint keys (for `list()`) | -## Dependencies +## Dependencies (declared via the `langgraph` extra in the root `pyproject.toml`) -- `dapr >= 1.17.0.dev` -- `langgraph >= 0.3.6` -- `langchain >= 0.1.17` -- `python-ulid >= 3.0.0` (for checkpoint ID ordering) -- `msgpack-python >= 0.4.5` (for binary serialization) +- `dapr` (core, same wheel as this extension) +- `langgraph >= 0.3.6, < 2.0.0` +- `langchain >= 0.1.17, < 2.0.0` +- `python-ulid >= 3.0.0, < 4.0.0` (for checkpoint ID ordering) +- `msgpack-python >= 0.4.5, < 1.0.0` (for binary serialization) ## Testing ```bash -python -m unittest discover -v ./ext/dapr-ext-langgraph/tests +uv run python -m unittest discover -v ./tests/ext/langgraph ``` 6 test cases using `@mock.patch('dapr.ext.langgraph.dapr_checkpointer.DaprClient')`: diff --git a/dapr/ext/langgraph/README.md b/dapr/ext/langgraph/README.md new file mode 100644 index 000000000..d39535459 --- /dev/null +++ b/dapr/ext/langgraph/README.md @@ -0,0 +1,15 @@ +# dapr.ext.langgraph + +LangGraph checkpoint persistence backed by any Dapr state store. Provides +`DaprCheckpointer`, which extends LangGraph's `BaseCheckpointSaver`. + +```sh +pip install "dapr[langgraph]" +``` + +```python +from dapr.ext.langgraph import DaprCheckpointer +``` + +See the root [README](../../../README.md) for migration steps from the legacy +`dapr-ext-langgraph` distribution. \ No newline at end of file diff --git a/ext/dapr-ext-langgraph/dapr/ext/langgraph/__init__.py b/dapr/ext/langgraph/__init__.py similarity index 68% rename from ext/dapr-ext-langgraph/dapr/ext/langgraph/__init__.py rename to dapr/ext/langgraph/__init__.py index 4f2d3cf8b..64858c9d1 100644 --- a/ext/dapr-ext-langgraph/dapr/ext/langgraph/__init__.py +++ b/dapr/ext/langgraph/__init__.py @@ -13,8 +13,13 @@ limitations under the License. """ -# Import your main classes here -from dapr.ext.langgraph.dapr_checkpointer import DaprCheckpointer +try: + from dapr.ext.langgraph.dapr_checkpointer import DaprCheckpointer +except ImportError as exc: + raise ImportError( + f'dapr.ext.langgraph is missing an optional dependency ({exc.name!r}). ' + f'Install the extension with: pip install "dapr[langgraph]"' + ) from exc __all__ = [ 'DaprCheckpointer', diff --git a/ext/dapr-ext-langgraph/dapr/ext/langgraph/dapr_checkpointer.py b/dapr/ext/langgraph/dapr_checkpointer.py similarity index 100% rename from ext/dapr-ext-langgraph/dapr/ext/langgraph/dapr_checkpointer.py rename to dapr/ext/langgraph/dapr_checkpointer.py diff --git a/ext/dapr-ext-workflow/dapr/ext/workflow/py.typed b/dapr/ext/langgraph/py.typed similarity index 100% rename from ext/dapr-ext-workflow/dapr/ext/workflow/py.typed rename to dapr/ext/langgraph/py.typed diff --git a/ext/dapr-ext-strands/AGENTS.md b/dapr/ext/strands/AGENTS.md similarity index 82% rename from ext/dapr-ext-strands/AGENTS.md rename to dapr/ext/strands/AGENTS.md index dc3d37ad8..a89955913 100644 --- a/ext/dapr-ext-strands/AGENTS.md +++ b/dapr/ext/strands/AGENTS.md @@ -1,21 +1,21 @@ -# AGENTS.md — dapr-ext-strands +# AGENTS.md — dapr.ext.strands The Strands extension provides distributed session management for [Strands Agents](https://github.com/strands-agents/strands-agents), persisting sessions, agents, and messages to any Dapr state store with optional TTL and consistency controls. ## Source layout ``` -ext/dapr-ext-strands/ -├── pyproject.toml # Deps: dapr, strands-agents, strands-agents-tools, python-ulid, msgpack-python -├── setup.py -├── tests/ -│ └── test_session_manager.py # Unit tests with mocked DaprClient -└── dapr/ext/strands/ - ├── __init__.py # Exports: DaprSessionManager - ├── dapr_session_manager.py # Main implementation (~550 lines) - └── version.py +dapr/ext/strands/ +├── __init__.py # Exports: DaprSessionManager +├── dapr_session_manager.py # Main implementation (~550 lines) +└── py.typed + +tests/ext/strands/ +└── test_session_manager.py # Unit tests with mocked DaprClient ``` +Installed via the `strands` extra on core dapr: `pip install "dapr[strands]"`. + ## Public API ```python @@ -76,18 +76,18 @@ manager = DaprSessionManager.from_address( | `{session_id}:messages:{agent_id}` | Message list: `{"messages": [...]}` (JSON) | | `{session_id}:manifest` | Agent ID registry: `{"agents": [...]}` (used for cascade deletion) | -## Dependencies +## Dependencies (declared via the `strands` extra in the root `pyproject.toml`) -- `dapr >= 1.17.0.dev` -- `strands-agents` — Strands agents framework -- `strands-agents-tools` — Strands agent tools -- `python-ulid >= 3.0.0` -- `msgpack-python >= 0.4.5` +- `dapr` (core, same wheel as this extension) +- `strands-agents >= 1.30.0, < 2.0.0` +- `strands-agents-tools >= 0.2.22, < 1.0.0` +- `python-ulid >= 3.0.0, < 4.0.0` +- `msgpack-python >= 0.4.5, < 1.0.0` ## Testing ```bash -python -m unittest discover -v ./ext/dapr-ext-strands/tests +uv run python -m unittest discover -v ./tests/ext/strands ``` 8 test cases using `@mock.patch('dapr.ext.strands.dapr_session_manager.DaprClient')`: diff --git a/dapr/ext/strands/README.md b/dapr/ext/strands/README.md new file mode 100644 index 000000000..27bb3773b --- /dev/null +++ b/dapr/ext/strands/README.md @@ -0,0 +1,15 @@ +# dapr.ext.strands + +Strands Agents session management backed by any Dapr state store. Provides +`DaprSessionManager` for distributed session, agent, and message persistence. + +```sh +pip install "dapr[strands]" +``` + +```python +from dapr.ext.strands import DaprSessionManager +``` + +See the root [README](../../../README.md) for migration steps from the legacy +`dapr-ext-strands` distribution. \ No newline at end of file diff --git a/ext/dapr-ext-strands/dapr/ext/strands/__init__.py b/dapr/ext/strands/__init__.py similarity index 68% rename from ext/dapr-ext-strands/dapr/ext/strands/__init__.py rename to dapr/ext/strands/__init__.py index 52ab2ee86..d4ec60947 100644 --- a/ext/dapr-ext-strands/dapr/ext/strands/__init__.py +++ b/dapr/ext/strands/__init__.py @@ -13,8 +13,13 @@ limitations under the License. """ -# Import your main classes here -from dapr.ext.strands.dapr_session_manager import DaprSessionManager +try: + from dapr.ext.strands.dapr_session_manager import DaprSessionManager +except ImportError as exc: + raise ImportError( + f'dapr.ext.strands is missing an optional dependency ({exc.name!r}). ' + f'Install the extension with: pip install "dapr[strands]"' + ) from exc __all__ = [ 'DaprSessionManager', diff --git a/ext/dapr-ext-strands/dapr/ext/strands/dapr_session_manager.py b/dapr/ext/strands/dapr_session_manager.py similarity index 100% rename from ext/dapr-ext-strands/dapr/ext/strands/dapr_session_manager.py rename to dapr/ext/strands/dapr_session_manager.py diff --git a/ext/dapr-ext-workflow/AGENTS.md b/dapr/ext/workflow/AGENTS.md similarity index 85% rename from ext/dapr-ext-workflow/AGENTS.md rename to dapr/ext/workflow/AGENTS.md index 635cb8705..d0aaa8878 100644 --- a/ext/dapr-ext-workflow/AGENTS.md +++ b/dapr/ext/workflow/AGENTS.md @@ -1,35 +1,37 @@ -# AGENTS.md — dapr-ext-workflow +# AGENTS.md — dapr.ext.workflow The workflow extension is a **major area of active development**. It provides durable workflow orchestration for Python, built on a vendored durabletask engine (in `_durabletask/`). ## Source layout ``` -ext/dapr-ext-workflow/ -├── pyproject.toml # Deps: dapr (durabletask is vendored) -├── setup.py -├── tests/ -│ ├── test_dapr_workflow_context.py # Context method proxying -│ ├── test_workflow_activity_context.py # Activity context properties -│ ├── test_workflow_client.py # Sync client (mock gRPC) -│ ├── test_workflow_client_aio.py # Async client (IsolatedAsyncioTestCase) -│ ├── test_workflow_runtime.py # Registration, decorators, worker readiness -│ └── test_workflow_util.py # Address resolution -└── dapr/ext/workflow/ - ├── __init__.py # Public API exports - ├── workflow_runtime.py # WorkflowRuntime — registration & lifecycle - ├── dapr_workflow_client.py # DaprWorkflowClient (sync) - ├── aio/dapr_workflow_client.py # DaprWorkflowClient (async) - ├── dapr_workflow_context.py # DaprWorkflowContext + when_all/when_any - ├── workflow_context.py # WorkflowContext ABC - ├── workflow_activity_context.py # WorkflowActivityContext wrapper - ├── workflow_state.py # WorkflowState, WorkflowStatus enum - ├── retry_policy.py # RetryPolicy wrapper - ├── util.py # gRPC address resolution - ├── logger/options.py # LoggerOptions - └── logger/logger.py # Logger wrapper +dapr/ext/workflow/ +├── __init__.py # Public API exports +├── workflow_runtime.py # WorkflowRuntime — registration & lifecycle +├── dapr_workflow_client.py # DaprWorkflowClient (sync) +├── aio/dapr_workflow_client.py # DaprWorkflowClient (async) +├── dapr_workflow_context.py # DaprWorkflowContext + when_all/when_any +├── workflow_context.py # WorkflowContext ABC +├── workflow_activity_context.py # WorkflowActivityContext wrapper +├── workflow_state.py # WorkflowState, WorkflowStatus enum +├── retry_policy.py # RetryPolicy wrapper +├── util.py # gRPC address resolution +├── logger/options.py # LoggerOptions +├── logger/logger.py # Logger wrapper +└── _durabletask/ # Vendored durabletask engine + +tests/ext/workflow/ +├── test_dapr_workflow_context.py # Context method proxying +├── test_workflow_activity_context.py # Activity context properties +├── test_workflow_client.py # Sync client (mock gRPC) +├── test_workflow_client_aio.py # Async client (IsolatedAsyncioTestCase) +├── test_workflow_runtime.py # Registration, decorators, worker readiness +├── test_workflow_util.py # Address resolution +└── durabletask/ # Vendored durabletask engine tests (pytest) ``` +Installed via the `workflow` extra: `pip install "dapr[workflow]"` (the extra has no third-party deps; it exists for install-command symmetry). + ## Architecture ``` @@ -197,7 +199,11 @@ Two example directories exercise workflows: Unit tests use mocks to simulate the durabletask layer (no Dapr runtime needed): ```bash -python -m unittest discover -v ./ext/dapr-ext-workflow/tests +# Workflow-side tests (unittest) +uv run python -m unittest discover -v ./tests/ext/workflow + +# Vendored durabletask tests (pytest — they use pytest fixtures) +uv run pytest -m "not e2e" ./tests/ext/workflow/durabletask ``` Test patterns: diff --git a/dapr/ext/workflow/README.md b/dapr/ext/workflow/README.md new file mode 100644 index 000000000..7df1df0ef --- /dev/null +++ b/dapr/ext/workflow/README.md @@ -0,0 +1,15 @@ +# dapr.ext.workflow + +Durable workflow orchestration for the Dapr Python SDK, built on a vendored +durabletask engine. Provides `WorkflowRuntime` and `DaprWorkflowClient`. + +```sh +pip install "dapr[workflow]" +``` + +```python +from dapr.ext.workflow import WorkflowRuntime, DaprWorkflowClient +``` + +See the root [README](../../../README.md) for migration steps from the legacy +`dapr-ext-workflow` distribution. \ No newline at end of file diff --git a/ext/dapr-ext-workflow/dapr/ext/workflow/__init__.py b/dapr/ext/workflow/__init__.py similarity index 100% rename from ext/dapr-ext-workflow/dapr/ext/workflow/__init__.py rename to dapr/ext/workflow/__init__.py diff --git a/ext/dapr-ext-workflow/dapr/ext/workflow/_durabletask/__init__.py b/dapr/ext/workflow/_durabletask/__init__.py similarity index 90% rename from ext/dapr-ext-workflow/dapr/ext/workflow/_durabletask/__init__.py rename to dapr/ext/workflow/_durabletask/__init__.py index 10b389044..d3e469c9e 100644 --- a/ext/dapr-ext-workflow/dapr/ext/workflow/_durabletask/__init__.py +++ b/dapr/ext/workflow/_durabletask/__init__.py @@ -9,4 +9,4 @@ # See the License for the specific language governing permissions and # limitations under the License. -"""Durable Task SDK for Python (vendored into dapr-ext-workflow)""" +"""Durable Task SDK for Python (vendored into dapr.ext.workflow)""" diff --git a/ext/dapr-ext-workflow/dapr/ext/workflow/_durabletask/aio/__init__.py b/dapr/ext/workflow/_durabletask/aio/__init__.py similarity index 100% rename from ext/dapr-ext-workflow/dapr/ext/workflow/_durabletask/aio/__init__.py rename to dapr/ext/workflow/_durabletask/aio/__init__.py diff --git a/ext/dapr-ext-workflow/dapr/ext/workflow/_durabletask/aio/client.py b/dapr/ext/workflow/_durabletask/aio/client.py similarity index 99% rename from ext/dapr-ext-workflow/dapr/ext/workflow/_durabletask/aio/client.py rename to dapr/ext/workflow/_durabletask/aio/client.py index 8a2790638..27085c694 100644 --- a/ext/dapr-ext-workflow/dapr/ext/workflow/_durabletask/aio/client.py +++ b/dapr/ext/workflow/_durabletask/aio/client.py @@ -14,11 +14,13 @@ from datetime import datetime from typing import Any, Optional, Sequence, Union +import grpc +from google.protobuf import wrappers_pb2 + import dapr.ext.workflow._durabletask.internal.helpers as helpers import dapr.ext.workflow._durabletask.internal.orchestrator_service_pb2_grpc as stubs import dapr.ext.workflow._durabletask.internal.protos as pb import dapr.ext.workflow._durabletask.internal.shared as shared -import grpc from dapr.ext.workflow._durabletask import task from dapr.ext.workflow._durabletask.aio.internal.grpc_interceptor import ( DefaultClientInterceptorImpl, @@ -35,7 +37,6 @@ WorkflowState, new_orchestration_state, ) -from google.protobuf import wrappers_pb2 # If `opentelemetry-instrumentation-grpc` is available, enable the gRPC client interceptor try: diff --git a/ext/dapr-ext-fastapi/tests/__init__.py b/dapr/ext/workflow/_durabletask/aio/internal/__init__.py similarity index 100% rename from ext/dapr-ext-fastapi/tests/__init__.py rename to dapr/ext/workflow/_durabletask/aio/internal/__init__.py diff --git a/ext/dapr-ext-workflow/dapr/ext/workflow/_durabletask/aio/internal/grpc_interceptor.py b/dapr/ext/workflow/_durabletask/aio/internal/grpc_interceptor.py similarity index 100% rename from ext/dapr-ext-workflow/dapr/ext/workflow/_durabletask/aio/internal/grpc_interceptor.py rename to dapr/ext/workflow/_durabletask/aio/internal/grpc_interceptor.py diff --git a/ext/dapr-ext-workflow/dapr/ext/workflow/_durabletask/aio/internal/shared.py b/dapr/ext/workflow/_durabletask/aio/internal/shared.py similarity index 99% rename from ext/dapr-ext-workflow/dapr/ext/workflow/_durabletask/aio/internal/shared.py rename to dapr/ext/workflow/_durabletask/aio/internal/shared.py index 4ac78537b..c6375294b 100644 --- a/ext/dapr-ext-workflow/dapr/ext/workflow/_durabletask/aio/internal/shared.py +++ b/dapr/ext/workflow/_durabletask/aio/internal/shared.py @@ -12,13 +12,14 @@ from typing import Optional, Sequence, Union import grpc +from grpc import aio as grpc_aio +from grpc.aio import ChannelArgumentType + from dapr.ext.workflow._durabletask.internal.shared import ( INSECURE_PROTOCOLS, SECURE_PROTOCOLS, get_default_host_address, ) -from grpc import aio as grpc_aio -from grpc.aio import ChannelArgumentType ClientInterceptor = Union[ grpc_aio.UnaryUnaryClientInterceptor, diff --git a/ext/dapr-ext-workflow/dapr/ext/workflow/_durabletask/client.py b/dapr/ext/workflow/_durabletask/client.py similarity index 99% rename from ext/dapr-ext-workflow/dapr/ext/workflow/_durabletask/client.py rename to dapr/ext/workflow/_durabletask/client.py index 72fcb2f89..b883bbadc 100644 --- a/ext/dapr-ext-workflow/dapr/ext/workflow/_durabletask/client.py +++ b/dapr/ext/workflow/_durabletask/client.py @@ -16,14 +16,15 @@ from enum import Enum from typing import Any, Optional, Sequence, TypeVar, Union +import grpc +from google.protobuf import wrappers_pb2 + import dapr.ext.workflow._durabletask.internal.helpers as helpers import dapr.ext.workflow._durabletask.internal.orchestrator_service_pb2_grpc as stubs import dapr.ext.workflow._durabletask.internal.protos as pb import dapr.ext.workflow._durabletask.internal.shared as shared -import grpc from dapr.ext.workflow._durabletask import task from dapr.ext.workflow._durabletask.internal.grpc_interceptor import DefaultClientInterceptorImpl -from google.protobuf import wrappers_pb2 TInput = TypeVar('TInput') TOutput = TypeVar('TOutput') diff --git a/ext/dapr-ext-workflow/dapr/ext/workflow/_durabletask/deterministic.py b/dapr/ext/workflow/_durabletask/deterministic.py similarity index 100% rename from ext/dapr-ext-workflow/dapr/ext/workflow/_durabletask/deterministic.py rename to dapr/ext/workflow/_durabletask/deterministic.py diff --git a/ext/dapr-ext-workflow/dapr/ext/workflow/_durabletask/internal/PROTO_SOURCE_COMMIT_HASH b/dapr/ext/workflow/_durabletask/internal/PROTO_SOURCE_COMMIT_HASH similarity index 100% rename from ext/dapr-ext-workflow/dapr/ext/workflow/_durabletask/internal/PROTO_SOURCE_COMMIT_HASH rename to dapr/ext/workflow/_durabletask/internal/PROTO_SOURCE_COMMIT_HASH diff --git a/ext/dapr-ext-grpc/tests/__init__.py b/dapr/ext/workflow/_durabletask/internal/__init__.py similarity index 100% rename from ext/dapr-ext-grpc/tests/__init__.py rename to dapr/ext/workflow/_durabletask/internal/__init__.py diff --git a/ext/dapr-ext-workflow/dapr/ext/workflow/_durabletask/internal/attestation_pb2.py b/dapr/ext/workflow/_durabletask/internal/attestation_pb2.py similarity index 100% rename from ext/dapr-ext-workflow/dapr/ext/workflow/_durabletask/internal/attestation_pb2.py rename to dapr/ext/workflow/_durabletask/internal/attestation_pb2.py diff --git a/ext/dapr-ext-workflow/dapr/ext/workflow/_durabletask/internal/attestation_pb2.pyi b/dapr/ext/workflow/_durabletask/internal/attestation_pb2.pyi similarity index 100% rename from ext/dapr-ext-workflow/dapr/ext/workflow/_durabletask/internal/attestation_pb2.pyi rename to dapr/ext/workflow/_durabletask/internal/attestation_pb2.pyi diff --git a/ext/dapr-ext-workflow/dapr/ext/workflow/_durabletask/internal/attestation_pb2_grpc.py b/dapr/ext/workflow/_durabletask/internal/attestation_pb2_grpc.py similarity index 100% rename from ext/dapr-ext-workflow/dapr/ext/workflow/_durabletask/internal/attestation_pb2_grpc.py rename to dapr/ext/workflow/_durabletask/internal/attestation_pb2_grpc.py diff --git a/ext/dapr-ext-workflow/dapr/ext/workflow/_durabletask/internal/backend_service_pb2.py b/dapr/ext/workflow/_durabletask/internal/backend_service_pb2.py similarity index 100% rename from ext/dapr-ext-workflow/dapr/ext/workflow/_durabletask/internal/backend_service_pb2.py rename to dapr/ext/workflow/_durabletask/internal/backend_service_pb2.py diff --git a/ext/dapr-ext-workflow/dapr/ext/workflow/_durabletask/internal/backend_service_pb2.pyi b/dapr/ext/workflow/_durabletask/internal/backend_service_pb2.pyi similarity index 100% rename from ext/dapr-ext-workflow/dapr/ext/workflow/_durabletask/internal/backend_service_pb2.pyi rename to dapr/ext/workflow/_durabletask/internal/backend_service_pb2.pyi diff --git a/ext/dapr-ext-workflow/dapr/ext/workflow/_durabletask/internal/backend_service_pb2_grpc.py b/dapr/ext/workflow/_durabletask/internal/backend_service_pb2_grpc.py similarity index 100% rename from ext/dapr-ext-workflow/dapr/ext/workflow/_durabletask/internal/backend_service_pb2_grpc.py rename to dapr/ext/workflow/_durabletask/internal/backend_service_pb2_grpc.py diff --git a/ext/dapr-ext-workflow/dapr/ext/workflow/_durabletask/internal/grpc_interceptor.py b/dapr/ext/workflow/_durabletask/internal/grpc_interceptor.py similarity index 100% rename from ext/dapr-ext-workflow/dapr/ext/workflow/_durabletask/internal/grpc_interceptor.py rename to dapr/ext/workflow/_durabletask/internal/grpc_interceptor.py diff --git a/ext/dapr-ext-workflow/dapr/ext/workflow/_durabletask/internal/helpers.py b/dapr/ext/workflow/_durabletask/internal/helpers.py similarity index 99% rename from ext/dapr-ext-workflow/dapr/ext/workflow/_durabletask/internal/helpers.py rename to dapr/ext/workflow/_durabletask/internal/helpers.py index ae322dd61..387a9ee10 100644 --- a/ext/dapr-ext-workflow/dapr/ext/workflow/_durabletask/internal/helpers.py +++ b/dapr/ext/workflow/_durabletask/internal/helpers.py @@ -13,6 +13,8 @@ from datetime import datetime from typing import Optional +from google.protobuf import timestamp_pb2, wrappers_pb2 + import dapr.ext.workflow._durabletask.internal.protos as pb from dapr.ext.workflow._durabletask.internal.timer import ( # noqa: F401 OPTIONAL_TIMER_FIRE_AT, @@ -23,7 +25,6 @@ new_timer_created_event, new_timer_fired_event, ) -from google.protobuf import timestamp_pb2, wrappers_pb2 # TODO: The new_xxx_event methods are only used by test code and should be moved elsewhere diff --git a/ext/dapr-ext-workflow/dapr/ext/workflow/_durabletask/internal/history_events_pb2.py b/dapr/ext/workflow/_durabletask/internal/history_events_pb2.py similarity index 100% rename from ext/dapr-ext-workflow/dapr/ext/workflow/_durabletask/internal/history_events_pb2.py rename to dapr/ext/workflow/_durabletask/internal/history_events_pb2.py diff --git a/ext/dapr-ext-workflow/dapr/ext/workflow/_durabletask/internal/history_events_pb2.pyi b/dapr/ext/workflow/_durabletask/internal/history_events_pb2.pyi similarity index 100% rename from ext/dapr-ext-workflow/dapr/ext/workflow/_durabletask/internal/history_events_pb2.pyi rename to dapr/ext/workflow/_durabletask/internal/history_events_pb2.pyi diff --git a/ext/dapr-ext-workflow/dapr/ext/workflow/_durabletask/internal/history_events_pb2_grpc.py b/dapr/ext/workflow/_durabletask/internal/history_events_pb2_grpc.py similarity index 100% rename from ext/dapr-ext-workflow/dapr/ext/workflow/_durabletask/internal/history_events_pb2_grpc.py rename to dapr/ext/workflow/_durabletask/internal/history_events_pb2_grpc.py diff --git a/ext/dapr-ext-workflow/dapr/ext/workflow/_durabletask/internal/orchestration_pb2.py b/dapr/ext/workflow/_durabletask/internal/orchestration_pb2.py similarity index 100% rename from ext/dapr-ext-workflow/dapr/ext/workflow/_durabletask/internal/orchestration_pb2.py rename to dapr/ext/workflow/_durabletask/internal/orchestration_pb2.py diff --git a/ext/dapr-ext-workflow/dapr/ext/workflow/_durabletask/internal/orchestration_pb2.pyi b/dapr/ext/workflow/_durabletask/internal/orchestration_pb2.pyi similarity index 100% rename from ext/dapr-ext-workflow/dapr/ext/workflow/_durabletask/internal/orchestration_pb2.pyi rename to dapr/ext/workflow/_durabletask/internal/orchestration_pb2.pyi diff --git a/ext/dapr-ext-workflow/dapr/ext/workflow/_durabletask/internal/orchestration_pb2_grpc.py b/dapr/ext/workflow/_durabletask/internal/orchestration_pb2_grpc.py similarity index 100% rename from ext/dapr-ext-workflow/dapr/ext/workflow/_durabletask/internal/orchestration_pb2_grpc.py rename to dapr/ext/workflow/_durabletask/internal/orchestration_pb2_grpc.py diff --git a/ext/dapr-ext-workflow/dapr/ext/workflow/_durabletask/internal/orchestrator_actions_pb2.py b/dapr/ext/workflow/_durabletask/internal/orchestrator_actions_pb2.py similarity index 100% rename from ext/dapr-ext-workflow/dapr/ext/workflow/_durabletask/internal/orchestrator_actions_pb2.py rename to dapr/ext/workflow/_durabletask/internal/orchestrator_actions_pb2.py diff --git a/ext/dapr-ext-workflow/dapr/ext/workflow/_durabletask/internal/orchestrator_actions_pb2.pyi b/dapr/ext/workflow/_durabletask/internal/orchestrator_actions_pb2.pyi similarity index 100% rename from ext/dapr-ext-workflow/dapr/ext/workflow/_durabletask/internal/orchestrator_actions_pb2.pyi rename to dapr/ext/workflow/_durabletask/internal/orchestrator_actions_pb2.pyi diff --git a/ext/dapr-ext-workflow/dapr/ext/workflow/_durabletask/internal/orchestrator_actions_pb2_grpc.py b/dapr/ext/workflow/_durabletask/internal/orchestrator_actions_pb2_grpc.py similarity index 100% rename from ext/dapr-ext-workflow/dapr/ext/workflow/_durabletask/internal/orchestrator_actions_pb2_grpc.py rename to dapr/ext/workflow/_durabletask/internal/orchestrator_actions_pb2_grpc.py diff --git a/ext/dapr-ext-workflow/dapr/ext/workflow/_durabletask/internal/orchestrator_service_pb2.py b/dapr/ext/workflow/_durabletask/internal/orchestrator_service_pb2.py similarity index 100% rename from ext/dapr-ext-workflow/dapr/ext/workflow/_durabletask/internal/orchestrator_service_pb2.py rename to dapr/ext/workflow/_durabletask/internal/orchestrator_service_pb2.py diff --git a/ext/dapr-ext-workflow/dapr/ext/workflow/_durabletask/internal/orchestrator_service_pb2.pyi b/dapr/ext/workflow/_durabletask/internal/orchestrator_service_pb2.pyi similarity index 100% rename from ext/dapr-ext-workflow/dapr/ext/workflow/_durabletask/internal/orchestrator_service_pb2.pyi rename to dapr/ext/workflow/_durabletask/internal/orchestrator_service_pb2.pyi diff --git a/ext/dapr-ext-workflow/dapr/ext/workflow/_durabletask/internal/orchestrator_service_pb2_grpc.py b/dapr/ext/workflow/_durabletask/internal/orchestrator_service_pb2_grpc.py similarity index 100% rename from ext/dapr-ext-workflow/dapr/ext/workflow/_durabletask/internal/orchestrator_service_pb2_grpc.py rename to dapr/ext/workflow/_durabletask/internal/orchestrator_service_pb2_grpc.py diff --git a/ext/dapr-ext-workflow/dapr/ext/workflow/_durabletask/internal/protos.py b/dapr/ext/workflow/_durabletask/internal/protos.py similarity index 100% rename from ext/dapr-ext-workflow/dapr/ext/workflow/_durabletask/internal/protos.py rename to dapr/ext/workflow/_durabletask/internal/protos.py diff --git a/ext/dapr-ext-workflow/dapr/ext/workflow/_durabletask/internal/runtime_state_pb2.py b/dapr/ext/workflow/_durabletask/internal/runtime_state_pb2.py similarity index 100% rename from ext/dapr-ext-workflow/dapr/ext/workflow/_durabletask/internal/runtime_state_pb2.py rename to dapr/ext/workflow/_durabletask/internal/runtime_state_pb2.py diff --git a/ext/dapr-ext-workflow/dapr/ext/workflow/_durabletask/internal/runtime_state_pb2.pyi b/dapr/ext/workflow/_durabletask/internal/runtime_state_pb2.pyi similarity index 100% rename from ext/dapr-ext-workflow/dapr/ext/workflow/_durabletask/internal/runtime_state_pb2.pyi rename to dapr/ext/workflow/_durabletask/internal/runtime_state_pb2.pyi diff --git a/ext/dapr-ext-workflow/dapr/ext/workflow/_durabletask/internal/runtime_state_pb2_grpc.py b/dapr/ext/workflow/_durabletask/internal/runtime_state_pb2_grpc.py similarity index 100% rename from ext/dapr-ext-workflow/dapr/ext/workflow/_durabletask/internal/runtime_state_pb2_grpc.py rename to dapr/ext/workflow/_durabletask/internal/runtime_state_pb2_grpc.py diff --git a/ext/dapr-ext-workflow/dapr/ext/workflow/_durabletask/internal/shared.py b/dapr/ext/workflow/_durabletask/internal/shared.py similarity index 99% rename from ext/dapr-ext-workflow/dapr/ext/workflow/_durabletask/internal/shared.py rename to dapr/ext/workflow/_durabletask/internal/shared.py index 5c9bd9f9b..fdcee8840 100644 --- a/ext/dapr-ext-workflow/dapr/ext/workflow/_durabletask/internal/shared.py +++ b/dapr/ext/workflow/_durabletask/internal/shared.py @@ -17,6 +17,7 @@ from typing import Any, Optional, Sequence, Union import grpc + from dapr.ext.workflow import _model_protocol ClientInterceptor = Union[ diff --git a/ext/dapr-ext-workflow/dapr/ext/workflow/_durabletask/internal/timer.py b/dapr/ext/workflow/_durabletask/internal/timer.py similarity index 99% rename from ext/dapr-ext-workflow/dapr/ext/workflow/_durabletask/internal/timer.py rename to dapr/ext/workflow/_durabletask/internal/timer.py index e04c4da05..a02380e52 100644 --- a/ext/dapr-ext-workflow/dapr/ext/workflow/_durabletask/internal/timer.py +++ b/dapr/ext/workflow/_durabletask/internal/timer.py @@ -18,9 +18,10 @@ from datetime import datetime from typing import Optional, Union -import dapr.ext.workflow._durabletask.internal.protos as pb from google.protobuf import timestamp_pb2 +import dapr.ext.workflow._durabletask.internal.protos as pb + TimerOrigin = Union[ pb.TimerOriginCreateTimer, pb.TimerOriginExternalEvent, diff --git a/ext/dapr-ext-workflow/dapr/ext/workflow/_durabletask/task.py b/dapr/ext/workflow/_durabletask/task.py similarity index 100% rename from ext/dapr-ext-workflow/dapr/ext/workflow/_durabletask/task.py rename to dapr/ext/workflow/_durabletask/task.py diff --git a/ext/dapr-ext-workflow/dapr/ext/workflow/_durabletask/worker.py b/dapr/ext/workflow/_durabletask/worker.py similarity index 99% rename from ext/dapr-ext-workflow/dapr/ext/workflow/_durabletask/worker.py rename to dapr/ext/workflow/_durabletask/worker.py index 84663064f..4b742b8aa 100644 --- a/ext/dapr-ext-workflow/dapr/ext/workflow/_durabletask/worker.py +++ b/dapr/ext/workflow/_durabletask/worker.py @@ -23,15 +23,16 @@ from types import GeneratorType from typing import Any, Generator, Iterator, Optional, Sequence, TypeVar, Union +import grpc +from google.protobuf import empty_pb2, timestamp_pb2 + import dapr.ext.workflow._durabletask.internal.helpers as ph import dapr.ext.workflow._durabletask.internal.orchestrator_service_pb2_grpc as stubs import dapr.ext.workflow._durabletask.internal.protos as pb import dapr.ext.workflow._durabletask.internal.shared as shared -import grpc from dapr.ext.workflow._durabletask import deterministic, task from dapr.ext.workflow._durabletask.internal.grpc_interceptor import DefaultClientInterceptorImpl from dapr.ext.workflow.propagation import PropagatedHistory, PropagationScope -from google.protobuf import empty_pb2, timestamp_pb2 TInput = TypeVar('TInput') TOutput = TypeVar('TOutput') diff --git a/ext/dapr-ext-workflow/dapr/ext/workflow/_model_protocol.py b/dapr/ext/workflow/_model_protocol.py similarity index 100% rename from ext/dapr-ext-workflow/dapr/ext/workflow/_model_protocol.py rename to dapr/ext/workflow/_model_protocol.py diff --git a/ext/dapr-ext-workflow/dapr/ext/workflow/aio/__init__.py b/dapr/ext/workflow/aio/__init__.py similarity index 100% rename from ext/dapr-ext-workflow/dapr/ext/workflow/aio/__init__.py rename to dapr/ext/workflow/aio/__init__.py diff --git a/ext/dapr-ext-workflow/dapr/ext/workflow/aio/dapr_workflow_client.py b/dapr/ext/workflow/aio/dapr_workflow_client.py similarity index 100% rename from ext/dapr-ext-workflow/dapr/ext/workflow/aio/dapr_workflow_client.py rename to dapr/ext/workflow/aio/dapr_workflow_client.py index b72be558d..5ce1e14ef 100644 --- a/ext/dapr-ext-workflow/dapr/ext/workflow/aio/dapr_workflow_client.py +++ b/dapr/ext/workflow/aio/dapr_workflow_client.py @@ -18,12 +18,6 @@ from datetime import datetime from typing import Any, Optional, TypeVar, Union -from dapr.ext.workflow._durabletask import client -from dapr.ext.workflow._durabletask.aio import client as aioclient -from dapr.ext.workflow.logger import Logger, LoggerOptions -from dapr.ext.workflow.util import getAddress -from dapr.ext.workflow.workflow_context import Workflow -from dapr.ext.workflow.workflow_state import WorkflowState from grpc.aio import AioRpcError from dapr.aio.clients.grpc.interceptors import DaprClientTimeoutInterceptorAsync @@ -31,6 +25,12 @@ from dapr.clients.http.client import DAPR_API_TOKEN_HEADER from dapr.conf import settings from dapr.conf.helpers import GrpcEndpoint +from dapr.ext.workflow._durabletask import client +from dapr.ext.workflow._durabletask.aio import client as aioclient +from dapr.ext.workflow.logger import Logger, LoggerOptions +from dapr.ext.workflow.util import getAddress +from dapr.ext.workflow.workflow_context import Workflow +from dapr.ext.workflow.workflow_state import WorkflowState T = TypeVar('T') TInput = TypeVar('TInput') diff --git a/ext/dapr-ext-workflow/dapr/ext/workflow/aio/mcp.py b/dapr/ext/workflow/aio/mcp.py similarity index 100% rename from ext/dapr-ext-workflow/dapr/ext/workflow/aio/mcp.py rename to dapr/ext/workflow/aio/mcp.py diff --git a/ext/dapr-ext-workflow/dapr/ext/workflow/dapr_workflow_client.py b/dapr/ext/workflow/dapr_workflow_client.py similarity index 100% rename from ext/dapr-ext-workflow/dapr/ext/workflow/dapr_workflow_client.py rename to dapr/ext/workflow/dapr_workflow_client.py index d732f7747..a9d70c711 100644 --- a/ext/dapr-ext-workflow/dapr/ext/workflow/dapr_workflow_client.py +++ b/dapr/ext/workflow/dapr_workflow_client.py @@ -18,11 +18,6 @@ from datetime import datetime from typing import Any, Optional, TypeVar, Union -from dapr.ext.workflow._durabletask import client -from dapr.ext.workflow.logger import Logger, LoggerOptions -from dapr.ext.workflow.util import getAddress -from dapr.ext.workflow.workflow_context import Workflow -from dapr.ext.workflow.workflow_state import WorkflowState from grpc import RpcError from dapr.clients import DaprInternalError @@ -30,6 +25,11 @@ from dapr.clients.http.client import DAPR_API_TOKEN_HEADER from dapr.conf import settings from dapr.conf.helpers import GrpcEndpoint +from dapr.ext.workflow._durabletask import client +from dapr.ext.workflow.logger import Logger, LoggerOptions +from dapr.ext.workflow.util import getAddress +from dapr.ext.workflow.workflow_context import Workflow +from dapr.ext.workflow.workflow_state import WorkflowState T = TypeVar('T') TInput = TypeVar('TInput') diff --git a/ext/dapr-ext-workflow/dapr/ext/workflow/dapr_workflow_context.py b/dapr/ext/workflow/dapr_workflow_context.py similarity index 100% rename from ext/dapr-ext-workflow/dapr/ext/workflow/dapr_workflow_context.py rename to dapr/ext/workflow/dapr_workflow_context.py diff --git a/ext/dapr-ext-workflow/dapr/ext/workflow/logger/__init__.py b/dapr/ext/workflow/logger/__init__.py similarity index 100% rename from ext/dapr-ext-workflow/dapr/ext/workflow/logger/__init__.py rename to dapr/ext/workflow/logger/__init__.py diff --git a/ext/dapr-ext-workflow/dapr/ext/workflow/logger/logger.py b/dapr/ext/workflow/logger/logger.py similarity index 100% rename from ext/dapr-ext-workflow/dapr/ext/workflow/logger/logger.py rename to dapr/ext/workflow/logger/logger.py diff --git a/ext/dapr-ext-workflow/dapr/ext/workflow/logger/options.py b/dapr/ext/workflow/logger/options.py similarity index 100% rename from ext/dapr-ext-workflow/dapr/ext/workflow/logger/options.py rename to dapr/ext/workflow/logger/options.py diff --git a/ext/dapr-ext-workflow/dapr/ext/workflow/mcp.py b/dapr/ext/workflow/mcp.py similarity index 100% rename from ext/dapr-ext-workflow/dapr/ext/workflow/mcp.py rename to dapr/ext/workflow/mcp.py diff --git a/ext/dapr-ext-workflow/dapr/ext/workflow/mcp_schema.py b/dapr/ext/workflow/mcp_schema.py similarity index 100% rename from ext/dapr-ext-workflow/dapr/ext/workflow/mcp_schema.py rename to dapr/ext/workflow/mcp_schema.py diff --git a/ext/dapr-ext-workflow/dapr/ext/workflow/propagation.py b/dapr/ext/workflow/propagation.py similarity index 100% rename from ext/dapr-ext-workflow/dapr/ext/workflow/propagation.py rename to dapr/ext/workflow/propagation.py diff --git a/ext/flask_dapr/flask_dapr/py.typed b/dapr/ext/workflow/py.typed similarity index 100% rename from ext/flask_dapr/flask_dapr/py.typed rename to dapr/ext/workflow/py.typed diff --git a/ext/dapr-ext-workflow/dapr/ext/workflow/retry_policy.py b/dapr/ext/workflow/retry_policy.py similarity index 100% rename from ext/dapr-ext-workflow/dapr/ext/workflow/retry_policy.py rename to dapr/ext/workflow/retry_policy.py diff --git a/ext/dapr-ext-workflow/dapr/ext/workflow/util.py b/dapr/ext/workflow/util.py similarity index 100% rename from ext/dapr-ext-workflow/dapr/ext/workflow/util.py rename to dapr/ext/workflow/util.py diff --git a/ext/dapr-ext-workflow/dapr/ext/workflow/workflow_activity_context.py b/dapr/ext/workflow/workflow_activity_context.py similarity index 100% rename from ext/dapr-ext-workflow/dapr/ext/workflow/workflow_activity_context.py rename to dapr/ext/workflow/workflow_activity_context.py diff --git a/ext/dapr-ext-workflow/dapr/ext/workflow/workflow_context.py b/dapr/ext/workflow/workflow_context.py similarity index 100% rename from ext/dapr-ext-workflow/dapr/ext/workflow/workflow_context.py rename to dapr/ext/workflow/workflow_context.py diff --git a/ext/dapr-ext-workflow/dapr/ext/workflow/workflow_runtime.py b/dapr/ext/workflow/workflow_runtime.py similarity index 100% rename from ext/dapr-ext-workflow/dapr/ext/workflow/workflow_runtime.py rename to dapr/ext/workflow/workflow_runtime.py index f33622a15..be0c3406d 100644 --- a/ext/dapr-ext-workflow/dapr/ext/workflow/workflow_runtime.py +++ b/dapr/ext/workflow/workflow_runtime.py @@ -19,18 +19,18 @@ from typing import Optional, Sequence, TypeVar, Union import grpc -from dapr.ext.workflow._durabletask import task, worker -from dapr.ext.workflow.dapr_workflow_context import DaprWorkflowContext -from dapr.ext.workflow.logger import Logger, LoggerOptions -from dapr.ext.workflow.util import getAddress -from dapr.ext.workflow.workflow_activity_context import Activity, WorkflowActivityContext -from dapr.ext.workflow.workflow_context import Workflow from dapr.clients import DaprInternalError from dapr.clients.grpc.interceptors import DaprClientTimeoutInterceptor from dapr.clients.http.client import DAPR_API_TOKEN_HEADER from dapr.conf import settings from dapr.conf.helpers import GrpcEndpoint +from dapr.ext.workflow._durabletask import task, worker +from dapr.ext.workflow.dapr_workflow_context import DaprWorkflowContext +from dapr.ext.workflow.logger import Logger, LoggerOptions +from dapr.ext.workflow.util import getAddress +from dapr.ext.workflow.workflow_activity_context import Activity, WorkflowActivityContext +from dapr.ext.workflow.workflow_context import Workflow from . import _model_protocol diff --git a/ext/dapr-ext-workflow/dapr/ext/workflow/workflow_state.py b/dapr/ext/workflow/workflow_state.py similarity index 100% rename from ext/dapr-ext-workflow/dapr/ext/workflow/workflow_state.py rename to dapr/ext/workflow/workflow_state.py diff --git a/examples/AGENTS.md b/examples/AGENTS.md index e96e493e8..b5df9aa04 100644 --- a/examples/AGENTS.md +++ b/examples/AGENTS.md @@ -68,62 +68,62 @@ Common component types used in examples: `state.redis`, `pubsub.redis`, `lock.re ### State management | Example | Pattern | SDK packages | Has components | |---------|---------|-------------|----------------| -| `state_store` | Standalone client | `dapr`, `dapr-ext-grpc` | Yes | -| `state_store_query` | Standalone client | `dapr`, `dapr-ext-grpc` | Yes | +| `state_store` | Standalone client | `dapr[grpc]` | Yes | +| `state_store_query` | Standalone client | `dapr[grpc]` | Yes | ### Service invocation | Example | Pattern | SDK packages | Has components | |---------|---------|-------------|----------------| -| `invoke-simple` | Client-server (receiver/caller) | `dapr`, `dapr-ext-grpc` | No | -| `invoke-custom-data` | Client-server (protobuf) | `dapr`, `dapr-ext-grpc` | No | +| `invoke-simple` | Client-server (receiver/caller) | `dapr[grpc]` | No | +| `invoke-custom-data` | Client-server (protobuf) | `dapr[grpc]` | No | | `invoke-http` | Client-server (Flask) | `dapr`, Flask | No | -| `invoke-binding` | Client with bindings | `dapr`, `dapr-ext-grpc` | Yes | -| `grpc_proxying` | Client-server (gRPC proxy) | `dapr`, `dapr-ext-grpc` | No (has config.yaml) | +| `invoke-binding` | Client with bindings | `dapr[grpc]` | Yes | +| `grpc_proxying` | Client-server (gRPC proxy) | `dapr[grpc]` | No (has config.yaml) | ### Pub/sub | Example | Pattern | SDK packages | Has components | |---------|---------|-------------|----------------| -| `pubsub-simple` | Client-server (publisher/subscriber) | `dapr`, `dapr-ext-grpc` | No | +| `pubsub-simple` | Client-server (publisher/subscriber) | `dapr[grpc]` | No | | `pubsub-streaming` | Streaming pub/sub | `dapr` (base only) | No | | `pubsub-streaming-async` | Async streaming pub/sub | `dapr` (base only) | No | ### Virtual actors | Example | Pattern | SDK packages | Has components | |---------|---------|-------------|----------------| -| `demo_actor` | Client-server (FastAPI/Flask + client) | `dapr`, `dapr-ext-fastapi` | No | +| `demo_actor` | Client-server (FastAPI/Flask + client) | `dapr[fastapi]` (FastAPI) / `dapr[flask]` (Flask) | No | ### Workflow | Example | Pattern | SDK packages | Has components | |---------|---------|-------------|----------------| -| `workflow` | Multiple standalone scripts | `dapr-ext-workflow`, `dapr` | No | +| `workflow` | Multiple standalone scripts | `dapr[workflow]` | No | The `workflow` example includes: `simple.py`, `task_chaining.py`, `fan_out_fan_in.py`, `human_approval.py`, `monitor.py`, `child_workflow.py`, `cross-app1/2/3.py`, `versioning.py`, `simple_aio_client.py`. ### Secrets, configuration, locks | Example | Pattern | SDK packages | Has components | |---------|---------|-------------|----------------| -| `secret_store` | Standalone client | `dapr`, `dapr-ext-grpc` | Yes | -| `configuration` | Standalone client with subscription | `dapr`, `dapr-ext-grpc` | Yes | -| `distributed_lock` | Standalone client | `dapr`, `dapr-ext-grpc` | Yes | +| `secret_store` | Standalone client | `dapr[grpc]` | Yes | +| `configuration` | Standalone client with subscription | `dapr[grpc]` | Yes | +| `distributed_lock` | Standalone client | `dapr[grpc]` | Yes | ### Cryptography | Example | Pattern | SDK packages | Has components | |---------|---------|-------------|----------------| -| `crypto` | Standalone (sync + async) | `dapr`, `dapr-ext-grpc` | Yes | +| `crypto` | Standalone (sync + async) | `dapr[grpc]` | Yes | ### Jobs, tracing, metadata, errors | Example | Pattern | SDK packages | Has components | |---------|---------|-------------|----------------| -| `jobs` | Standalone + gRPC event handler | `dapr`, `dapr-ext-grpc` | No | -| `w3c-tracing` | Client-server with OpenTelemetry | `dapr`, `dapr-ext-grpc`, OpenTelemetry | No | -| `metadata` | Standalone client | `dapr`, `dapr-ext-grpc` | Yes | -| `error_handling` | Standalone client | `dapr`, `dapr-ext-grpc` | Yes | +| `jobs` | Standalone + gRPC event handler | `dapr[grpc]` | No | +| `w3c-tracing` | Client-server with OpenTelemetry | `dapr[grpc]`, OpenTelemetry | No | +| `metadata` | Standalone client | `dapr[grpc]` | Yes | +| `error_handling` | Standalone client | `dapr[grpc]` | Yes | ### AI/LLM integrations | Example | Pattern | SDK packages | Has components | |---------|---------|-------------|----------------| | `conversation` | Standalone client | `dapr` (base, uses sidecar) | No (uses config/) | -| `langgraph-checkpointer` | Standalone gRPC server | `dapr-ext-langgraph`, LangGraph, LangChain | Yes | +| `langgraph-checkpointer` | Standalone gRPC server | `dapr[langgraph]`, LangGraph, LangChain | Yes | ## Adding a new example diff --git a/examples/configuration/README.md b/examples/configuration/README.md index ec260b531..5f6d42f49 100644 --- a/examples/configuration/README.md +++ b/examples/configuration/README.md @@ -15,7 +15,7 @@ It demonstrates the following APIs: <!-- Our CI/CD pipeline automatically installs the correct version, so we can skip this step in the automation --> ```bash -pip3 install dapr dapr-ext-grpc +pip3 install "dapr[grpc]" ``` ## Store the configuration in configurationstore diff --git a/examples/demo_actor/demo_actor/demo_actor_flask.py b/examples/demo_actor/demo_actor/demo_actor_flask.py index de1245ad0..1c6245e95 100644 --- a/examples/demo_actor/demo_actor/demo_actor_flask.py +++ b/examples/demo_actor/demo_actor/demo_actor_flask.py @@ -12,11 +12,11 @@ from demo_actor import DemoActor from flask import Flask, jsonify -from flask_dapr.actor import DaprActor from dapr.actor.runtime.config import ActorReentrancyConfig, ActorRuntimeConfig, ActorTypeConfig from dapr.actor.runtime.runtime import ActorRuntime from dapr.conf import settings +from dapr.ext.flask.actor import DaprActor app = Flask(f'{DemoActor.__name__}Service') diff --git a/examples/demo_actor/demo_actor/demo_actor_service.py b/examples/demo_actor/demo_actor/demo_actor_service.py index c67b28c87..046a8df24 100644 --- a/examples/demo_actor/demo_actor/demo_actor_service.py +++ b/examples/demo_actor/demo_actor/demo_actor_service.py @@ -10,12 +10,12 @@ # See the License for the specific language governing permissions and # limitations under the License. -from dapr.ext.fastapi import DaprActor # type: ignore from demo_actor import DemoActor from fastapi import FastAPI # type: ignore from dapr.actor.runtime.config import ActorReentrancyConfig, ActorRuntimeConfig, ActorTypeConfig from dapr.actor.runtime.runtime import ActorRuntime +from dapr.ext.fastapi import DaprActor # type: ignore app = FastAPI(title=f'{DemoActor.__name__}Service') diff --git a/examples/demo_actor/demo_actor/requirements.txt b/examples/demo_actor/demo_actor/requirements.txt index 3ec219df2..99bcd5fe7 100644 --- a/examples/demo_actor/demo_actor/requirements.txt +++ b/examples/demo_actor/demo_actor/requirements.txt @@ -1 +1 @@ -dapr-ext-fastapi>=1.17.0.dev +dapr[fastapi,flask] >= 1.19.0.dev \ No newline at end of file diff --git a/examples/distributed_lock/README.md b/examples/distributed_lock/README.md index 1c60e6c85..062e5cacc 100644 --- a/examples/distributed_lock/README.md +++ b/examples/distributed_lock/README.md @@ -19,7 +19,7 @@ all the distributed lock API methods available as example. <!-- Our CI/CD pipeline automatically installs the correct version, so we can skip this step in the automation --> ```bash -pip3 install dapr dapr-ext-grpc +pip3 install "dapr[grpc]" ``` ## Run the example diff --git a/examples/error_handling/README.md b/examples/error_handling/README.md index 480d73635..49e4a3f2a 100644 --- a/examples/error_handling/README.md +++ b/examples/error_handling/README.md @@ -15,7 +15,7 @@ It uses the default configuration from Dapr init in [self-hosted mode](https://g <!-- Our CI/CD pipeline automatically installs the correct version, so we can skip this step in the automation --> ```bash -pip3 install dapr dapr-ext-grpc +pip3 install "dapr[grpc]" ``` ## Run the example diff --git a/examples/grpc_proxying/README.md b/examples/grpc_proxying/README.md index cd9aaa892..179e0a80e 100644 --- a/examples/grpc_proxying/README.md +++ b/examples/grpc_proxying/README.md @@ -14,7 +14,7 @@ This example creates a gRPC service using the protobuf file and adds it to the P <!-- Our CI/CD pipeline automatically installs the correct version, so we can skip this step in the automation --> ```bash -pip3 install dapr dapr-ext-grpc +pip3 install "dapr[grpc]" ``` ## Running in self-hosted mode diff --git a/examples/grpc_proxying/invoke-receiver.py b/examples/grpc_proxying/invoke-receiver.py index 0a140ff79..b6ced9604 100644 --- a/examples/grpc_proxying/invoke-receiver.py +++ b/examples/grpc_proxying/invoke-receiver.py @@ -2,9 +2,10 @@ import grpc import helloworld_service_pb2_grpc -from dapr.ext.grpc import App from helloworld_service_pb2 import HelloReply, HelloRequest +from dapr.ext.grpc import App + class HelloWorldService(helloworld_service_pb2_grpc.HelloWorldService): def SayHello(self, request: HelloRequest, context: grpc.aio.ServicerContext) -> HelloReply: diff --git a/examples/invoke-binding/README.md b/examples/invoke-binding/README.md index 6126ea00e..c50652773 100644 --- a/examples/invoke-binding/README.md +++ b/examples/invoke-binding/README.md @@ -14,7 +14,7 @@ This example utilizes a publisher and a receiver for the InvokeBinding / OnBindi <!-- Our CI/CD pipeline automatically installs the correct version, so we can skip this step in the automation --> ```bash -pip3 install dapr dapr-ext-grpc +pip3 install "dapr[grpc]" ``` ## Run example diff --git a/examples/invoke-custom-data/README.md b/examples/invoke-custom-data/README.md index b5426c722..560ff95d3 100644 --- a/examples/invoke-custom-data/README.md +++ b/examples/invoke-custom-data/README.md @@ -14,7 +14,7 @@ This example utilizes a receiver and a caller for the OnInvoke / Invoke function <!-- Our CI/CD pipeline automatically installs the correct version, so we can skip this step in the automation --> ```bash -pip3 install dapr dapr-ext-grpc +pip3 install "dapr[grpc]" ``` ## How To - Run Example diff --git a/examples/invoke-custom-data/invoke-receiver.py b/examples/invoke-custom-data/invoke-receiver.py index 543d4fceb..cd1e074d5 100644 --- a/examples/invoke-custom-data/invoke-receiver.py +++ b/examples/invoke-custom-data/invoke-receiver.py @@ -1,4 +1,5 @@ import proto.response_pb2 as response_messages + from dapr.ext.grpc import App, InvokeMethodRequest app = App() diff --git a/examples/invoke-simple/README.md b/examples/invoke-simple/README.md index 35fd2b9ed..3e99c18f5 100644 --- a/examples/invoke-simple/README.md +++ b/examples/invoke-simple/README.md @@ -14,7 +14,7 @@ This example utilizes a receiver and a caller for the OnInvoke / Invoke function <!-- Our CI/CD pipeline automatically installs the correct version, so we can skip this step in the automation --> ```bash -pip3 install dapr dapr-ext-grpc +pip3 install "dapr[grpc]" ``` ## Running in self-hosted mode diff --git a/examples/invoke-simple/requirements.txt b/examples/invoke-simple/requirements.txt index 299df8fd7..b98935e65 100644 --- a/examples/invoke-simple/requirements.txt +++ b/examples/invoke-simple/requirements.txt @@ -1,2 +1 @@ -dapr-ext-grpc >= 1.17.0.dev -dapr >= 1.17.0.dev +dapr[grpc] >= 1.19.0.dev \ No newline at end of file diff --git a/examples/jobs/README.md b/examples/jobs/README.md index 5c0fb514f..c24592616 100644 --- a/examples/jobs/README.md +++ b/examples/jobs/README.md @@ -24,7 +24,7 @@ It includes two examples that showcase different aspects of the Jobs API: <!-- Our CI/CD pipeline automatically installs the correct version, so we can skip this step in the automation --> ```bash -pip3 install dapr dapr-ext-grpc +pip3 install "dapr[grpc]" ``` ## Run the example diff --git a/examples/jobs/job_processing.py b/examples/jobs/job_processing.py index 6d384cbb0..89ae1e7ce 100644 --- a/examples/jobs/job_processing.py +++ b/examples/jobs/job_processing.py @@ -15,9 +15,8 @@ import threading import time -from dapr.ext.grpc import App, JobEvent - from dapr.clients import ConstantFailurePolicy, DaprClient, Job +from dapr.ext.grpc import App, JobEvent try: from google.protobuf.any_pb2 import Any as GrpcAny diff --git a/examples/langgraph-checkpointer/agent.py b/examples/langgraph-checkpointer/agent.py index 8ea98ae82..43479f46d 100644 --- a/examples/langgraph-checkpointer/agent.py +++ b/examples/langgraph-checkpointer/agent.py @@ -1,9 +1,10 @@ -from dapr.ext.langgraph import DaprCheckpointer from langchain_core.messages import HumanMessage, SystemMessage from langchain_ollama import ChatOllama from langgraph.graph import START, MessagesState, StateGraph from langgraph.prebuilt import ToolNode, tools_condition +from dapr.ext.langgraph import DaprCheckpointer + def add(a: int, b: int) -> int: """Adds a and b. diff --git a/examples/mcp/mcp_tool_discovery.py b/examples/mcp/mcp_tool_discovery.py index 383de8bc0..a5171c3c1 100644 --- a/examples/mcp/mcp_tool_discovery.py +++ b/examples/mcp/mcp_tool_discovery.py @@ -41,6 +41,8 @@ dapr run --app-id mcp-demo --resources-path ./resources -- python mcp_tool_discovery.py """ +from pydantic import ValidationError + from dapr.ext.workflow import ( DaprMCPClient, DaprWorkflowClient, @@ -48,7 +50,6 @@ WorkflowRuntime, ) from dapr.ext.workflow.mcp_schema import create_pydantic_model_from_schema -from pydantic import ValidationError def call_mcp_tool_workflow(ctx: DaprWorkflowContext, wf_input: dict): diff --git a/examples/mcp/requirements.txt b/examples/mcp/requirements.txt index 8529ad0bb..aad3ddd63 100644 --- a/examples/mcp/requirements.txt +++ b/examples/mcp/requirements.txt @@ -1,3 +1,3 @@ -dapr-ext-workflow +dapr[workflow] >= 1.19.0.dev mcp -pydantic>=2.0 +pydantic >= 2.0 \ No newline at end of file diff --git a/examples/metadata/README.md b/examples/metadata/README.md index ee3d9d20c..8a9dc2bfb 100644 --- a/examples/metadata/README.md +++ b/examples/metadata/README.md @@ -22,7 +22,7 @@ It creates a client using `DaprClient`, uses a set of components defined in the <!-- Our CI/CD pipeline automatically installs the correct version, so we can skip this step in the automation --> ```bash -pip3 install dapr dapr-ext-grpc +pip3 install "dapr[grpc]" ``` ## Run the example diff --git a/examples/pubsub-simple/README.md b/examples/pubsub-simple/README.md index 1cf38c9c1..1b48e609a 100644 --- a/examples/pubsub-simple/README.md +++ b/examples/pubsub-simple/README.md @@ -17,7 +17,7 @@ The subscriber will tell dapr to retry delivery of the first message it receives <!-- Our CI/CD pipeline automatically installs the correct version, so we can skip this step in the automation --> ```bash -pip3 install dapr dapr-ext-grpc +pip3 install "dapr[grpc]" ``` ## Run the example diff --git a/examples/pubsub-simple/subscriber.py b/examples/pubsub-simple/subscriber.py index 4d36f2807..7dab9e922 100644 --- a/examples/pubsub-simple/subscriber.py +++ b/examples/pubsub-simple/subscriber.py @@ -15,9 +15,9 @@ from time import sleep from cloudevents.sdk.event import v1 -from dapr.ext.grpc import App from dapr.clients.grpc._response import TopicEventResponse +from dapr.ext.grpc import App from dapr.proto import appcallback_v1 app = App() diff --git a/examples/secret_store/README.md b/examples/secret_store/README.md index d384c6fc2..1e556d17a 100644 --- a/examples/secret_store/README.md +++ b/examples/secret_store/README.md @@ -15,7 +15,7 @@ This example also illustrates the use of access control for secrets. <!-- Our CI/CD pipeline automatically installs the correct version, so we can skip this step in the automation --> ```bash -pip3 install dapr dapr-ext-grpc +pip3 install "dapr[grpc]" ``` ## Run the example diff --git a/examples/state_store/README.md b/examples/state_store/README.md index 66627c9bb..ac7b100d9 100644 --- a/examples/state_store/README.md +++ b/examples/state_store/README.md @@ -24,7 +24,7 @@ It uses the default configuration from Dapr init in [self-hosted mode](https://g <!-- Our CI/CD pipeline automatically installs the correct version, so we can skip this step in the automation --> ```bash -pip3 install dapr dapr-ext-grpc +pip3 install "dapr[grpc]" ``` ## Run the example diff --git a/examples/state_store_query/README.md b/examples/state_store_query/README.md index cab871789..6037971f3 100644 --- a/examples/state_store_query/README.md +++ b/examples/state_store_query/README.md @@ -15,7 +15,7 @@ It demonstrates the following APIs: <!-- Our CI/CD pipeline automatically installs the correct version, so we can skip this step in the automation --> ```bash -pip3 install dapr dapr-ext-grpc +pip3 install "dapr[grpc]" ``` ## Store the configuration in configurationstore diff --git a/examples/w3c-tracing/invoke-receiver.py b/examples/w3c-tracing/invoke-receiver.py index bb49236a8..9d6450acf 100644 --- a/examples/w3c-tracing/invoke-receiver.py +++ b/examples/w3c-tracing/invoke-receiver.py @@ -3,7 +3,6 @@ import typing from concurrent import futures -from dapr.ext.grpc import App, InvokeMethodRequest, InvokeMethodResponse from opentelemetry import trace from opentelemetry.exporter.zipkin.json import ZipkinExporter from opentelemetry.instrumentation.grpc import GrpcInstrumentorServer @@ -13,6 +12,7 @@ from opentelemetry.trace.propagation.tracecontext import TraceContextTextMapPropagator from dapr.clients import DaprClient +from dapr.ext.grpc import App, InvokeMethodRequest, InvokeMethodResponse # Create a tracer provider tracer_provider = TracerProvider(sampler=ALWAYS_ON) diff --git a/examples/w3c-tracing/requirements.txt b/examples/w3c-tracing/requirements.txt index 32683b57c..02c334d0e 100644 --- a/examples/w3c-tracing/requirements.txt +++ b/examples/w3c-tracing/requirements.txt @@ -1,5 +1,4 @@ -dapr-ext-grpc >= 1.17.0.dev -dapr >= 1.17.0.dev +dapr[grpc] >= 1.19.0.dev opentelemetry-sdk opentelemetry-instrumentation-grpc -opentelemetry-exporter-zipkin +opentelemetry-exporter-zipkin \ No newline at end of file diff --git a/examples/workflow/human_approval.py b/examples/workflow/human_approval.py index e12bf5b5e..0ca373e53 100644 --- a/examples/workflow/human_approval.py +++ b/examples/workflow/human_approval.py @@ -16,7 +16,6 @@ from datetime import timedelta import dapr.ext.workflow as wf - from dapr.clients import DaprClient wfr = wf.WorkflowRuntime() diff --git a/examples/workflow/pydantic_models.py b/examples/workflow/pydantic_models.py index e9b1471ea..134c26938 100644 --- a/examples/workflow/pydantic_models.py +++ b/examples/workflow/pydantic_models.py @@ -17,13 +17,14 @@ apps. """ +from pydantic import BaseModel + from dapr.ext.workflow import ( DaprWorkflowClient, DaprWorkflowContext, WorkflowActivityContext, WorkflowRuntime, ) -from pydantic import BaseModel class OrderRequest(BaseModel): diff --git a/examples/workflow/requirements.txt b/examples/workflow/requirements.txt index 023e2c2b4..0e49e6638 100644 --- a/examples/workflow/requirements.txt +++ b/examples/workflow/requirements.txt @@ -1,3 +1,2 @@ -dapr-ext-workflow>=1.17.0.dev -dapr>=1.17.0.dev -pydantic>=2.0 +dapr[workflow] >= 1.19.0.dev +pydantic >= 2.0 \ No newline at end of file diff --git a/examples/workflow/simple.py b/examples/workflow/simple.py index dc0ea0b6a..5bbdf68a9 100644 --- a/examples/workflow/simple.py +++ b/examples/workflow/simple.py @@ -12,6 +12,8 @@ from datetime import timedelta from time import sleep +from dapr.clients.exceptions import DaprInternalError +from dapr.conf import Settings from dapr.ext.workflow import ( DaprWorkflowClient, DaprWorkflowContext, @@ -21,9 +23,6 @@ when_any, ) -from dapr.clients.exceptions import DaprInternalError -from dapr.conf import Settings - settings = Settings() counter = 0 diff --git a/examples/workflow/simple_aio_client.py b/examples/workflow/simple_aio_client.py index fd93a5016..5af41adc6 100644 --- a/examples/workflow/simple_aio_client.py +++ b/examples/workflow/simple_aio_client.py @@ -12,6 +12,8 @@ import asyncio from datetime import timedelta +from dapr.clients.exceptions import DaprInternalError +from dapr.conf import Settings from dapr.ext.workflow import ( DaprWorkflowContext, RetryPolicy, @@ -21,9 +23,6 @@ ) from dapr.ext.workflow.aio import DaprWorkflowClient -from dapr.clients.exceptions import DaprInternalError -from dapr.conf import Settings - settings = Settings() counter = 0 diff --git a/ext/dapr-ext-fastapi/LICENSE b/ext/dapr-ext-fastapi/LICENSE deleted file mode 100644 index be033a7fd..000000000 --- a/ext/dapr-ext-fastapi/LICENSE +++ /dev/null @@ -1,203 +0,0 @@ -Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright 2021 The Dapr Authors. - - and others that have contributed code to the public domain. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. \ No newline at end of file diff --git a/ext/dapr-ext-fastapi/README.rst b/ext/dapr-ext-fastapi/README.rst deleted file mode 100644 index 9d44f633e..000000000 --- a/ext/dapr-ext-fastapi/README.rst +++ /dev/null @@ -1,22 +0,0 @@ -dapr-ext-fastapi extension -========================== - -|pypi| - -.. |pypi| image:: https://badge.fury.io/py/dapr-ext-fastapi.svg - :target: https://pypi.org/project/dapr-ext-fastapi/ - -This FastAPI extension is used for FastAPI http server. - -Installation ------------- - -:: - - pip install dapr-ext-fastapi - -References ----------- - -* `Dapr <https://github.com/dapr/dapr>`_ -* `Dapr Python-SDK <https://github.com/dapr/python-sdk>`_ diff --git a/ext/dapr-ext-fastapi/pyproject.toml b/ext/dapr-ext-fastapi/pyproject.toml deleted file mode 100644 index 2d272c329..000000000 --- a/ext/dapr-ext-fastapi/pyproject.toml +++ /dev/null @@ -1,44 +0,0 @@ -[project] -name = "dapr-ext-fastapi" -dynamic = ["version"] -description = "Dapr FastAPI Extension for the Dapr Python SDK." -readme = "README.rst" -requires-python = ">=3.10" -license = {text = "Apache-2.0"} -authors = [{name = "Dapr Authors", email = "dapr@dapr.io"}] -classifiers = [ - "Development Status :: 5 - Production/Stable", - "Intended Audience :: Developers", - "License :: OSI Approved :: Apache Software License", - "Operating System :: OS Independent", - "Programming Language :: Python", - "Programming Language :: Python :: 3.10", - "Programming Language :: Python :: 3.11", - "Programming Language :: Python :: 3.12", - "Programming Language :: Python :: 3.13", - "Programming Language :: Python :: 3.14", -] -dependencies = [ - "dapr", - "uvicorn>=0.11.6,<1.0.0", - "fastapi>=0.60.1,<1.0.0", -] - -[project.urls] -Documentation = "https://github.com/dapr/docs" -Source = "https://github.com/dapr/python-sdk" - -[build-system] -requires = ["hatchling"] -build-backend = "hatchling.build" - -[tool.hatch.version] -source = "regex" -path = "../../VERSION" -pattern = '(?P<version>\S+)' - -[tool.hatch.build.targets.wheel] -only-include = ["dapr/ext/fastapi"] - -[tool.uv.sources] -dapr = { workspace = true } diff --git a/ext/dapr-ext-grpc/LICENSE b/ext/dapr-ext-grpc/LICENSE deleted file mode 100644 index be033a7fd..000000000 --- a/ext/dapr-ext-grpc/LICENSE +++ /dev/null @@ -1,203 +0,0 @@ -Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright 2021 The Dapr Authors. - - and others that have contributed code to the public domain. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. \ No newline at end of file diff --git a/ext/dapr-ext-grpc/README.rst b/ext/dapr-ext-grpc/README.rst deleted file mode 100644 index 2c610e388..000000000 --- a/ext/dapr-ext-grpc/README.rst +++ /dev/null @@ -1,22 +0,0 @@ -dapr-ext-grpc extension -======================= - -|pypi| - -.. |pypi| image:: https://badge.fury.io/py/dapr-ext-grpc.svg - :target: https://pypi.org/project/dapr-ext-grpc/ - -This gRPC extension is used for gRPC appcallback - -Installation ------------- - -:: - - pip install dapr-ext-grpc - -References ----------- - -* `Dapr <https://github.com/dapr/dapr>`_ -* `Dapr Python-SDK <https://github.com/dapr/python-sdk>`_ diff --git a/ext/dapr-ext-grpc/pyproject.toml b/ext/dapr-ext-grpc/pyproject.toml deleted file mode 100644 index 393c99476..000000000 --- a/ext/dapr-ext-grpc/pyproject.toml +++ /dev/null @@ -1,43 +0,0 @@ -[project] -name = "dapr-ext-grpc" -dynamic = ["version"] -description = "Dapr gRPC AppCallback Extension for the Dapr Python SDK." -readme = "README.rst" -requires-python = ">=3.10" -license = {text = "Apache-2.0"} -authors = [{name = "Dapr Authors", email = "dapr@dapr.io"}] -classifiers = [ - "Development Status :: 5 - Production/Stable", - "Intended Audience :: Developers", - "License :: OSI Approved :: Apache Software License", - "Operating System :: OS Independent", - "Programming Language :: Python", - "Programming Language :: Python :: 3.10", - "Programming Language :: Python :: 3.11", - "Programming Language :: Python :: 3.12", - "Programming Language :: Python :: 3.13", - "Programming Language :: Python :: 3.14", -] -dependencies = [ - "dapr", - "cloudevents>=1.0.0,<2.0.0", -] - -[project.urls] -Documentation = "https://github.com/dapr/docs" -Source = "https://github.com/dapr/python-sdk" - -[build-system] -requires = ["hatchling"] -build-backend = "hatchling.build" - -[tool.hatch.version] -source = "regex" -path = "../../VERSION" -pattern = '(?P<version>\S+)' - -[tool.hatch.build.targets.wheel] -only-include = ["dapr/ext/grpc"] - -[tool.uv.sources] -dapr = { workspace = true } diff --git a/ext/dapr-ext-langgraph/LICENSE b/ext/dapr-ext-langgraph/LICENSE deleted file mode 100644 index be033a7fd..000000000 --- a/ext/dapr-ext-langgraph/LICENSE +++ /dev/null @@ -1,203 +0,0 @@ -Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright 2021 The Dapr Authors. - - and others that have contributed code to the public domain. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. \ No newline at end of file diff --git a/ext/dapr-ext-langgraph/README.rst b/ext/dapr-ext-langgraph/README.rst deleted file mode 100644 index dbd75edce..000000000 --- a/ext/dapr-ext-langgraph/README.rst +++ /dev/null @@ -1,22 +0,0 @@ -dapr-ext-langgraph extension -============================ - -|pypi| - -.. |pypi| image:: https://badge.fury.io/py/dapr-ext-langgraph.svg - :target: https://pypi.org/project/dapr-ext-langgraph/ - -This is the Dapr Checkpointer extension for LangGraph - -Installation ------------- - -:: - - pip install dapr-ext-langgraph - -References ----------- - -* `Dapr <https://github.com/dapr/dapr>`_ -* `Dapr Python-SDK <https://github.com/dapr/python-sdk>`_ diff --git a/ext/dapr-ext-langgraph/pyproject.toml b/ext/dapr-ext-langgraph/pyproject.toml deleted file mode 100644 index acb7e0014..000000000 --- a/ext/dapr-ext-langgraph/pyproject.toml +++ /dev/null @@ -1,46 +0,0 @@ -[project] -name = "dapr-ext-langgraph" -dynamic = ["version"] -description = "Dapr LangGraph Checkpointer Extension for the Dapr Python SDK." -readme = "README.rst" -requires-python = ">=3.10" -license = {text = "Apache-2.0"} -authors = [{name = "Dapr Authors", email = "dapr@dapr.io"}] -classifiers = [ - "Development Status :: 5 - Production/Stable", - "Intended Audience :: Developers", - "License :: OSI Approved :: Apache Software License", - "Operating System :: OS Independent", - "Programming Language :: Python", - "Programming Language :: Python :: 3.10", - "Programming Language :: Python :: 3.11", - "Programming Language :: Python :: 3.12", - "Programming Language :: Python :: 3.13", - "Programming Language :: Python :: 3.14", -] -dependencies = [ - "dapr", - "langgraph>=0.3.6,<2.0.0", - "langchain>=0.1.17,<2.0.0", - "python-ulid>=3.0.0,<4.0.0", - "msgpack-python>=0.4.5,<1.0.0", -] - -[project.urls] -Documentation = "https://github.com/dapr/docs" -Source = "https://github.com/dapr/python-sdk" - -[build-system] -requires = ["hatchling"] -build-backend = "hatchling.build" - -[tool.hatch.version] -source = "regex" -path = "../../VERSION" -pattern = '(?P<version>\S+)' - -[tool.hatch.build.targets.wheel] -only-include = ["dapr/ext/langgraph"] - -[tool.uv.sources] -dapr = { workspace = true } diff --git a/ext/dapr-ext-strands/LICENSE b/ext/dapr-ext-strands/LICENSE deleted file mode 100644 index be033a7fd..000000000 --- a/ext/dapr-ext-strands/LICENSE +++ /dev/null @@ -1,203 +0,0 @@ -Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright 2021 The Dapr Authors. - - and others that have contributed code to the public domain. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. \ No newline at end of file diff --git a/ext/dapr-ext-strands/README.rst b/ext/dapr-ext-strands/README.rst deleted file mode 100644 index d45a1a40c..000000000 --- a/ext/dapr-ext-strands/README.rst +++ /dev/null @@ -1,22 +0,0 @@ -dapr-ext-strands extension -========================== - -|pypi| - -.. |pypi| image:: https://badge.fury.io/py/dapr-ext-strands.svg - :target: https://pypi.org/project/dapr-ext-strands/ - -This is the Dapr Session Manager for Strands Agents - -Installation ------------- - -:: - - pip install dapr-ext-strands - -References ----------- - -* `Dapr <https://github.com/dapr/dapr>`_ -* `Dapr Python-SDK <https://github.com/dapr/python-sdk>`_ diff --git a/ext/dapr-ext-strands/pyproject.toml b/ext/dapr-ext-strands/pyproject.toml deleted file mode 100644 index 1ff0de72b..000000000 --- a/ext/dapr-ext-strands/pyproject.toml +++ /dev/null @@ -1,46 +0,0 @@ -[project] -name = "dapr-ext-strands" -dynamic = ["version"] -description = "Dapr Strands Agent Sessions Extension for the Dapr Python SDK." -readme = "README.rst" -requires-python = ">=3.10" -license = {text = "Apache-2.0"} -authors = [{name = "Dapr Authors", email = "dapr@dapr.io"}] -classifiers = [ - "Development Status :: 5 - Production/Stable", - "Intended Audience :: Developers", - "License :: OSI Approved :: Apache Software License", - "Operating System :: OS Independent", - "Programming Language :: Python", - "Programming Language :: Python :: 3.10", - "Programming Language :: Python :: 3.11", - "Programming Language :: Python :: 3.12", - "Programming Language :: Python :: 3.13", - "Programming Language :: Python :: 3.14", -] -dependencies = [ - "dapr", - "strands-agents>=1.30.0,<2.0.0", - "strands-agents-tools>=0.2.22,<1.0.0", - "python-ulid>=3.0.0,<4.0.0", - "msgpack-python>=0.4.5,<1.0.0", -] - -[project.urls] -Documentation = "https://github.com/dapr/docs" -Source = "https://github.com/dapr/python-sdk" - -[build-system] -requires = ["hatchling"] -build-backend = "hatchling.build" - -[tool.hatch.version] -source = "regex" -path = "../../VERSION" -pattern = '(?P<version>\S+)' - -[tool.hatch.build.targets.wheel] -only-include = ["dapr/ext/strands"] - -[tool.uv.sources] -dapr = { workspace = true } diff --git a/ext/dapr-ext-workflow/LICENSE b/ext/dapr-ext-workflow/LICENSE deleted file mode 100644 index be033a7fd..000000000 --- a/ext/dapr-ext-workflow/LICENSE +++ /dev/null @@ -1,203 +0,0 @@ -Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright 2021 The Dapr Authors. - - and others that have contributed code to the public domain. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. \ No newline at end of file diff --git a/ext/dapr-ext-workflow/README.rst b/ext/dapr-ext-workflow/README.rst deleted file mode 100644 index aa0003c6e..000000000 --- a/ext/dapr-ext-workflow/README.rst +++ /dev/null @@ -1,23 +0,0 @@ -dapr-ext-workflow extension -=========================== - -|pypi| - -.. |pypi| image:: https://badge.fury.io/py/dapr-ext-workflow.svg - :target: https://pypi.org/project/dapr-ext-workflow/ - -This is the workflow authoring extension for Dapr Workflow - - -Installation ------------- - -:: - - pip install dapr-ext-workflow - -References ----------- - -* `Dapr <https://github.com/dapr/dapr>`_ -* `Dapr Python-SDK <https://github.com/dapr/python-sdk>`_ diff --git a/ext/dapr-ext-workflow/pyproject.toml b/ext/dapr-ext-workflow/pyproject.toml deleted file mode 100644 index 93baaf554..000000000 --- a/ext/dapr-ext-workflow/pyproject.toml +++ /dev/null @@ -1,42 +0,0 @@ -[project] -name = "dapr-ext-workflow" -dynamic = ["version"] -description = "Dapr Workflow Authoring Extension for the Dapr Python SDK." -readme = "README.rst" -requires-python = ">=3.10" -license = {text = "Apache-2.0"} -authors = [{name = "Dapr Authors", email = "dapr@dapr.io"}] -classifiers = [ - "Development Status :: 5 - Production/Stable", - "Intended Audience :: Developers", - "License :: OSI Approved :: Apache Software License", - "Operating System :: OS Independent", - "Programming Language :: Python", - "Programming Language :: Python :: 3.10", - "Programming Language :: Python :: 3.11", - "Programming Language :: Python :: 3.12", - "Programming Language :: Python :: 3.13", - "Programming Language :: Python :: 3.14", -] -dependencies = [ - "dapr", -] - -[project.urls] -Documentation = "https://github.com/dapr/docs" -Source = "https://github.com/dapr/python-sdk" - -[build-system] -requires = ["hatchling"] -build-backend = "hatchling.build" - -[tool.hatch.version] -source = "regex" -path = "../../VERSION" -pattern = '(?P<version>\S+)' - -[tool.hatch.build.targets.wheel] -only-include = ["dapr/ext/workflow"] - -[tool.uv.sources] -dapr = { workspace = true } diff --git a/ext/flask_dapr/LICENSE b/ext/flask_dapr/LICENSE deleted file mode 100644 index be033a7fd..000000000 --- a/ext/flask_dapr/LICENSE +++ /dev/null @@ -1,203 +0,0 @@ -Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright 2021 The Dapr Authors. - - and others that have contributed code to the public domain. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. \ No newline at end of file diff --git a/ext/flask_dapr/README.rst b/ext/flask_dapr/README.rst deleted file mode 100644 index a44d11898..000000000 --- a/ext/flask_dapr/README.rst +++ /dev/null @@ -1,39 +0,0 @@ -Dapr flask extension -==================== - -|pypi| - -.. |pypi| image:: https://badge.fury.io/py/flask-dapr.svg - :target: https://pypi.org/project/flask-dapr/ - -This flask extension is used to: -- run the actor service -- subscribe to PubSub events - -Installation ------------- - -:: - - pip install flask-dapr - -PubSub Events -------------- - -.. code-block:: python - - from flask import Flask, request - from flask_dapr import DaprApp - - app = Flask('myapp') - dapr_app = DaprApp(app) - @dapr_app.subscribe(pubsub='pubsub', topic='some_topic', route='/some_endpoint') - def my_event_handler(): - # request.data contains pubsub event - pass - -References ----------- - -* `Dapr <https://github.com/dapr/dapr>`_ -* `Dapr Python-SDK <https://github.com/dapr/python-sdk>`_ diff --git a/ext/flask_dapr/pyproject.toml b/ext/flask_dapr/pyproject.toml deleted file mode 100644 index 66f86806c..000000000 --- a/ext/flask_dapr/pyproject.toml +++ /dev/null @@ -1,43 +0,0 @@ -[project] -name = "flask-dapr" -dynamic = ["version"] -description = "Dapr Flask Extension for the Dapr Python SDK." -readme = "README.rst" -requires-python = ">=3.10" -license = {text = "Apache-2.0"} -authors = [{name = "Dapr Authors", email = "dapr@dapr.io"}] -classifiers = [ - "Development Status :: 5 - Production/Stable", - "Intended Audience :: Developers", - "License :: OSI Approved :: Apache Software License", - "Operating System :: OS Independent", - "Programming Language :: Python", - "Programming Language :: Python :: 3.10", - "Programming Language :: Python :: 3.11", - "Programming Language :: Python :: 3.12", - "Programming Language :: Python :: 3.13", - "Programming Language :: Python :: 3.14", -] -dependencies = [ - "Flask>=1.1.4,<4.0.0", - "dapr", -] - -[project.urls] -Documentation = "https://github.com/dapr/docs" -Source = "https://github.com/dapr/python-sdk" - -[build-system] -requires = ["hatchling"] -build-backend = "hatchling.build" - -[tool.hatch.version] -source = "regex" -path = "../../VERSION" -pattern = '(?P<version>\S+)' - -[tool.hatch.build.targets.wheel] -only-include = ["flask_dapr"] - -[tool.uv.sources] -dapr = { workspace = true } diff --git a/flask_dapr/__init__.py b/flask_dapr/__init__.py new file mode 100644 index 000000000..f98b70382 --- /dev/null +++ b/flask_dapr/__init__.py @@ -0,0 +1,39 @@ +# -*- coding: utf-8 -*- + +""" +Copyright 2023 The Dapr Authors +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +""" + +# Deprecation shim for the pre-1.19 `flask_dapr` top-level import path. +# Use `dapr.ext.flask` instead. + +import sys +import warnings + +# Warn before importing so the migration hint reaches users even when the +# inner import fails (bare `pip install dapr` without the flask extra). +warnings.warn( + "Importing from 'flask_dapr' is deprecated; " + "use 'from dapr.ext.flask import DaprActor, DaprApp' instead. " + "The 'flask_dapr' top-level module will be removed in a future release.", + FutureWarning, + stacklevel=2, +) + +from dapr.ext.flask import DaprActor, DaprApp, actor, app # noqa: E402 + +# Register submodule aliases so `from flask_dapr.actor import DaprActor` and +# `import flask_dapr.app` resolve without on-disk files. +sys.modules['flask_dapr.actor'] = actor +sys.modules['flask_dapr.app'] = app + +__all__ = ['DaprActor', 'DaprApp'] diff --git a/dapr/__init__.pyi b/flask_dapr/py.typed similarity index 100% rename from dapr/__init__.pyi rename to flask_dapr/py.typed diff --git a/pyproject.toml b/pyproject.toml index 5e29cd9dd..f28afcc29 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -27,6 +27,35 @@ dependencies = [ "typing-extensions>=4.4.0,<5.0.0", ] +[project.optional-dependencies] +fastapi = [ + "fastapi>=0.60.1,<1.0.0", + "uvicorn>=0.11.6,<1.0.0", +] +flask = [ + "Flask>=1.1.4,<4.0.0", +] +grpc = [ + "cloudevents>=1.0.0,<2.0.0", +] +langgraph = [ + "langgraph>=0.3.6,<2.0.0", + "langchain>=0.1.17,<2.0.0", + "python-ulid>=3.0.0,<4.0.0", + "msgpack>=1.0,<2.0", +] +strands = [ + "strands-agents>=1.30.0,<2.0.0", + "strands-agents-tools>=0.2.22,<1.0.0", + "python-ulid>=3.0.0,<4.0.0", + "msgpack>=1.0,<2.0", +] +# workflow has no third-party runtime deps beyond core dapr. The empty extra +# exists so users get a consistent `pip install dapr[<ext>]` shape and so the +# extra is reserved if workflow ever grows external deps. +workflow = [] +all = ["dapr[fastapi,flask,grpc,langgraph,strands,workflow]"] + [project.urls] Documentation = "https://github.com/dapr/docs" Source = "https://github.com/dapr/python-sdk" @@ -41,20 +70,32 @@ path = "VERSION" pattern = '(?P<version>\S+)' [tool.hatch.build.targets.wheel] -packages = ["dapr"] +# IMPORTANT: do NOT introduce dapr/ext/__init__.py. `dapr.ext` is kept as an +# implicit PEP 420 namespace package so external plugins can publish their own +# distributions under `dapr.ext.*` without colliding with this wheel's +# `RECORD`. Materialising `dapr/ext/__init__.py` here would lock out every +# future externally-published dapr.ext.* plugin by claiming ownership of the +# namespace parent. +packages = ["dapr", "flask_dapr"] +# Repo-internal docs (contributor / AI-agent guidance) live next to the code +# for discoverability but should not ship in the published wheel. +exclude = [ + "**/AGENTS.md", + "dapr/ext/*/README.md", +] +# No workspace members. Before the bundling, each extension was a separate +# workspace package under ext/. Now all extension code lives in the core +# `dapr` package and is opt-in via [project.optional-dependencies]. [tool.uv.workspace] -members = [ - "ext/dapr-ext-workflow", - "ext/dapr-ext-grpc", - "ext/dapr-ext-fastapi", - "ext/dapr-ext-langgraph", - "ext/dapr-ext-strands", - "ext/flask_dapr", -] +members = [] [dependency-groups] dev = [ + # Pull in every extension's third-party deps so the full test suite runs + # in the dev env. `dapr` here resolves to this workspace project itself, + # so `dapr[all]` activates every extras list declared above. + "dapr[all]", "mypy==1.20.2", "mypy-extensions~=1.1.0", "mypy-protobuf==5.0.0", @@ -88,7 +129,12 @@ tests = [ target-version = "py310" line-length = 100 fix = true -extend-exclude = [".github", "dapr/proto", "ext/dapr-ext-workflow/dapr/ext/workflow/_durabletask/internal/*_pb2*"] +extend-exclude = [".github", "dapr/proto", "dapr/ext/workflow/_durabletask/internal/*_pb2*"] +# Honor extend-exclude even when ruff is invoked with explicit file paths +# (pre-commit hooks, lint-staged, manual debugging). Without this, ruff would +# happily lint and "fix" the generated `*_pb2.py` stubs and strip the +# `import attestation_pb2` lines that the protobuf descriptor pool needs. +force-exclude = true [tool.ruff.lint] select = [ @@ -131,6 +177,24 @@ ignore_errors = true module = ["grpc.aio"] ignore_missing_imports = true +[[tool.mypy.overrides]] +module = ["langgraph.*", "langchain.*", "strands.*", "strands_agents.*"] +ignore_missing_imports = true + +# Bundling the extensions into the core wheel brings their source under mypy's +# namespace walk for the first time. These modules carry pre-existing type +# errors that were previously hidden by the separate-workspace-package layout. +# Ignored here to keep this packaging PR scope-limited; clean up in a follow-up. +# TODO: drop these overrides as each module's type errors are fixed. +[[tool.mypy.overrides]] +module = [ + "dapr.ext.fastapi.*", + "dapr.ext.langgraph.*", + "dapr.ext.strands.*", + "dapr.ext.workflow.*", +] +ignore_errors = true + [tool.pytest.ini_options] markers = [ 'example_dir(name): set the example directory for the dapr fixture', diff --git a/tests/actor/test_actor_reentrancy.py b/tests/actor/test_actor_reentrancy.py index 263070f65..69f11160e 100644 --- a/tests/actor/test_actor_reentrancy.py +++ b/tests/actor/test_actor_reentrancy.py @@ -211,7 +211,7 @@ async def expected_return_value(*args, **kwargs): def test_parse_incoming_reentrancy_header_flask(self): from flask import Flask - from ext.flask_dapr import flask_dapr + from dapr.ext import flask as flask_dapr app = Flask(f'{FakeReentrantActor.__name__}Service') flask_dapr.DaprActor(app) @@ -242,10 +242,11 @@ def test_parse_incoming_reentrancy_header_flask(self): ) def test_parse_incoming_reentrancy_header_fastapi(self): - from dapr.ext import fastapi from fastapi import FastAPI from fastapi.testclient import TestClient + from dapr.ext import fastapi + app = FastAPI(title=f'{FakeReentrantActor.__name__}Service') fastapi.DaprActor(app) diff --git a/ext/dapr-ext-workflow/dapr/ext/workflow/_durabletask/aio/internal/__init__.py b/tests/ext/__init__.py similarity index 100% rename from ext/dapr-ext-workflow/dapr/ext/workflow/_durabletask/aio/internal/__init__.py rename to tests/ext/__init__.py diff --git a/ext/dapr-ext-workflow/dapr/ext/workflow/_durabletask/internal/__init__.py b/tests/ext/fastapi/__init__.py similarity index 100% rename from ext/dapr-ext-workflow/dapr/ext/workflow/_durabletask/internal/__init__.py rename to tests/ext/fastapi/__init__.py diff --git a/ext/dapr-ext-fastapi/tests/test_app.py b/tests/ext/fastapi/test_app.py similarity index 99% rename from ext/dapr-ext-fastapi/tests/test_app.py rename to tests/ext/fastapi/test_app.py index 619697994..831d55ebb 100644 --- a/ext/dapr-ext-fastapi/tests/test_app.py +++ b/tests/ext/fastapi/test_app.py @@ -1,10 +1,11 @@ import unittest -from dapr.ext.fastapi import DaprApp from fastapi import FastAPI from fastapi.testclient import TestClient from pydantic import BaseModel +from dapr.ext.fastapi import DaprApp + class Message(BaseModel): body: str diff --git a/ext/dapr-ext-fastapi/tests/test_dapractor.py b/tests/ext/fastapi/test_dapractor.py similarity index 99% rename from ext/dapr-ext-fastapi/tests/test_dapractor.py rename to tests/ext/fastapi/test_dapractor.py index 71408c88c..ee863d726 100644 --- a/ext/dapr-ext-fastapi/tests/test_dapractor.py +++ b/tests/ext/fastapi/test_dapractor.py @@ -16,9 +16,10 @@ import json import unittest -from dapr.ext.fastapi.actor import DaprActor, _wrap_response from fastapi import FastAPI +from dapr.ext.fastapi.actor import DaprActor, _wrap_response + class DaprActorTest(unittest.TestCase): def test_wrap_response_str(self): diff --git a/ext/dapr-ext-workflow/tests/durabletask/__init__.py b/tests/ext/flask/__init__.py similarity index 100% rename from ext/dapr-ext-workflow/tests/durabletask/__init__.py rename to tests/ext/flask/__init__.py diff --git a/ext/flask_dapr/tests/test_app.py b/tests/ext/flask/test_app.py similarity index 99% rename from ext/flask_dapr/tests/test_app.py rename to tests/ext/flask/test_app.py index 7ddfa14fe..4caa348d5 100644 --- a/ext/flask_dapr/tests/test_app.py +++ b/tests/ext/flask/test_app.py @@ -2,7 +2,8 @@ import unittest from flask import Flask -from flask_dapr import DaprApp + +from dapr.ext.flask import DaprApp class DaprAppTest(unittest.TestCase): diff --git a/tests/ext/flask/test_shim_deprecation.py b/tests/ext/flask/test_shim_deprecation.py new file mode 100644 index 000000000..b58789ebe --- /dev/null +++ b/tests/ext/flask/test_shim_deprecation.py @@ -0,0 +1,30 @@ +"""Locks the deprecation contract of the top-level `flask_dapr` shim. + +The shim re-exports `dapr.ext.flask` and must emit a `FutureWarning` on import, +not a `DeprecationWarning` (which Python's default filter would suppress for +non-`__main__` callers). +""" + +import sys + +import pytest + + +def _fresh_import(): + sys.modules.pop('flask_dapr', None) + import flask_dapr + + return flask_dapr + + +def test_emits_future_warning_on_import(): + with pytest.warns(FutureWarning, match=r'dapr\.ext\.flask'): + _fresh_import() + + +def test_reexports_public_surface(recwarn): + flask_dapr = _fresh_import() + from dapr.ext.flask import DaprActor, DaprApp + + assert flask_dapr.DaprActor is DaprActor + assert flask_dapr.DaprApp is DaprApp diff --git a/tests/ext/grpc/__init__.py b/tests/ext/grpc/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/ext/dapr-ext-grpc/tests/test_app.py b/tests/ext/grpc/test_app.py similarity index 100% rename from ext/dapr-ext-grpc/tests/test_app.py rename to tests/ext/grpc/test_app.py index 99ee0b37c..e25e6a273 100644 --- a/ext/dapr-ext-grpc/tests/test_app.py +++ b/tests/ext/grpc/test_app.py @@ -17,9 +17,9 @@ from unittest.mock import MagicMock, patch from cloudevents.sdk.event import v1 -from dapr.ext.grpc import App, BindingRequest, InvokeMethodRequest, Rule from dapr.conf import settings +from dapr.ext.grpc import App, BindingRequest, InvokeMethodRequest, Rule class AppTests(unittest.TestCase): diff --git a/ext/dapr-ext-grpc/tests/test_health_servicer.py b/tests/ext/grpc/test_health_servicer.py similarity index 100% rename from ext/dapr-ext-grpc/tests/test_health_servicer.py rename to tests/ext/grpc/test_health_servicer.py diff --git a/ext/dapr-ext-grpc/tests/test_servicier.py b/tests/ext/grpc/test_servicier.py similarity index 100% rename from ext/dapr-ext-grpc/tests/test_servicier.py rename to tests/ext/grpc/test_servicier.py index 1d362ea52..adafa6cbc 100644 --- a/ext/dapr-ext-grpc/tests/test_servicier.py +++ b/tests/ext/grpc/test_servicier.py @@ -16,11 +16,11 @@ import unittest from unittest.mock import MagicMock, Mock -from dapr.ext.grpc._servicer import _CallbackServicer from google.protobuf.any_pb2 import Any as GrpcAny from dapr.clients.grpc._request import InvokeMethodRequest from dapr.clients.grpc._response import InvokeMethodResponse, TopicEventResponse +from dapr.ext.grpc._servicer import _CallbackServicer from dapr.proto import appcallback_v1, common_v1 diff --git a/ext/dapr-ext-grpc/tests/test_topic_event_response.py b/tests/ext/grpc/test_topic_event_response.py similarity index 100% rename from ext/dapr-ext-grpc/tests/test_topic_event_response.py rename to tests/ext/grpc/test_topic_event_response.py diff --git a/ext/dapr-ext-langgraph/tests/__init__.py b/tests/ext/langgraph/__init__.py similarity index 100% rename from ext/dapr-ext-langgraph/tests/__init__.py rename to tests/ext/langgraph/__init__.py diff --git a/ext/dapr-ext-langgraph/tests/test_checkpointer.py b/tests/ext/langgraph/test_checkpointer.py similarity index 99% rename from ext/dapr-ext-langgraph/tests/test_checkpointer.py rename to tests/ext/langgraph/test_checkpointer.py index fc51d9182..9e518c1ae 100644 --- a/ext/dapr-ext-langgraph/tests/test_checkpointer.py +++ b/tests/ext/langgraph/test_checkpointer.py @@ -7,9 +7,10 @@ from unittest import mock import msgpack -from dapr.ext.langgraph.dapr_checkpointer import DaprCheckpointer from langgraph.checkpoint.base import Checkpoint +from dapr.ext.langgraph.dapr_checkpointer import DaprCheckpointer + @mock.patch('dapr.ext.langgraph.dapr_checkpointer.DaprClient') class DaprCheckpointerTest(unittest.TestCase): diff --git a/ext/dapr-ext-strands/tests/__init__.py b/tests/ext/strands/__init__.py similarity index 100% rename from ext/dapr-ext-strands/tests/__init__.py rename to tests/ext/strands/__init__.py diff --git a/ext/dapr-ext-strands/tests/test_session_manager.py b/tests/ext/strands/test_session_manager.py similarity index 99% rename from ext/dapr-ext-strands/tests/test_session_manager.py rename to tests/ext/strands/test_session_manager.py index 6f25edc55..3b4a34ec2 100644 --- a/ext/dapr-ext-strands/tests/test_session_manager.py +++ b/tests/ext/strands/test_session_manager.py @@ -18,10 +18,11 @@ import unittest from unittest import mock -from dapr.ext.strands.dapr_session_manager import DaprSessionManager from strands.types.exceptions import SessionException from strands.types.session import Session, SessionAgent, SessionMessage +from dapr.ext.strands.dapr_session_manager import DaprSessionManager + def dapr_state(data): """Simulate a real Dapr get_state() response.""" diff --git a/ext/dapr-ext-workflow/tests/__init__.py b/tests/ext/workflow/__init__.py similarity index 100% rename from ext/dapr-ext-workflow/tests/__init__.py rename to tests/ext/workflow/__init__.py diff --git a/tests/ext/workflow/durabletask/__init__.py b/tests/ext/workflow/durabletask/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/ext/dapr-ext-workflow/tests/durabletask/test_activity_executor.py b/tests/ext/workflow/durabletask/test_activity_executor.py similarity index 100% rename from ext/dapr-ext-workflow/tests/durabletask/test_activity_executor.py rename to tests/ext/workflow/durabletask/test_activity_executor.py diff --git a/ext/dapr-ext-workflow/tests/durabletask/test_client.py b/tests/ext/workflow/durabletask/test_client.py similarity index 100% rename from ext/dapr-ext-workflow/tests/durabletask/test_client.py rename to tests/ext/workflow/durabletask/test_client.py diff --git a/ext/dapr-ext-workflow/tests/durabletask/test_client_async.py b/tests/ext/workflow/durabletask/test_client_async.py similarity index 100% rename from ext/dapr-ext-workflow/tests/durabletask/test_client_async.py rename to tests/ext/workflow/durabletask/test_client_async.py diff --git a/ext/dapr-ext-workflow/tests/durabletask/test_concurrency_options.py b/tests/ext/workflow/durabletask/test_concurrency_options.py similarity index 100% rename from ext/dapr-ext-workflow/tests/durabletask/test_concurrency_options.py rename to tests/ext/workflow/durabletask/test_concurrency_options.py diff --git a/ext/dapr-ext-workflow/tests/durabletask/test_deterministic.py b/tests/ext/workflow/durabletask/test_deterministic.py similarity index 99% rename from ext/dapr-ext-workflow/tests/durabletask/test_deterministic.py rename to tests/ext/workflow/durabletask/test_deterministic.py index 4d2d27cba..f1d5e1e18 100644 --- a/ext/dapr-ext-workflow/tests/durabletask/test_deterministic.py +++ b/tests/ext/workflow/durabletask/test_deterministic.py @@ -16,6 +16,7 @@ from datetime import datetime, timezone import pytest + from dapr.ext.workflow._durabletask.deterministic import ( DeterminismSeed, derive_seed, diff --git a/ext/dapr-ext-workflow/tests/durabletask/test_orchestration_e2e.py b/tests/ext/workflow/durabletask/test_orchestration_e2e.py similarity index 99% rename from ext/dapr-ext-workflow/tests/durabletask/test_orchestration_e2e.py rename to tests/ext/workflow/durabletask/test_orchestration_e2e.py index c36bdc90b..9aac1c221 100644 --- a/ext/dapr-ext-workflow/tests/durabletask/test_orchestration_e2e.py +++ b/tests/ext/workflow/durabletask/test_orchestration_e2e.py @@ -16,6 +16,7 @@ from typing import Optional import pytest + from dapr.ext.workflow._durabletask import client, task, worker # NOTE: These tests assume a sidecar process is running. Example command: diff --git a/ext/dapr-ext-workflow/tests/durabletask/test_orchestration_e2e_async.py b/tests/ext/workflow/durabletask/test_orchestration_e2e_async.py similarity index 99% rename from ext/dapr-ext-workflow/tests/durabletask/test_orchestration_e2e_async.py rename to tests/ext/workflow/durabletask/test_orchestration_e2e_async.py index b155c7372..bbb2d45b1 100644 --- a/ext/dapr-ext-workflow/tests/durabletask/test_orchestration_e2e_async.py +++ b/tests/ext/workflow/durabletask/test_orchestration_e2e_async.py @@ -15,6 +15,7 @@ from datetime import timedelta import pytest + from dapr.ext.workflow._durabletask import task, worker from dapr.ext.workflow._durabletask.aio.client import AsyncTaskHubGrpcClient from dapr.ext.workflow._durabletask.client import OrchestrationStatus diff --git a/ext/dapr-ext-workflow/tests/durabletask/test_orchestration_executor.py b/tests/ext/workflow/durabletask/test_orchestration_executor.py similarity index 99% rename from ext/dapr-ext-workflow/tests/durabletask/test_orchestration_executor.py rename to tests/ext/workflow/durabletask/test_orchestration_executor.py index 953155027..fa9d570f4 100644 --- a/ext/dapr-ext-workflow/tests/durabletask/test_orchestration_executor.py +++ b/tests/ext/workflow/durabletask/test_orchestration_executor.py @@ -13,9 +13,10 @@ import logging from datetime import datetime, timedelta, timezone +import pytest + import dapr.ext.workflow._durabletask.internal.helpers as helpers import dapr.ext.workflow._durabletask.internal.protos as pb -import pytest from dapr.ext.workflow._durabletask import task, worker logging.basicConfig( diff --git a/ext/dapr-ext-workflow/tests/durabletask/test_orchestration_wait.py b/tests/ext/workflow/durabletask/test_orchestration_wait.py similarity index 99% rename from ext/dapr-ext-workflow/tests/durabletask/test_orchestration_wait.py rename to tests/ext/workflow/durabletask/test_orchestration_wait.py index f550cf4f9..2f4c9ba27 100644 --- a/ext/dapr-ext-workflow/tests/durabletask/test_orchestration_wait.py +++ b/tests/ext/workflow/durabletask/test_orchestration_wait.py @@ -1,6 +1,7 @@ from unittest.mock import Mock import pytest + from dapr.ext.workflow._durabletask.client import TaskHubGrpcClient diff --git a/ext/dapr-ext-workflow/tests/durabletask/test_propagation.py b/tests/ext/workflow/durabletask/test_propagation.py similarity index 99% rename from ext/dapr-ext-workflow/tests/durabletask/test_propagation.py rename to tests/ext/workflow/durabletask/test_propagation.py index 260ab1abb..73f5e83df 100644 --- a/ext/dapr-ext-workflow/tests/durabletask/test_propagation.py +++ b/tests/ext/workflow/durabletask/test_propagation.py @@ -17,14 +17,15 @@ from __future__ import annotations -import dapr.ext.workflow._durabletask.internal.protos as pb import pytest +from google.protobuf import wrappers_pb2 + +import dapr.ext.workflow._durabletask.internal.protos as pb from dapr.ext.workflow import ( PropagatedHistory, PropagationNotFoundError, PropagationScope, ) -from google.protobuf import wrappers_pb2 # --- Test history fixtures --------------------------------------------------- diff --git a/ext/dapr-ext-workflow/tests/durabletask/test_propagation_wiring.py b/tests/ext/workflow/durabletask/test_propagation_wiring.py similarity index 100% rename from ext/dapr-ext-workflow/tests/durabletask/test_propagation_wiring.py rename to tests/ext/workflow/durabletask/test_propagation_wiring.py diff --git a/ext/dapr-ext-workflow/tests/durabletask/test_registry.py b/tests/ext/workflow/durabletask/test_registry.py similarity index 99% rename from ext/dapr-ext-workflow/tests/durabletask/test_registry.py rename to tests/ext/workflow/durabletask/test_registry.py index eee83388f..534dbf355 100644 --- a/ext/dapr-ext-workflow/tests/durabletask/test_registry.py +++ b/tests/ext/workflow/durabletask/test_registry.py @@ -12,6 +12,7 @@ """Unit tests for the _Registry class validation logic.""" import pytest + from dapr.ext.workflow._durabletask import worker diff --git a/ext/dapr-ext-workflow/tests/durabletask/test_serialization.py b/tests/ext/workflow/durabletask/test_serialization.py similarity index 99% rename from ext/dapr-ext-workflow/tests/durabletask/test_serialization.py rename to tests/ext/workflow/durabletask/test_serialization.py index 2b9a79dfb..127c5db4c 100644 --- a/ext/dapr-ext-workflow/tests/durabletask/test_serialization.py +++ b/tests/ext/workflow/durabletask/test_serialization.py @@ -15,9 +15,10 @@ from dataclasses import dataclass from types import SimpleNamespace -from dapr.ext.workflow._durabletask.internal.shared import AUTO_SERIALIZED, from_json, to_json from pydantic import BaseModel +from dapr.ext.workflow._durabletask.internal.shared import AUTO_SERIALIZED, from_json, to_json + @dataclass class SamplePayload: diff --git a/ext/dapr-ext-workflow/tests/durabletask/test_task.py b/tests/ext/workflow/durabletask/test_task.py similarity index 99% rename from ext/dapr-ext-workflow/tests/durabletask/test_task.py rename to tests/ext/workflow/durabletask/test_task.py index a381ab3d1..aeb2d2b3b 100644 --- a/ext/dapr-ext-workflow/tests/durabletask/test_task.py +++ b/tests/ext/workflow/durabletask/test_task.py @@ -11,8 +11,9 @@ """Unit tests for durabletask.task primitives.""" -import dapr.ext.workflow._durabletask.internal.helpers as pbh import pytest + +import dapr.ext.workflow._durabletask.internal.helpers as pbh from dapr.ext.workflow._durabletask import task diff --git a/ext/dapr-ext-workflow/tests/durabletask/test_worker_concurrency_loop.py b/tests/ext/workflow/durabletask/test_worker_concurrency_loop.py similarity index 100% rename from ext/dapr-ext-workflow/tests/durabletask/test_worker_concurrency_loop.py rename to tests/ext/workflow/durabletask/test_worker_concurrency_loop.py diff --git a/ext/dapr-ext-workflow/tests/durabletask/test_worker_concurrency_loop_async.py b/tests/ext/workflow/durabletask/test_worker_concurrency_loop_async.py similarity index 100% rename from ext/dapr-ext-workflow/tests/durabletask/test_worker_concurrency_loop_async.py rename to tests/ext/workflow/durabletask/test_worker_concurrency_loop_async.py diff --git a/ext/dapr-ext-workflow/tests/durabletask/test_worker_stop.py b/tests/ext/workflow/durabletask/test_worker_stop.py similarity index 99% rename from ext/dapr-ext-workflow/tests/durabletask/test_worker_stop.py rename to tests/ext/workflow/durabletask/test_worker_stop.py index 0fef6ab8f..009505c13 100644 --- a/ext/dapr-ext-workflow/tests/durabletask/test_worker_stop.py +++ b/tests/ext/workflow/durabletask/test_worker_stop.py @@ -5,6 +5,7 @@ import grpc import pytest + from dapr.ext.workflow._durabletask.worker import TaskHubGrpcWorker diff --git a/ext/dapr-ext-workflow/tests/test_dapr_workflow_context.py b/tests/ext/workflow/test_dapr_workflow_context.py similarity index 100% rename from ext/dapr-ext-workflow/tests/test_dapr_workflow_context.py rename to tests/ext/workflow/test_dapr_workflow_context.py diff --git a/ext/dapr-ext-workflow/tests/test_mcp_client.py b/tests/ext/workflow/test_mcp_client.py similarity index 100% rename from ext/dapr-ext-workflow/tests/test_mcp_client.py rename to tests/ext/workflow/test_mcp_client.py diff --git a/ext/dapr-ext-workflow/tests/test_mcp_schema.py b/tests/ext/workflow/test_mcp_schema.py similarity index 99% rename from ext/dapr-ext-workflow/tests/test_mcp_schema.py rename to tests/ext/workflow/test_mcp_schema.py index 642d5b16f..6f369b712 100644 --- a/ext/dapr-ext-workflow/tests/test_mcp_schema.py +++ b/tests/ext/workflow/test_mcp_schema.py @@ -15,9 +15,10 @@ import unittest -from dapr.ext.workflow.mcp_schema import create_pydantic_model_from_schema from pydantic import BaseModel +from dapr.ext.workflow.mcp_schema import create_pydantic_model_from_schema + class TestBasicTypes(unittest.TestCase): """Tests for basic JSON Schema type conversions.""" diff --git a/ext/dapr-ext-workflow/tests/test_model_protocol.py b/tests/ext/workflow/test_model_protocol.py similarity index 99% rename from ext/dapr-ext-workflow/tests/test_model_protocol.py rename to tests/ext/workflow/test_model_protocol.py index bcfa6b1d6..78a3c2cb2 100644 --- a/ext/dapr-ext-workflow/tests/test_model_protocol.py +++ b/tests/ext/workflow/test_model_protocol.py @@ -17,9 +17,10 @@ from types import SimpleNamespace from typing import Optional -from dapr.ext.workflow import _model_protocol from pydantic import BaseModel, ValidationError +from dapr.ext.workflow import _model_protocol + class Order(BaseModel): order_id: str diff --git a/ext/dapr-ext-workflow/tests/test_workflow_activity_context.py b/tests/ext/workflow/test_workflow_activity_context.py similarity index 100% rename from ext/dapr-ext-workflow/tests/test_workflow_activity_context.py rename to tests/ext/workflow/test_workflow_activity_context.py diff --git a/ext/dapr-ext-workflow/tests/test_workflow_client.py b/tests/ext/workflow/test_workflow_client.py similarity index 99% rename from ext/dapr-ext-workflow/tests/test_workflow_client.py rename to tests/ext/workflow/test_workflow_client.py index 88e227373..0267fca3b 100644 --- a/ext/dapr-ext-workflow/tests/test_workflow_client.py +++ b/tests/ext/workflow/test_workflow_client.py @@ -18,10 +18,11 @@ from typing import Any, Union from unittest import mock +from grpc import RpcError + from dapr.ext.workflow._durabletask import client from dapr.ext.workflow.dapr_workflow_client import DaprWorkflowClient from dapr.ext.workflow.dapr_workflow_context import DaprWorkflowContext -from grpc import RpcError mock_schedule_result = 'workflow001' mock_raise_event_result = 'event001' diff --git a/ext/dapr-ext-workflow/tests/test_workflow_client_aio.py b/tests/ext/workflow/test_workflow_client_aio.py similarity index 99% rename from ext/dapr-ext-workflow/tests/test_workflow_client_aio.py rename to tests/ext/workflow/test_workflow_client_aio.py index 729231e8d..27897976f 100644 --- a/ext/dapr-ext-workflow/tests/test_workflow_client_aio.py +++ b/tests/ext/workflow/test_workflow_client_aio.py @@ -18,10 +18,11 @@ from typing import Any, Union from unittest import mock +from grpc.aio import AioRpcError + from dapr.ext.workflow._durabletask import client from dapr.ext.workflow.aio import DaprWorkflowClient from dapr.ext.workflow.dapr_workflow_context import DaprWorkflowContext -from grpc.aio import AioRpcError mock_schedule_result = 'workflow001' mock_raise_event_result = 'event001' diff --git a/ext/dapr-ext-workflow/tests/test_workflow_runtime.py b/tests/ext/workflow/test_workflow_runtime.py similarity index 99% rename from ext/dapr-ext-workflow/tests/test_workflow_runtime.py rename to tests/ext/workflow/test_workflow_runtime.py index 32331a263..b3558e8f8 100644 --- a/ext/dapr-ext-workflow/tests/test_workflow_runtime.py +++ b/tests/ext/workflow/test_workflow_runtime.py @@ -18,10 +18,11 @@ from unittest import mock import grpc +from pydantic import BaseModel, ValidationError + from dapr.ext.workflow.dapr_workflow_context import DaprWorkflowContext from dapr.ext.workflow.workflow_activity_context import WorkflowActivityContext from dapr.ext.workflow.workflow_runtime import WorkflowRuntime, alternate_name -from pydantic import BaseModel, ValidationError class Order(BaseModel): diff --git a/ext/dapr-ext-workflow/tests/test_workflow_util.py b/tests/ext/workflow/test_workflow_util.py similarity index 99% rename from ext/dapr-ext-workflow/tests/test_workflow_util.py rename to tests/ext/workflow/test_workflow_util.py index 28e92e6c5..476126858 100644 --- a/ext/dapr-ext-workflow/tests/test_workflow_util.py +++ b/tests/ext/workflow/test_workflow_util.py @@ -1,9 +1,8 @@ import unittest from unittest.mock import patch -from dapr.ext.workflow.util import getAddress - from dapr.conf import settings +from dapr.ext.workflow.util import getAddress class DaprWorkflowUtilTest(unittest.TestCase): diff --git a/tests/integration/AGENTS.md b/tests/integration/AGENTS.md index ecf417582..997ca9277 100644 --- a/tests/integration/AGENTS.md +++ b/tests/integration/AGENTS.md @@ -89,7 +89,7 @@ Each test file defines its own module-scoped fixture (`client` or `sidecar`) tha | `test_crypto.py` | Cryptography | `encrypt`, `decrypt` (RSA + AES round-trips against `crypto.dapr.localstorage`) | | `test_conversation.py` | Conversation | `converse_alpha1`, `converse_alpha2` against `conversation.echo` | | `test_conversation_ollama.py` | Conversation (real LLM) | `converse_alpha1`, `converse_alpha2` against `conversation.ollama`; skips if `ollama` CLI is missing | -| `test_workflow.py` | Workflow (`dapr-ext-workflow`) | `WorkflowRuntime`, `DaprWorkflowClient.schedule_new_workflow`, `wait_for_workflow_start`, `wait_for_workflow_completion`, `raise_workflow_event`, `pause_workflow`, `resume_workflow`, `terminate_workflow`, `purge_workflow`, `get_workflow_state` | +| `test_workflow.py` | Workflow (`dapr.ext.workflow`) | `WorkflowRuntime`, `DaprWorkflowClient.schedule_new_workflow`, `wait_for_workflow_start`, `wait_for_workflow_completion`, `raise_workflow_event`, `pause_workflow`, `resume_workflow`, `terminate_workflow`, `purge_workflow`, `get_workflow_state` | ### Async client coverage diff --git a/tests/integration/apps/pubsub_subscriber.py b/tests/integration/apps/pubsub_subscriber.py index 110fa14c8..4e89bfb74 100644 --- a/tests/integration/apps/pubsub_subscriber.py +++ b/tests/integration/apps/pubsub_subscriber.py @@ -6,10 +6,10 @@ import json from cloudevents.sdk.event import v1 -from dapr.ext.grpc import App from dapr.clients import DaprClient from dapr.clients.grpc._response import TopicEventResponse +from dapr.ext.grpc import App app = App() diff --git a/tools/regen_durabletask_protos.sh b/tools/regen_durabletask_protos.sh index 17d57471c..4b9120f11 100755 --- a/tools/regen_durabletask_protos.sh +++ b/tools/regen_durabletask_protos.sh @@ -16,9 +16,9 @@ # Regenerate Python protobuf/gRPC stubs for the vendored durabletask package. # # Proto source files are fetched from the durabletask-protobuf repository. -# Generated output goes to ext/dapr-ext-workflow/dapr/ext/workflow/_durabletask/internal/ +# Generated output goes to dapr/ext/workflow/_durabletask/internal/ # -# Prerequisites: uv sync --all-packages --group dev +# Prerequisites: uv sync --all-extras --group dev # # Usage: # ./tools/regen_durabletask_protos.sh @@ -28,7 +28,7 @@ set -euo pipefail DURABLETASK_PROTOBUF_BRANCH=${DURABLETASK_PROTOBUF_BRANCH:-main} REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)" -OUTPUT_DIR="${REPO_ROOT}/ext/dapr-ext-workflow/dapr/ext/workflow/_durabletask/internal" +OUTPUT_DIR="${REPO_ROOT}/dapr/ext/workflow/_durabletask/internal" PYTHON_PACKAGE="dapr.ext.workflow._durabletask.internal" if type "curl" > /dev/null 2>&1; then diff --git a/uv.lock b/uv.lock index 00fe24e7c..8493f8cae 100644 --- a/uv.lock +++ b/uv.lock @@ -6,17 +6,6 @@ resolution-markers = [ "python_full_version < '3.15'", ] -[manifest] -members = [ - "dapr", - "dapr-ext-fastapi", - "dapr-ext-grpc", - "dapr-ext-langgraph", - "dapr-ext-strands", - "dapr-ext-workflow", - "flask-dapr", -] - [[package]] name = "aiohappyeyeballs" version = "2.6.1" @@ -678,10 +667,47 @@ dependencies = [ { name = "typing-extensions" }, ] +[package.optional-dependencies] +all = [ + { name = "cloudevents" }, + { name = "fastapi" }, + { name = "flask" }, + { name = "langchain" }, + { name = "langgraph" }, + { name = "msgpack" }, + { name = "python-ulid" }, + { name = "strands-agents" }, + { name = "strands-agents-tools" }, + { name = "uvicorn" }, +] +fastapi = [ + { name = "fastapi" }, + { name = "uvicorn" }, +] +flask = [ + { name = "flask" }, +] +grpc = [ + { name = "cloudevents" }, +] +langgraph = [ + { name = "langchain" }, + { name = "langgraph" }, + { name = "msgpack" }, + { name = "python-ulid" }, +] +strands = [ + { name = "msgpack" }, + { name = "python-ulid" }, + { name = "strands-agents" }, + { name = "strands-agents-tools" }, +] + [package.dev-dependencies] dev = [ { name = "coverage" }, { name = "cryptography" }, + { name = "dapr", extra = ["all"] }, { name = "flask" }, { name = "grpcio-tools" }, { name = "httpx" }, @@ -706,6 +732,7 @@ dev = [ tests = [ { name = "coverage" }, { name = "cryptography" }, + { name = "dapr", extra = ["all"] }, { name = "flask" }, { name = "grpcio-tools" }, { name = "httpx" }, @@ -733,17 +760,41 @@ tests = [ [package.metadata] requires-dist = [ { name = "aiohttp", specifier = ">=3.9.5,<4.0.0" }, + { name = "cloudevents", marker = "extra == 'all'", specifier = ">=1.0.0,<2.0.0" }, + { name = "cloudevents", marker = "extra == 'grpc'", specifier = ">=1.0.0,<2.0.0" }, + { name = "fastapi", marker = "extra == 'all'", specifier = ">=0.60.1,<1.0.0" }, + { name = "fastapi", marker = "extra == 'fastapi'", specifier = ">=0.60.1,<1.0.0" }, + { name = "flask", marker = "extra == 'all'", specifier = ">=1.1.4,<4.0.0" }, + { name = "flask", marker = "extra == 'flask'", specifier = ">=1.1.4,<4.0.0" }, { name = "grpcio", specifier = ">=1.76.0,<2.0.0" }, { name = "grpcio-status", specifier = ">=1.76.0,<2.0.0" }, + { name = "langchain", marker = "extra == 'all'", specifier = ">=0.1.17,<2.0.0" }, + { name = "langchain", marker = "extra == 'langgraph'", specifier = ">=0.1.17,<2.0.0" }, + { name = "langgraph", marker = "extra == 'all'", specifier = ">=0.3.6,<2.0.0" }, + { name = "langgraph", marker = "extra == 'langgraph'", specifier = ">=0.3.6,<2.0.0" }, + { name = "msgpack", marker = "extra == 'all'", specifier = ">=1.0,<2.0" }, + { name = "msgpack", marker = "extra == 'langgraph'", specifier = ">=1.0,<2.0" }, + { name = "msgpack", marker = "extra == 'strands'", specifier = ">=1.0,<2.0" }, { name = "protobuf", specifier = ">=4.22.5,<8.0.0" }, { name = "python-dateutil", specifier = ">=2.8.1,<3.0.0" }, + { name = "python-ulid", marker = "extra == 'all'", specifier = ">=3.0.0,<4.0.0" }, + { name = "python-ulid", marker = "extra == 'langgraph'", specifier = ">=3.0.0,<4.0.0" }, + { name = "python-ulid", marker = "extra == 'strands'", specifier = ">=3.0.0,<4.0.0" }, + { name = "strands-agents", marker = "extra == 'all'", specifier = ">=1.30.0,<2.0.0" }, + { name = "strands-agents", marker = "extra == 'strands'", specifier = ">=1.30.0,<2.0.0" }, + { name = "strands-agents-tools", marker = "extra == 'all'", specifier = ">=0.2.22,<1.0.0" }, + { name = "strands-agents-tools", marker = "extra == 'strands'", specifier = ">=0.2.22,<1.0.0" }, { name = "typing-extensions", specifier = ">=4.4.0,<5.0.0" }, + { name = "uvicorn", marker = "extra == 'all'", specifier = ">=0.11.6,<1.0.0" }, + { name = "uvicorn", marker = "extra == 'fastapi'", specifier = ">=0.11.6,<1.0.0" }, ] +provides-extras = ["all", "fastapi", "flask", "grpc", "langgraph", "strands", "workflow"] [package.metadata.requires-dev] dev = [ { name = "coverage", specifier = "~=7.13.4" }, { name = "cryptography", specifier = ">=42.0.0" }, + { name = "dapr", extras = ["all"] }, { name = "flask", specifier = "~=3.1.3" }, { name = "grpcio-tools", specifier = "==1.76.0" }, { name = "httpx", specifier = "~=0.28.1" }, @@ -768,6 +819,7 @@ dev = [ tests = [ { name = "coverage", specifier = "~=7.13.4" }, { name = "cryptography", specifier = ">=42.0.0" }, + { name = "dapr", extras = ["all"] }, { name = "flask", specifier = "~=3.1.3" }, { name = "grpcio-tools", specifier = "==1.76.0" }, { name = "httpx", specifier = "~=0.28.1" }, @@ -792,86 +844,6 @@ tests = [ { name = "wheel", specifier = "~=0.46.3" }, ] -[[package]] -name = "dapr-ext-fastapi" -source = { editable = "ext/dapr-ext-fastapi" } -dependencies = [ - { name = "dapr" }, - { name = "fastapi" }, - { name = "uvicorn" }, -] - -[package.metadata] -requires-dist = [ - { name = "dapr", editable = "." }, - { name = "fastapi", specifier = ">=0.60.1,<1.0.0" }, - { name = "uvicorn", specifier = ">=0.11.6,<1.0.0" }, -] - -[[package]] -name = "dapr-ext-grpc" -source = { editable = "ext/dapr-ext-grpc" } -dependencies = [ - { name = "cloudevents" }, - { name = "dapr" }, -] - -[package.metadata] -requires-dist = [ - { name = "cloudevents", specifier = ">=1.0.0,<2.0.0" }, - { name = "dapr", editable = "." }, -] - -[[package]] -name = "dapr-ext-langgraph" -source = { editable = "ext/dapr-ext-langgraph" } -dependencies = [ - { name = "dapr" }, - { name = "langchain" }, - { name = "langgraph" }, - { name = "msgpack-python" }, - { name = "python-ulid" }, -] - -[package.metadata] -requires-dist = [ - { name = "dapr", editable = "." }, - { name = "langchain", specifier = ">=0.1.17,<2.0.0" }, - { name = "langgraph", specifier = ">=0.3.6,<2.0.0" }, - { name = "msgpack-python", specifier = ">=0.4.5,<1.0.0" }, - { name = "python-ulid", specifier = ">=3.0.0,<4.0.0" }, -] - -[[package]] -name = "dapr-ext-strands" -source = { editable = "ext/dapr-ext-strands" } -dependencies = [ - { name = "dapr" }, - { name = "msgpack-python" }, - { name = "python-ulid" }, - { name = "strands-agents" }, - { name = "strands-agents-tools" }, -] - -[package.metadata] -requires-dist = [ - { name = "dapr", editable = "." }, - { name = "msgpack-python", specifier = ">=0.4.5,<1.0.0" }, - { name = "python-ulid", specifier = ">=3.0.0,<4.0.0" }, - { name = "strands-agents", specifier = ">=1.30.0,<2.0.0" }, - { name = "strands-agents-tools", specifier = ">=0.2.22,<1.0.0" }, -] - -[[package]] -name = "dapr-ext-workflow" -source = { editable = "ext/dapr-ext-workflow" } -dependencies = [ - { name = "dapr" }, -] - -[package.metadata] -requires-dist = [{ name = "dapr", editable = "." }] - [[package]] name = "deprecation" version = "2.1.0" @@ -947,20 +919,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/7f/9c/34f6962f9b9e9c71f6e5ed806e0d0ff03c9d1b0b2340088a0cf4bce09b18/flask-3.1.3-py3-none-any.whl", hash = "sha256:f4bcbefc124291925f1a26446da31a5178f9483862233b23c0c96a20701f670c", size = 103424, upload-time = "2026-02-19T05:00:56.027Z" }, ] -[[package]] -name = "flask-dapr" -source = { editable = "ext/flask_dapr" } -dependencies = [ - { name = "dapr" }, - { name = "flask" }, -] - -[package.metadata] -requires-dist = [ - { name = "dapr", editable = "." }, - { name = "flask", specifier = ">=1.1.4,<4.0.0" }, -] - [[package]] name = "frozenlist" version = "1.8.0" @@ -1788,10 +1746,65 @@ wheels = [ ] [[package]] -name = "msgpack-python" -version = "0.5.6" +name = "msgpack" +version = "1.1.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/8a/20/6eca772d1a5830336f84aca1d8198e5a3f4715cd1c7fc36d3cc7f7185091/msgpack-python-0.5.6.tar.gz", hash = "sha256:378cc8a6d3545b532dfd149da715abae4fda2a3adb6d74e525d0d5e51f46909b", size = 138996, upload-time = "2018-03-10T09:22:56.493Z" } +sdist = { url = "https://files.pythonhosted.org/packages/4d/f2/bfb55a6236ed8725a96b0aa3acbd0ec17588e6a2c3b62a93eb513ed8783f/msgpack-1.1.2.tar.gz", hash = "sha256:3b60763c1373dd60f398488069bcdc703cd08a711477b5d480eecc9f9626f47e", size = 173581, upload-time = "2025-10-08T09:15:56.596Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f5/a2/3b68a9e769db68668b25c6108444a35f9bd163bb848c0650d516761a59c0/msgpack-1.1.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0051fffef5a37ca2cd16978ae4f0aef92f164df86823871b5162812bebecd8e2", size = 81318, upload-time = "2025-10-08T09:14:38.722Z" }, + { url = "https://files.pythonhosted.org/packages/5b/e1/2b720cc341325c00be44e1ed59e7cfeae2678329fbf5aa68f5bda57fe728/msgpack-1.1.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a605409040f2da88676e9c9e5853b3449ba8011973616189ea5ee55ddbc5bc87", size = 83786, upload-time = "2025-10-08T09:14:40.082Z" }, + { url = "https://files.pythonhosted.org/packages/71/e5/c2241de64bfceac456b140737812a2ab310b10538a7b34a1d393b748e095/msgpack-1.1.2-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8b696e83c9f1532b4af884045ba7f3aa741a63b2bc22617293a2c6a7c645f251", size = 398240, upload-time = "2025-10-08T09:14:41.151Z" }, + { url = "https://files.pythonhosted.org/packages/b7/09/2a06956383c0fdebaef5aa9246e2356776f12ea6f2a44bd1368abf0e46c4/msgpack-1.1.2-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:365c0bbe981a27d8932da71af63ef86acc59ed5c01ad929e09a0b88c6294e28a", size = 406070, upload-time = "2025-10-08T09:14:42.821Z" }, + { url = "https://files.pythonhosted.org/packages/0e/74/2957703f0e1ef20637d6aead4fbb314330c26f39aa046b348c7edcf6ca6b/msgpack-1.1.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:41d1a5d875680166d3ac5c38573896453bbbea7092936d2e107214daf43b1d4f", size = 393403, upload-time = "2025-10-08T09:14:44.38Z" }, + { url = "https://files.pythonhosted.org/packages/a5/09/3bfc12aa90f77b37322fc33e7a8a7c29ba7c8edeadfa27664451801b9860/msgpack-1.1.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:354e81bcdebaab427c3df4281187edc765d5d76bfb3a7c125af9da7a27e8458f", size = 398947, upload-time = "2025-10-08T09:14:45.56Z" }, + { url = "https://files.pythonhosted.org/packages/4b/4f/05fcebd3b4977cb3d840f7ef6b77c51f8582086de5e642f3fefee35c86fc/msgpack-1.1.2-cp310-cp310-win32.whl", hash = "sha256:e64c8d2f5e5d5fda7b842f55dec6133260ea8f53c4257d64494c534f306bf7a9", size = 64769, upload-time = "2025-10-08T09:14:47.334Z" }, + { url = "https://files.pythonhosted.org/packages/d0/3e/b4547e3a34210956382eed1c85935fff7e0f9b98be3106b3745d7dec9c5e/msgpack-1.1.2-cp310-cp310-win_amd64.whl", hash = "sha256:db6192777d943bdaaafb6ba66d44bf65aa0e9c5616fa1d2da9bb08828c6b39aa", size = 71293, upload-time = "2025-10-08T09:14:48.665Z" }, + { url = "https://files.pythonhosted.org/packages/2c/97/560d11202bcd537abca693fd85d81cebe2107ba17301de42b01ac1677b69/msgpack-1.1.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2e86a607e558d22985d856948c12a3fa7b42efad264dca8a3ebbcfa2735d786c", size = 82271, upload-time = "2025-10-08T09:14:49.967Z" }, + { url = "https://files.pythonhosted.org/packages/83/04/28a41024ccbd67467380b6fb440ae916c1e4f25e2cd4c63abe6835ac566e/msgpack-1.1.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:283ae72fc89da59aa004ba147e8fc2f766647b1251500182fac0350d8af299c0", size = 84914, upload-time = "2025-10-08T09:14:50.958Z" }, + { url = "https://files.pythonhosted.org/packages/71/46/b817349db6886d79e57a966346cf0902a426375aadc1e8e7a86a75e22f19/msgpack-1.1.2-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:61c8aa3bd513d87c72ed0b37b53dd5c5a0f58f2ff9f26e1555d3bd7948fb7296", size = 416962, upload-time = "2025-10-08T09:14:51.997Z" }, + { url = "https://files.pythonhosted.org/packages/da/e0/6cc2e852837cd6086fe7d8406af4294e66827a60a4cf60b86575a4a65ca8/msgpack-1.1.2-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:454e29e186285d2ebe65be34629fa0e8605202c60fbc7c4c650ccd41870896ef", size = 426183, upload-time = "2025-10-08T09:14:53.477Z" }, + { url = "https://files.pythonhosted.org/packages/25/98/6a19f030b3d2ea906696cedd1eb251708e50a5891d0978b012cb6107234c/msgpack-1.1.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:7bc8813f88417599564fafa59fd6f95be417179f76b40325b500b3c98409757c", size = 411454, upload-time = "2025-10-08T09:14:54.648Z" }, + { url = "https://files.pythonhosted.org/packages/b7/cd/9098fcb6adb32187a70b7ecaabf6339da50553351558f37600e53a4a2a23/msgpack-1.1.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:bafca952dc13907bdfdedfc6a5f579bf4f292bdd506fadb38389afa3ac5b208e", size = 422341, upload-time = "2025-10-08T09:14:56.328Z" }, + { url = "https://files.pythonhosted.org/packages/e6/ae/270cecbcf36c1dc85ec086b33a51a4d7d08fc4f404bdbc15b582255d05ff/msgpack-1.1.2-cp311-cp311-win32.whl", hash = "sha256:602b6740e95ffc55bfb078172d279de3773d7b7db1f703b2f1323566b878b90e", size = 64747, upload-time = "2025-10-08T09:14:57.882Z" }, + { url = "https://files.pythonhosted.org/packages/2a/79/309d0e637f6f37e83c711f547308b91af02b72d2326ddd860b966080ef29/msgpack-1.1.2-cp311-cp311-win_amd64.whl", hash = "sha256:d198d275222dc54244bf3327eb8cbe00307d220241d9cec4d306d49a44e85f68", size = 71633, upload-time = "2025-10-08T09:14:59.177Z" }, + { url = "https://files.pythonhosted.org/packages/73/4d/7c4e2b3d9b1106cd0aa6cb56cc57c6267f59fa8bfab7d91df5adc802c847/msgpack-1.1.2-cp311-cp311-win_arm64.whl", hash = "sha256:86f8136dfa5c116365a8a651a7d7484b65b13339731dd6faebb9a0242151c406", size = 64755, upload-time = "2025-10-08T09:15:00.48Z" }, + { url = "https://files.pythonhosted.org/packages/ad/bd/8b0d01c756203fbab65d265859749860682ccd2a59594609aeec3a144efa/msgpack-1.1.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:70a0dff9d1f8da25179ffcf880e10cf1aad55fdb63cd59c9a49a1b82290062aa", size = 81939, upload-time = "2025-10-08T09:15:01.472Z" }, + { url = "https://files.pythonhosted.org/packages/34/68/ba4f155f793a74c1483d4bdef136e1023f7bcba557f0db4ef3db3c665cf1/msgpack-1.1.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:446abdd8b94b55c800ac34b102dffd2f6aa0ce643c55dfc017ad89347db3dbdb", size = 85064, upload-time = "2025-10-08T09:15:03.764Z" }, + { url = "https://files.pythonhosted.org/packages/f2/60/a064b0345fc36c4c3d2c743c82d9100c40388d77f0b48b2f04d6041dbec1/msgpack-1.1.2-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c63eea553c69ab05b6747901b97d620bb2a690633c77f23feb0c6a947a8a7b8f", size = 417131, upload-time = "2025-10-08T09:15:05.136Z" }, + { url = "https://files.pythonhosted.org/packages/65/92/a5100f7185a800a5d29f8d14041f61475b9de465ffcc0f3b9fba606e4505/msgpack-1.1.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:372839311ccf6bdaf39b00b61288e0557916c3729529b301c52c2d88842add42", size = 427556, upload-time = "2025-10-08T09:15:06.837Z" }, + { url = "https://files.pythonhosted.org/packages/f5/87/ffe21d1bf7d9991354ad93949286f643b2bb6ddbeab66373922b44c3b8cc/msgpack-1.1.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2929af52106ca73fcb28576218476ffbb531a036c2adbcf54a3664de124303e9", size = 404920, upload-time = "2025-10-08T09:15:08.179Z" }, + { url = "https://files.pythonhosted.org/packages/ff/41/8543ed2b8604f7c0d89ce066f42007faac1eaa7d79a81555f206a5cdb889/msgpack-1.1.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:be52a8fc79e45b0364210eef5234a7cf8d330836d0a64dfbb878efa903d84620", size = 415013, upload-time = "2025-10-08T09:15:09.83Z" }, + { url = "https://files.pythonhosted.org/packages/41/0d/2ddfaa8b7e1cee6c490d46cb0a39742b19e2481600a7a0e96537e9c22f43/msgpack-1.1.2-cp312-cp312-win32.whl", hash = "sha256:1fff3d825d7859ac888b0fbda39a42d59193543920eda9d9bea44d958a878029", size = 65096, upload-time = "2025-10-08T09:15:11.11Z" }, + { url = "https://files.pythonhosted.org/packages/8c/ec/d431eb7941fb55a31dd6ca3404d41fbb52d99172df2e7707754488390910/msgpack-1.1.2-cp312-cp312-win_amd64.whl", hash = "sha256:1de460f0403172cff81169a30b9a92b260cb809c4cb7e2fc79ae8d0510c78b6b", size = 72708, upload-time = "2025-10-08T09:15:12.554Z" }, + { url = "https://files.pythonhosted.org/packages/c5/31/5b1a1f70eb0e87d1678e9624908f86317787b536060641d6798e3cf70ace/msgpack-1.1.2-cp312-cp312-win_arm64.whl", hash = "sha256:be5980f3ee0e6bd44f3a9e9dea01054f175b50c3e6cdb692bc9424c0bbb8bf69", size = 64119, upload-time = "2025-10-08T09:15:13.589Z" }, + { url = "https://files.pythonhosted.org/packages/6b/31/b46518ecc604d7edf3a4f94cb3bf021fc62aa301f0cb849936968164ef23/msgpack-1.1.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:4efd7b5979ccb539c221a4c4e16aac1a533efc97f3b759bb5a5ac9f6d10383bf", size = 81212, upload-time = "2025-10-08T09:15:14.552Z" }, + { url = "https://files.pythonhosted.org/packages/92/dc/c385f38f2c2433333345a82926c6bfa5ecfff3ef787201614317b58dd8be/msgpack-1.1.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:42eefe2c3e2af97ed470eec850facbe1b5ad1d6eacdbadc42ec98e7dcf68b4b7", size = 84315, upload-time = "2025-10-08T09:15:15.543Z" }, + { url = "https://files.pythonhosted.org/packages/d3/68/93180dce57f684a61a88a45ed13047558ded2be46f03acb8dec6d7c513af/msgpack-1.1.2-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1fdf7d83102bf09e7ce3357de96c59b627395352a4024f6e2458501f158bf999", size = 412721, upload-time = "2025-10-08T09:15:16.567Z" }, + { url = "https://files.pythonhosted.org/packages/5d/ba/459f18c16f2b3fc1a1ca871f72f07d70c07bf768ad0a507a698b8052ac58/msgpack-1.1.2-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fac4be746328f90caa3cd4bc67e6fe36ca2bf61d5c6eb6d895b6527e3f05071e", size = 424657, upload-time = "2025-10-08T09:15:17.825Z" }, + { url = "https://files.pythonhosted.org/packages/38/f8/4398c46863b093252fe67368b44edc6c13b17f4e6b0e4929dbf0bdb13f23/msgpack-1.1.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:fffee09044073e69f2bad787071aeec727183e7580443dfeb8556cbf1978d162", size = 402668, upload-time = "2025-10-08T09:15:19.003Z" }, + { url = "https://files.pythonhosted.org/packages/28/ce/698c1eff75626e4124b4d78e21cca0b4cc90043afb80a507626ea354ab52/msgpack-1.1.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5928604de9b032bc17f5099496417f113c45bc6bc21b5c6920caf34b3c428794", size = 419040, upload-time = "2025-10-08T09:15:20.183Z" }, + { url = "https://files.pythonhosted.org/packages/67/32/f3cd1667028424fa7001d82e10ee35386eea1408b93d399b09fb0aa7875f/msgpack-1.1.2-cp313-cp313-win32.whl", hash = "sha256:a7787d353595c7c7e145e2331abf8b7ff1e6673a6b974ded96e6d4ec09f00c8c", size = 65037, upload-time = "2025-10-08T09:15:21.416Z" }, + { url = "https://files.pythonhosted.org/packages/74/07/1ed8277f8653c40ebc65985180b007879f6a836c525b3885dcc6448ae6cb/msgpack-1.1.2-cp313-cp313-win_amd64.whl", hash = "sha256:a465f0dceb8e13a487e54c07d04ae3ba131c7c5b95e2612596eafde1dccf64a9", size = 72631, upload-time = "2025-10-08T09:15:22.431Z" }, + { url = "https://files.pythonhosted.org/packages/e5/db/0314e4e2db56ebcf450f277904ffd84a7988b9e5da8d0d61ab2d057df2b6/msgpack-1.1.2-cp313-cp313-win_arm64.whl", hash = "sha256:e69b39f8c0aa5ec24b57737ebee40be647035158f14ed4b40e6f150077e21a84", size = 64118, upload-time = "2025-10-08T09:15:23.402Z" }, + { url = "https://files.pythonhosted.org/packages/22/71/201105712d0a2ff07b7873ed3c220292fb2ea5120603c00c4b634bcdafb3/msgpack-1.1.2-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:e23ce8d5f7aa6ea6d2a2b326b4ba46c985dbb204523759984430db7114f8aa00", size = 81127, upload-time = "2025-10-08T09:15:24.408Z" }, + { url = "https://files.pythonhosted.org/packages/1b/9f/38ff9e57a2eade7bf9dfee5eae17f39fc0e998658050279cbb14d97d36d9/msgpack-1.1.2-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:6c15b7d74c939ebe620dd8e559384be806204d73b4f9356320632d783d1f7939", size = 84981, upload-time = "2025-10-08T09:15:25.812Z" }, + { url = "https://files.pythonhosted.org/packages/8e/a9/3536e385167b88c2cc8f4424c49e28d49a6fc35206d4a8060f136e71f94c/msgpack-1.1.2-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:99e2cb7b9031568a2a5c73aa077180f93dd2e95b4f8d3b8e14a73ae94a9e667e", size = 411885, upload-time = "2025-10-08T09:15:27.22Z" }, + { url = "https://files.pythonhosted.org/packages/2f/40/dc34d1a8d5f1e51fc64640b62b191684da52ca469da9cd74e84936ffa4a6/msgpack-1.1.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:180759d89a057eab503cf62eeec0aa61c4ea1200dee709f3a8e9397dbb3b6931", size = 419658, upload-time = "2025-10-08T09:15:28.4Z" }, + { url = "https://files.pythonhosted.org/packages/3b/ef/2b92e286366500a09a67e03496ee8b8ba00562797a52f3c117aa2b29514b/msgpack-1.1.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:04fb995247a6e83830b62f0b07bf36540c213f6eac8e851166d8d86d83cbd014", size = 403290, upload-time = "2025-10-08T09:15:29.764Z" }, + { url = "https://files.pythonhosted.org/packages/78/90/e0ea7990abea5764e4655b8177aa7c63cdfa89945b6e7641055800f6c16b/msgpack-1.1.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:8e22ab046fa7ede9e36eeb4cfad44d46450f37bb05d5ec482b02868f451c95e2", size = 415234, upload-time = "2025-10-08T09:15:31.022Z" }, + { url = "https://files.pythonhosted.org/packages/72/4e/9390aed5db983a2310818cd7d3ec0aecad45e1f7007e0cda79c79507bb0d/msgpack-1.1.2-cp314-cp314-win32.whl", hash = "sha256:80a0ff7d4abf5fecb995fcf235d4064b9a9a8a40a3ab80999e6ac1e30b702717", size = 66391, upload-time = "2025-10-08T09:15:32.265Z" }, + { url = "https://files.pythonhosted.org/packages/6e/f1/abd09c2ae91228c5f3998dbd7f41353def9eac64253de3c8105efa2082f7/msgpack-1.1.2-cp314-cp314-win_amd64.whl", hash = "sha256:9ade919fac6a3e7260b7f64cea89df6bec59104987cbea34d34a2fa15d74310b", size = 73787, upload-time = "2025-10-08T09:15:33.219Z" }, + { url = "https://files.pythonhosted.org/packages/6a/b0/9d9f667ab48b16ad4115c1935d94023b82b3198064cb84a123e97f7466c1/msgpack-1.1.2-cp314-cp314-win_arm64.whl", hash = "sha256:59415c6076b1e30e563eb732e23b994a61c159cec44deaf584e5cc1dd662f2af", size = 66453, upload-time = "2025-10-08T09:15:34.225Z" }, + { url = "https://files.pythonhosted.org/packages/16/67/93f80545eb1792b61a217fa7f06d5e5cb9e0055bed867f43e2b8e012e137/msgpack-1.1.2-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:897c478140877e5307760b0ea66e0932738879e7aa68144d9b78ea4c8302a84a", size = 85264, upload-time = "2025-10-08T09:15:35.61Z" }, + { url = "https://files.pythonhosted.org/packages/87/1c/33c8a24959cf193966ef11a6f6a2995a65eb066bd681fd085afd519a57ce/msgpack-1.1.2-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:a668204fa43e6d02f89dbe79a30b0d67238d9ec4c5bd8a940fc3a004a47b721b", size = 89076, upload-time = "2025-10-08T09:15:36.619Z" }, + { url = "https://files.pythonhosted.org/packages/fc/6b/62e85ff7193663fbea5c0254ef32f0c77134b4059f8da89b958beb7696f3/msgpack-1.1.2-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5559d03930d3aa0f3aacb4c42c776af1a2ace2611871c84a75afe436695e6245", size = 435242, upload-time = "2025-10-08T09:15:37.647Z" }, + { url = "https://files.pythonhosted.org/packages/c1/47/5c74ecb4cc277cf09f64e913947871682ffa82b3b93c8dad68083112f412/msgpack-1.1.2-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:70c5a7a9fea7f036b716191c29047374c10721c389c21e9ffafad04df8c52c90", size = 432509, upload-time = "2025-10-08T09:15:38.794Z" }, + { url = "https://files.pythonhosted.org/packages/24/a4/e98ccdb56dc4e98c929a3f150de1799831c0a800583cde9fa022fa90602d/msgpack-1.1.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:f2cb069d8b981abc72b41aea1c580ce92d57c673ec61af4c500153a626cb9e20", size = 415957, upload-time = "2025-10-08T09:15:40.238Z" }, + { url = "https://files.pythonhosted.org/packages/da/28/6951f7fb67bc0a4e184a6b38ab71a92d9ba58080b27a77d3e2fb0be5998f/msgpack-1.1.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:d62ce1f483f355f61adb5433ebfd8868c5f078d1a52d042b0a998682b4fa8c27", size = 422910, upload-time = "2025-10-08T09:15:41.505Z" }, + { url = "https://files.pythonhosted.org/packages/f0/03/42106dcded51f0a0b5284d3ce30a671e7bd3f7318d122b2ead66ad289fed/msgpack-1.1.2-cp314-cp314t-win32.whl", hash = "sha256:1d1418482b1ee984625d88aa9585db570180c286d942da463533b238b98b812b", size = 75197, upload-time = "2025-10-08T09:15:42.954Z" }, + { url = "https://files.pythonhosted.org/packages/15/86/d0071e94987f8db59d4eeb386ddc64d0bb9b10820a8d82bcd3e53eeb2da6/msgpack-1.1.2-cp314-cp314t-win_amd64.whl", hash = "sha256:5a46bf7e831d09470ad92dff02b8b1ac92175ca36b087f904a0519857c6be3ff", size = 85772, upload-time = "2025-10-08T09:15:43.954Z" }, + { url = "https://files.pythonhosted.org/packages/81/f2/08ace4142eb281c12701fc3b93a10795e4d4dc7f753911d836675050f886/msgpack-1.1.2-cp314-cp314t-win_arm64.whl", hash = "sha256:d99ef64f349d5ec3293688e91486c5fdb925ed03807f64d98d205d2713c60b46", size = 70868, upload-time = "2025-10-08T09:15:44.959Z" }, +] [[package]] name = "multidict" From 59ae8e9684ef99994534c21d298ebc8ac42278b4 Mon Sep 17 00:00:00 2001 From: Sergio Herrera <627709+seherv@users.noreply.github.com> Date: Tue, 26 May 2026 10:00:44 +0200 Subject: [PATCH 2/2] Run linter Signed-off-by: Sergio Herrera <627709+seherv@users.noreply.github.com> --- RELEASE.md | 24 +++++++++++++++++++----- dapr/__init__.py | 6 +++--- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/RELEASE.md b/RELEASE.md index 5e94a6a8c..f6204a23a 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -10,11 +10,25 @@ A single tag (`v*`) triggers the release of the core SDK only: **The previously-separate distributions** — `dapr-ext-fastapi`, `dapr-ext-grpc`, `dapr-ext-langgraph`, `dapr-ext-strands`, `dapr-ext-workflow`, `flask-dapr` — -are **no longer published**. Republishing them as `dapr-ext-name` shims that -depend on `dapr[name]` was considered but rejected: any shim that doesn't carry -the actual extension code creates a `RECORD` ownership conflict with the legacy -versions in existing user environments, and `pip uninstall` of a legacy package would -delete files that core `dapr` now provides. +are **no longer published**. + +The design constraint was keeping `from dapr.ext.X import ...` stable across +the upgrade, so the cost lands once in pip during migration rather than +forever in every existing codebase that already imports those paths. + +The price: legacy dists on disk now claim the same files core `dapr` ships, +and pip has no cross-dist ownership awareness. `pip uninstall <legacy>` walks +the legacy RECORD and deletes `dapr/ext/<name>/*.py` from disk, leaving a +silently broken install: `pip show dapr` reports 1.19 installed, but +`from dapr.ext.<name> import ...` raises `ModuleNotFoundError`. The recipe +below uses `--force-reinstall --no-deps dapr` to rewrite those files after +the legacy uninstall removes them. + +Republishing the legacy distributions as `dapr-ext-name` shims depending on +`dapr[name]` was considered and rejected: any shim that doesn't ship the +actual files leaves the legacy version's RECORD on disk in existing +environments, so the same uninstall failure mode remains. They would also +add a per-extension release artifact to maintain in perpetuity. Existing installs must migrate explicitly: diff --git a/dapr/__init__.py b/dapr/__init__.py index 4f46a0983..9fb451b69 100644 --- a/dapr/__init__.py +++ b/dapr/__init__.py @@ -17,10 +17,10 @@ # the environment in. # # 1. Legacy `dapr-ext-*` or `flask-dapr` dist still installed alongside -# core dapr. +# core dapr. # Pre-1.19 each extension was its own dist owning files under -# `dapr/ext/<name>/`, the new core wheel ships those same files. -# pip has no cross-dist ownership awareness, so `pip uninstall <legacy>` +# `dapr/ext/<name>/`, the new core wheel ships those same files. +# pip has no cross-dist ownership awareness, so `pip uninstall <legacy>` # walks the legacy RECORD and deletes `dapr/ext/<name>/*.py` from disk. End # state: `pip show dapr` reports OK, but `from dapr.ext.<name> import ...` # raises ModuleNotFoundError.