├── dapr
├── py.typed
├── __init__.pyi
├── version
│ ├── __init__.py
│ └── version.py
├── proto
│ ├── common
│ │ ├── v1
│ │ │ ├── common_pb2_grpc.py
│ │ │ └── __init__.py
│ │ └── __init__.py
│ ├── runtime
│ │ ├── __init__.py
│ │ └── v1
│ │ │ └── __init__.py
│ ├── README.md
│ └── __init__.py
├── actor
│ ├── client
│ │ └── __init__.py
│ ├── runtime
│ │ ├── __init__.py
│ │ ├── reentrancy_context.py
│ │ ├── _call_type.py
│ │ ├── remindable.py
│ │ ├── state_change.py
│ │ ├── method_dispatcher.py
│ │ └── _method_context.py
│ ├── __init__.py
│ ├── id.py
│ └── actor_interface.py
├── clients
│ ├── grpc
│ │ └── __init__.py
│ ├── http
│ │ ├── __init__.py
│ │ ├── conf.py
│ │ └── helpers.py
│ ├── _constants.py
│ └── base.py
├── aio
│ └── clients
│ │ └── grpc
│ │ └── __init__.py
├── serializers
│ ├── __init__.py
│ └── base.py
└── conf
│ ├── __init__.py
│ └── global_settings.py
├── tests
├── __init__.py
├── actor
│ ├── utils.py
│ ├── __init__.py
│ ├── test_actor_id.py
│ ├── test_type_information.py
│ └── test_timer_data.py
├── clients
│ ├── __init__.py
│ ├── test_http_helpers.py
│ ├── test_dapr_grpc_response_async.py
│ ├── test_client_interceptor.py
│ └── test_timeout_interceptor_async.py
└── serializers
│ └── __init__.py
├── ext
├── dapr-ext-fastapi
│ ├── tests
│ │ └── __init__.py
│ ├── dapr
│ │ └── ext
│ │ │ └── fastapi
│ │ │ ├── py.typed
│ │ │ ├── version.py
│ │ │ └── __init__.py
│ ├── README.rst
│ ├── setup.cfg
│ └── setup.py
├── dapr-ext-grpc
│ ├── tests
│ │ ├── __init__.py
│ │ ├── test_health_servicer.py
│ │ └── test_topic_event_response.py
│ ├── dapr
│ │ └── ext
│ │ │ └── grpc
│ │ │ ├── py.typed
│ │ │ ├── version.py
│ │ │ ├── _health_servicer.py
│ │ │ └── __init__.py
│ ├── README.rst
│ ├── setup.cfg
│ └── setup.py
├── flask_dapr
│ ├── flask_dapr
│ │ ├── py.typed
│ │ ├── version.py
│ │ └── __init__.py
│ ├── README.rst
│ ├── setup.cfg
│ └── setup.py
├── dapr-ext-workflow
│ ├── dapr
│ │ └── ext
│ │ │ └── workflow
│ │ │ ├── py.typed
│ │ │ ├── logger
│ │ │ ├── __init__.py
│ │ │ ├── logger.py
│ │ │ └── options.py
│ │ │ ├── version.py
│ │ │ ├── aio
│ │ │ └── __init__.py
│ │ │ ├── util.py
│ │ │ ├── __init__.py
│ │ │ └── workflow_activity_context.py
│ ├── README.rst
│ ├── tests
│ │ ├── __init__.py
│ │ ├── test_workflow_util.py
│ │ └── test_workflow_activity_context.py
│ └── setup.cfg
└── dapr-ext-langgraph
│ ├── dapr
│ └── ext
│ │ └── langgraph
│ │ ├── py.typed
│ │ ├── version.py
│ │ └── __init__.py
│ ├── README.rst
│ ├── tests
│ └── __init__.py
│ └── setup.cfg
├── tools
└── requirements.txt
├── examples
├── demo_actor
│ ├── demo_actor
│ │ ├── requirements.txt
│ │ ├── Dockerfile
│ │ ├── demo_actor_interface.py
│ │ ├── demo_actor_service.py
│ │ ├── test_demo_actor.py
│ │ └── demo_actor_flask.py
│ └── deploy
│ │ ├── redis.yml
│ │ ├── demo_actor_client.yml
│ │ └── demo_actor_service.yml
├── demo_workflow
│ ├── demo_workflow
│ │ └── requirements.txt
│ └── components
│ │ └── state_redis.yaml
├── workflow
│ ├── requirements.txt
│ ├── cross-app3.py
│ ├── child_workflow.py
│ ├── cross-app2.py
│ └── cross-app1.py
├── invoke-simple
│ ├── requirements.txt
│ ├── Dockerfile
│ ├── invoke-receiver.py
│ ├── invoke-caller.py
│ └── deploy
│ │ ├── invoke-caller.yaml
│ │ └── invoke-receiver.yaml
├── validate.sh
├── crypto
│ ├── desert.jpg
│ └── components
│ │ └── crypto-localstorage.yaml
├── secret_store
│ ├── secrets.json
│ ├── config.yaml
│ ├── components
│ │ └── localsecretstore.yaml
│ └── example.py
├── langgraph-checkpointer
│ ├── requirements.txt
│ ├── components
│ │ └── statestore.yaml
│ ├── README.md
│ └── agent.py
├── w3c-tracing
│ ├── img
│ │ ├── service.png
│ │ ├── zipkin-details.png
│ │ ├── zipkin-landing.png
│ │ └── zipkin-result.png
│ ├── requirements.txt
│ └── Dockerfile
├── conversation
│ ├── config
│ │ └── conversation-echo.yaml
│ ├── .env.example
│ ├── conversation_alpha1.py
│ └── conversation_alpha2.py
├── invoke-custom-data
│ ├── proto
│ │ ├── response.proto
│ │ ├── response_pb2_grpc.py
│ │ └── response_pb2.py
│ ├── invoke-receiver.py
│ └── invoke-caller.py
├── state_store_query
│ ├── components
│ │ └── mongodb.yml
│ ├── query.json
│ ├── query-token.json
│ ├── state_store_query.py
│ └── dataset.json
├── invoke-binding
│ ├── invoke-input-binding.py
│ ├── components
│ │ ├── pubsub.yaml
│ │ ├── statestore.yaml
│ │ └── kafka-binding.yaml
│ ├── invoke-output-binding.py
│ └── docker-compose-single-kafka.yml
├── metadata
│ ├── components
│ │ ├── pubsub.yaml
│ │ ├── lockstore.yaml
│ │ └── statestore.yaml
│ └── app.py
├── state_store
│ └── components
│ │ ├── pubsub.yaml
│ │ └── statestore.yaml
├── distributed_lock
│ ├── components
│ │ └── lockstore.yaml
│ └── lock.py
├── grpc_proxying
│ ├── config.yaml
│ ├── proto
│ │ └── helloworld_service.proto
│ ├── invoke-caller.py
│ ├── invoke-receiver.py
│ ├── deploy
│ │ ├── invoke-caller.yaml
│ │ └── invoke-receiver.yaml
│ └── helloworld_service_pb2.py
├── configuration
│ ├── components
│ │ └── configurationstore.yaml
│ ├── configuration.py
│ └── README.md
├── error_handling
│ ├── components
│ │ └── state_redis.yaml
│ └── error_handling.py
├── invoke-http
│ ├── invoke-receiver.py
│ ├── invoke-caller.py
│ └── README.md
├── pubsub-streaming
│ ├── subscriber-handler.py
│ └── publisher.py
├── README.md
└── pubsub-streaming-async
│ ├── subscriber-handler.py
│ └── publisher.py
├── docs
├── actor
│ ├── modules.rst
│ ├── actor.client.rst
│ ├── actor.rst
│ └── actor.runtime.rst
├── proto
│ ├── modules.rst
│ ├── proto.dapr.rst
│ ├── proto.common.rst
│ ├── proto.runtime.rst
│ ├── proto.rst
│ ├── proto.daprclient.rst
│ ├── proto.dapr.v1.rst
│ ├── proto.common.v1.rst
│ ├── proto.daprclient.v1.rst
│ └── proto.runtime.v1.rst
├── clients
│ ├── modules.rst
│ ├── clients.http.rst
│ ├── clients.rst
│ └── clients.grpc.rst
├── serializers
│ ├── modules.rst
│ └── serializers.rst
├── index.rst
├── Makefile
└── make.bat
├── CODEOWNERS
├── .github
├── holopin.yml
├── ISSUE_TEMPLATE
│ ├── question.md
│ ├── workflow_question.md
│ ├── feature_request.md
│ ├── workflow_feature_request.md
│ ├── config.yml
│ ├── bug_report.md
│ └── workflow_bug_report.md
├── pull_request_template.md
├── dependabot.yml
└── workflows
│ ├── build.yaml
│ └── fossa.yaml
├── .devcontainer
├── postCreateCommand.sh
└── devcontainer.json
├── .codecov.yml
├── mypy.ini
├── dev-requirements.txt
├── pyproject.toml
├── setup.cfg
├── .gitignore
└── setup.py
/dapr/py.typed:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/dapr/__init__.pyi:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ext/dapr-ext-fastapi/tests/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ext/dapr-ext-grpc/tests/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ext/flask_dapr/flask_dapr/py.typed:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ext/dapr-ext-grpc/dapr/ext/grpc/py.typed:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ext/dapr-ext-fastapi/dapr/ext/fastapi/py.typed:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ext/dapr-ext-workflow/dapr/ext/workflow/py.typed:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ext/dapr-ext-langgraph/dapr/ext/langgraph/py.typed:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tools/requirements.txt:
--------------------------------------------------------------------------------
1 | grpcio-tools==1.62.3
2 | mypy-protobuf==3.7.0
3 |
--------------------------------------------------------------------------------
/examples/demo_actor/demo_actor/requirements.txt:
--------------------------------------------------------------------------------
1 | dapr-ext-fastapi>=1.16.0.dev
2 |
--------------------------------------------------------------------------------
/examples/demo_workflow/demo_workflow/requirements.txt:
--------------------------------------------------------------------------------
1 | dapr-ext-workflow>=1.16.0.dev
2 |
--------------------------------------------------------------------------------
/examples/workflow/requirements.txt:
--------------------------------------------------------------------------------
1 | dapr-ext-workflow>=1.16.0.dev
2 | dapr>=1.16.0.dev
3 |
--------------------------------------------------------------------------------
/examples/invoke-simple/requirements.txt:
--------------------------------------------------------------------------------
1 | dapr-ext-grpc >= 1.16.0.dev
2 | dapr >= 1.16.0.dev
3 |
--------------------------------------------------------------------------------
/examples/validate.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | echo "Home: $HOME"
3 |
4 | cd $1 && mm.py -l README.md
5 |
--------------------------------------------------------------------------------
/docs/actor/modules.rst:
--------------------------------------------------------------------------------
1 | actor
2 | =====
3 |
4 | .. toctree::
5 | :maxdepth: 4
6 |
7 | actor
8 |
--------------------------------------------------------------------------------
/docs/proto/modules.rst:
--------------------------------------------------------------------------------
1 | proto
2 | =====
3 |
4 | .. toctree::
5 | :maxdepth: 4
6 |
7 | proto
8 |
--------------------------------------------------------------------------------
/examples/crypto/desert.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dapr/python-sdk/HEAD/examples/crypto/desert.jpg
--------------------------------------------------------------------------------
/dapr/version/__init__.py:
--------------------------------------------------------------------------------
1 | from dapr.version.version import __version__
2 |
3 | __all__ = ['__version__']
4 |
--------------------------------------------------------------------------------
/docs/clients/modules.rst:
--------------------------------------------------------------------------------
1 | clients
2 | =======
3 |
4 | .. toctree::
5 | :maxdepth: 4
6 |
7 | clients
8 |
--------------------------------------------------------------------------------
/examples/secret_store/secrets.json:
--------------------------------------------------------------------------------
1 | {
2 | "secretKey": "secretValue",
3 | "random": "randomValue"
4 | }
--------------------------------------------------------------------------------
/examples/langgraph-checkpointer/requirements.txt:
--------------------------------------------------------------------------------
1 | langchain-core>=1.0.7
2 | langgraph>=1.0.3
3 | langchain-ollama>=1.0.0
--------------------------------------------------------------------------------
/examples/w3c-tracing/img/service.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dapr/python-sdk/HEAD/examples/w3c-tracing/img/service.png
--------------------------------------------------------------------------------
/docs/serializers/modules.rst:
--------------------------------------------------------------------------------
1 | serializers
2 | ===========
3 |
4 | .. toctree::
5 | :maxdepth: 4
6 |
7 | serializers
8 |
--------------------------------------------------------------------------------
/examples/w3c-tracing/img/zipkin-details.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dapr/python-sdk/HEAD/examples/w3c-tracing/img/zipkin-details.png
--------------------------------------------------------------------------------
/examples/w3c-tracing/img/zipkin-landing.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dapr/python-sdk/HEAD/examples/w3c-tracing/img/zipkin-landing.png
--------------------------------------------------------------------------------
/examples/w3c-tracing/img/zipkin-result.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dapr/python-sdk/HEAD/examples/w3c-tracing/img/zipkin-result.png
--------------------------------------------------------------------------------
/CODEOWNERS:
--------------------------------------------------------------------------------
1 | # These owners are the maintainers and approvers of this repo
2 | * @dapr/maintainers-python-sdk @dapr/approvers-python-sdk
3 |
--------------------------------------------------------------------------------
/.github/holopin.yml:
--------------------------------------------------------------------------------
1 | organization: dapr
2 | defaultSticker: clrqfdv4x24910fl5n4iwu5oa
3 | stickers:
4 | - id: clrqfdv4x24910fl5n4iwu5oa
5 | alias: sdk-badge
6 |
--------------------------------------------------------------------------------
/examples/conversation/config/conversation-echo.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: dapr.io/v1alpha1
2 | kind: Component
3 | metadata:
4 | name: echo
5 | spec:
6 | type: conversation.echo
7 | version: v1
--------------------------------------------------------------------------------
/examples/invoke-custom-data/proto/response.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | message CustomResponse {
4 | bool isSuccess = 1;
5 | int32 code = 2;
6 | string message = 3;
7 | }
--------------------------------------------------------------------------------
/examples/w3c-tracing/requirements.txt:
--------------------------------------------------------------------------------
1 | dapr-ext-grpc >= 1.16.0.dev
2 | dapr >= 1.16.0.dev
3 | opentelemetry-sdk
4 | opentelemetry-instrumentation-grpc
5 | opentelemetry-exporter-zipkin
6 |
--------------------------------------------------------------------------------
/examples/invoke-custom-data/proto/response_pb2_grpc.py:
--------------------------------------------------------------------------------
1 | # Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT!
2 | """Client and server classes corresponding to protobuf-defined services."""
3 |
--------------------------------------------------------------------------------
/dapr/proto/common/v1/common_pb2_grpc.py:
--------------------------------------------------------------------------------
1 | # Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT!
2 | """Client and server classes corresponding to protobuf-defined services."""
3 | import grpc
4 |
5 |
--------------------------------------------------------------------------------
/ext/dapr-ext-workflow/dapr/ext/workflow/logger/__init__.py:
--------------------------------------------------------------------------------
1 | from dapr.ext.workflow.logger.logger import Logger
2 | from dapr.ext.workflow.logger.options import LoggerOptions
3 |
4 | __all__ = ['LoggerOptions', 'Logger']
5 |
--------------------------------------------------------------------------------
/examples/invoke-simple/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM python:3.9-slim
2 |
3 | WORKDIR /app
4 |
5 | ADD requirements.txt .
6 | RUN pip install -r requirements.txt
7 |
8 | COPY *.py /app/
9 |
10 | CMD [ "python", "invoke-receiver.py" ]
11 |
--------------------------------------------------------------------------------
/examples/w3c-tracing/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM python:3.9-slim
2 |
3 | WORKDIR /app
4 |
5 | ADD requirements.txt .
6 | RUN pip install -r requirements.txt
7 |
8 | COPY *.py /app/
9 |
10 | CMD [ "python", "invoke-receiver.py" ]
11 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/question.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Question (not workflow)
3 | about: Ask a question about the python sdk (not workflow)
4 | title: '[QUESTION]
'
5 | labels: kind/question
6 | assignees: ''
7 |
8 | ---
9 | ## Ask your question here
10 |
--------------------------------------------------------------------------------
/examples/state_store_query/components/mongodb.yml:
--------------------------------------------------------------------------------
1 | apiVersion: dapr.io/v1alpha1
2 | kind: Component
3 | metadata:
4 | name: statestore
5 | spec:
6 | type: state.mongodb
7 | version: v1
8 | metadata:
9 | - name: host
10 | value: localhost:27017
11 |
--------------------------------------------------------------------------------
/examples/invoke-binding/invoke-input-binding.py:
--------------------------------------------------------------------------------
1 | from dapr.ext.grpc import App, BindingRequest
2 |
3 | app = App()
4 |
5 |
6 | @app.binding('kafkaBinding')
7 | def binding(request: BindingRequest):
8 | print(request.text(), flush=True)
9 |
10 |
11 | app.run(50051)
12 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/workflow_question.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: WORKFLOW Question
3 | about: Ask a question about workflow
4 | title: '[WORKFLOW QUESTION] '
5 | labels: ["kind/question", "dapr-ext-workflow"]
6 | assignees: ''
7 |
8 | ---
9 | ## Ask your WORKFLOW SDK question here
10 |
--------------------------------------------------------------------------------
/examples/invoke-binding/components/pubsub.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: dapr.io/v1alpha1
2 | kind: Component
3 | metadata:
4 | name: pubsub
5 | spec:
6 | type: pubsub.redis
7 | metadata:
8 | - name: redisHost
9 | value: localhost:6379
10 | - name: redisPassword
11 | value: ""
12 |
--------------------------------------------------------------------------------
/examples/secret_store/config.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: dapr.io/v1alpha1
2 | kind: Configuration
3 | metadata:
4 | name: daprConfig
5 | spec:
6 | secrets:
7 | scopes:
8 | - storeName: "localsecretstore"
9 | defaultAccess: "deny"
10 | allowedSecrets: ["secretKey",]
--------------------------------------------------------------------------------
/examples/metadata/components/pubsub.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: dapr.io/v1alpha1
2 | kind: Component
3 | metadata:
4 | name: pubsub
5 | spec:
6 | type: pubsub.redis
7 | version: v1
8 | metadata:
9 | - name: redisHost
10 | value: localhost:6379
11 | - name: redisPassword
12 | value: ""
13 |
--------------------------------------------------------------------------------
/.devcontainer/postCreateCommand.sh:
--------------------------------------------------------------------------------
1 | # Install a project in a editable mode
2 | pip3 install -e .
3 | pip3 install -e ./ext/dapr-ext-grpc/
4 | pip3 install -e ./ext/dapr-ext-fastapi/
5 | pip3 install -e ./ext/dapr-ext-workflow/
6 |
7 | # Install required packages
8 | pip3 install -r ./dev-requirements.txt
9 |
--------------------------------------------------------------------------------
/examples/state_store/components/pubsub.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: dapr.io/v1alpha1
2 | kind: Component
3 | metadata:
4 | name: pubsub
5 | spec:
6 | type: pubsub.redis
7 | version: v1
8 | metadata:
9 | - name: redisHost
10 | value: localhost:6379
11 | - name: redisPassword
12 | value: ""
13 |
--------------------------------------------------------------------------------
/examples/metadata/components/lockstore.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: dapr.io/v1alpha1
2 | kind: Component
3 | metadata:
4 | name: lockstore
5 | namespace: default
6 | spec:
7 | type: lock.redis
8 | metadata:
9 | - name: redisHost
10 | value: localhost:6379
11 | - name: redisPassword
12 | value: ""
13 |
--------------------------------------------------------------------------------
/examples/distributed_lock/components/lockstore.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: dapr.io/v1alpha1
2 | kind: Component
3 | metadata:
4 | name: lockstore
5 | namespace: default
6 | spec:
7 | type: lock.redis
8 | metadata:
9 | - name: redisHost
10 | value: localhost:6379
11 | - name: redisPassword
12 | value: ""
13 |
--------------------------------------------------------------------------------
/examples/grpc_proxying/config.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: dapr.io/v1alpha1
2 | kind: Configuration
3 | metadata:
4 | name: serverconfig
5 | spec:
6 | tracing:
7 | samplingRate: "1"
8 | zipkin:
9 | endpointAddress: http://localhost:9411/api/v2/spans
10 | features:
11 | - name: proxy.grpc
12 | enabled: true
--------------------------------------------------------------------------------
/docs/proto/proto.dapr.rst:
--------------------------------------------------------------------------------
1 | proto.dapr package
2 | ==================
3 |
4 | Subpackages
5 | -----------
6 |
7 | .. toctree::
8 | :maxdepth: 4
9 |
10 | proto.dapr.v1
11 |
12 | Module contents
13 | ---------------
14 |
15 | .. automodule:: proto.dapr
16 | :members:
17 | :undoc-members:
18 | :show-inheritance:
19 |
--------------------------------------------------------------------------------
/examples/configuration/components/configurationstore.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: dapr.io/v1alpha1
2 | kind: Component
3 | metadata:
4 | name: configurationstore
5 | namespace: default
6 | spec:
7 | type: configuration.redis
8 | metadata:
9 | - name: redisHost
10 | value: localhost:6379
11 | - name: redisPassword
12 | value: ""
--------------------------------------------------------------------------------
/examples/secret_store/components/localsecretstore.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: dapr.io/v1alpha1
2 | kind: Component
3 | metadata:
4 | name: localsecretstore
5 | namespace: default
6 | spec:
7 | type: secretstores.local.file
8 | metadata:
9 | - name: secretsFile
10 | value: secrets.json
11 | - name: nestedSeparator
12 | value: ":"
--------------------------------------------------------------------------------
/docs/proto/proto.common.rst:
--------------------------------------------------------------------------------
1 | proto.common package
2 | ====================
3 |
4 | Subpackages
5 | -----------
6 |
7 | .. toctree::
8 | :maxdepth: 4
9 |
10 | proto.common.v1
11 |
12 | Module contents
13 | ---------------
14 |
15 | .. automodule:: proto.common
16 | :members:
17 | :undoc-members:
18 | :show-inheritance:
19 |
--------------------------------------------------------------------------------
/docs/proto/proto.runtime.rst:
--------------------------------------------------------------------------------
1 | proto.runtime package
2 | =====================
3 |
4 | Subpackages
5 | -----------
6 |
7 | .. toctree::
8 | :maxdepth: 4
9 |
10 | proto.runtime.v1
11 |
12 | Module contents
13 | ---------------
14 |
15 | .. automodule:: proto.runtime
16 | :members:
17 | :undoc-members:
18 | :show-inheritance:
19 |
--------------------------------------------------------------------------------
/examples/crypto/components/crypto-localstorage.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: dapr.io/v1alpha1
2 | kind: Component
3 | metadata:
4 | name: crypto-localstorage
5 | spec:
6 | type: crypto.dapr.localstorage
7 | version: v1
8 | metadata:
9 | - name: path
10 | # Path is relative to the folder where the example is located
11 | value: ./keys
--------------------------------------------------------------------------------
/examples/invoke-binding/components/statestore.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: dapr.io/v1alpha1
2 | kind: Component
3 | metadata:
4 | name: statestore
5 | spec:
6 | type: state.redis
7 | metadata:
8 | - name: redisHost
9 | value: localhost:6379
10 | - name: redisPassword
11 | value: ""
12 | - name: actorStateStore
13 | value: "true"
14 |
--------------------------------------------------------------------------------
/docs/proto/proto.rst:
--------------------------------------------------------------------------------
1 | proto package
2 | =============
3 |
4 | Subpackages
5 | -----------
6 |
7 | .. toctree::
8 | :maxdepth: 4
9 |
10 | proto.common
11 | proto.dapr
12 | proto.daprclient
13 |
14 | Module contents
15 | ---------------
16 |
17 | .. automodule:: proto
18 | :members:
19 | :undoc-members:
20 | :show-inheritance:
21 |
--------------------------------------------------------------------------------
/docs/proto/proto.daprclient.rst:
--------------------------------------------------------------------------------
1 | proto.daprclient package
2 | ========================
3 |
4 | Subpackages
5 | -----------
6 |
7 | .. toctree::
8 | :maxdepth: 4
9 |
10 | proto.daprclient.v1
11 |
12 | Module contents
13 | ---------------
14 |
15 | .. automodule:: proto.daprclient
16 | :members:
17 | :undoc-members:
18 | :show-inheritance:
19 |
--------------------------------------------------------------------------------
/examples/metadata/components/statestore.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: dapr.io/v1alpha1
2 | kind: Component
3 | metadata:
4 | name: statestore
5 | spec:
6 | type: state.redis
7 | version: v1
8 | metadata:
9 | - name: redisHost
10 | value: localhost:6379
11 | - name: redisPassword
12 | value: ""
13 | - name: actorStateStore
14 | value: "true"
15 |
--------------------------------------------------------------------------------
/examples/langgraph-checkpointer/components/statestore.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: dapr.io/v1alpha1
2 | kind: Component
3 | metadata:
4 | name: statestore
5 | spec:
6 | type: state.redis
7 | version: v1
8 | metadata:
9 | - name: redisHost
10 | value: localhost:6379
11 | - name: redisPassword
12 | value: ""
13 | - name: actorStateStore
14 | value: "true"
15 |
--------------------------------------------------------------------------------
/examples/error_handling/components/state_redis.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: dapr.io/v1alpha1
2 | kind: Component
3 | metadata:
4 | name: statestore
5 | spec:
6 | type: state.redis
7 | version: v1
8 | initTimeout: 1m
9 | metadata:
10 | - name: redisHost
11 | value: localhost:6379
12 | - name: redisPassword
13 | value: ""
14 | - name: actorStateStore
15 | value: "true"
--------------------------------------------------------------------------------
/.codecov.yml:
--------------------------------------------------------------------------------
1 | coverage:
2 | status:
3 | project:
4 | default:
5 | # basic
6 | target: auto
7 | threshold: 0%
8 |
9 | ignore:
10 | - dapr/proto # - Generated GRPC client
11 | - tests # - tests
12 | - .tox # - environment
13 | - ext/dapr-ext-fastapi/tests # - fastapi extention tests
14 |
--------------------------------------------------------------------------------
/docs/actor/actor.client.rst:
--------------------------------------------------------------------------------
1 | actor.client package
2 | ====================
3 |
4 | Submodules
5 | ----------
6 |
7 |
8 | .. automodule:: actor.client.proxy
9 | :members:
10 | :undoc-members:
11 | :show-inheritance:
12 |
13 |
14 | Module contents
15 | ---------------
16 |
17 | .. automodule:: actor.client
18 | :members:
19 | :undoc-members:
20 | :show-inheritance:
21 |
--------------------------------------------------------------------------------
/examples/demo_workflow/components/state_redis.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: dapr.io/v1alpha1
2 | kind: Component
3 | metadata:
4 | name: statestore-actors
5 | spec:
6 | type: state.redis
7 | version: v1
8 | initTimeout: 1m
9 | metadata:
10 | - name: redisHost
11 | value: localhost:6379
12 | - name: redisPassword
13 | value: ""
14 | - name: actorStateStore
15 | value: "true"
--------------------------------------------------------------------------------
/docs/clients/clients.http.rst:
--------------------------------------------------------------------------------
1 | clients.http package
2 | ====================
3 |
4 | Submodules
5 | ----------
6 |
7 |
8 | .. automodule:: clients.http.dapr_actor_http_client
9 | :members:
10 | :undoc-members:
11 | :show-inheritance:
12 |
13 |
14 | Module contents
15 | ---------------
16 |
17 | .. automodule:: clients.http
18 | :members:
19 | :undoc-members:
20 | :show-inheritance:
21 |
--------------------------------------------------------------------------------
/examples/grpc_proxying/proto/helloworld_service.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | message HelloRequest {
4 | string name = 1;
5 | }
6 |
7 | // The response message containing the greetings
8 | message HelloReply {
9 | string message = 1;
10 | }
11 |
12 | // The greeting service definition.
13 | service HelloWorldService {
14 | // Sends a greeting
15 | rpc SayHello (HelloRequest) returns (HelloReply) {}
16 | }
--------------------------------------------------------------------------------
/examples/demo_actor/deploy/redis.yml:
--------------------------------------------------------------------------------
1 | apiVersion: dapr.io/v1alpha1
2 | kind: Component
3 | metadata:
4 | name: statestore
5 | namespace: default
6 | spec:
7 | type: state.redis
8 | version: v1
9 | metadata:
10 | - name: redisHost
11 | value: redis-master.default.svc.cluster.local:6379
12 | - name: redisPassword
13 | secretKeyRef:
14 | name: redis
15 | key: redis-password
16 | - name: actorStateStore
17 | value: "true"
18 |
--------------------------------------------------------------------------------
/examples/invoke-simple/invoke-receiver.py:
--------------------------------------------------------------------------------
1 | from dapr.ext.grpc import App, InvokeMethodRequest, InvokeMethodResponse
2 |
3 | app = App()
4 |
5 |
6 | @app.method(name='my-method')
7 | def mymethod(request: InvokeMethodRequest) -> InvokeMethodResponse:
8 | print(request.metadata, flush=True)
9 | print(request.text(), flush=True)
10 |
11 | return InvokeMethodResponse(b'INVOKE_RECEIVED', 'text/plain; charset=UTF-8')
12 |
13 |
14 | app.run(50051)
15 |
--------------------------------------------------------------------------------
/examples/state_store/components/statestore.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: dapr.io/v1alpha1
2 | kind: Component
3 | metadata:
4 | name: statestore
5 | spec:
6 | type: state.redis
7 | version: v1
8 | metadata:
9 | - name: redisHost
10 | value: localhost:6379
11 | - name: redisPassword
12 | value: ""
13 | - name: actorStateStore
14 | value: "true"
15 | - name: outboxPublishPubsub
16 | value: "pubsub"
17 | - name: outboxPublishTopic
18 | value: "test"
--------------------------------------------------------------------------------
/examples/invoke-custom-data/invoke-receiver.py:
--------------------------------------------------------------------------------
1 | import proto.response_pb2 as response_messages
2 | from dapr.ext.grpc import App, InvokeMethodRequest
3 |
4 | app = App()
5 |
6 |
7 | @app.method('my_method')
8 | def mymethod(request: InvokeMethodRequest):
9 | print(request.metadata, flush=True)
10 | print(request.text(), flush=True)
11 |
12 | return response_messages.CustomResponse(
13 | isSuccess=True, code=200, message='Hello World - Success!'
14 | )
15 |
16 |
17 | app.run(50051)
18 |
--------------------------------------------------------------------------------
/docs/proto/proto.dapr.v1.rst:
--------------------------------------------------------------------------------
1 | proto.dapr.v1 package
2 | =====================
3 |
4 | Submodules
5 | ----------
6 |
7 |
8 | .. automodule:: proto.dapr.v1.dapr_pb2
9 | :members:
10 | :undoc-members:
11 | :show-inheritance:
12 |
13 |
14 | .. automodule:: proto.dapr.v1.dapr_pb2_grpc
15 | :members:
16 | :undoc-members:
17 | :show-inheritance:
18 |
19 |
20 | Module contents
21 | ---------------
22 |
23 | .. automodule:: proto.dapr.v1
24 | :members:
25 | :undoc-members:
26 | :show-inheritance:
27 |
--------------------------------------------------------------------------------
/ext/dapr-ext-grpc/README.rst:
--------------------------------------------------------------------------------
1 | dapr-ext-grpc extension
2 | =======================
3 |
4 | |pypi|
5 |
6 | .. |pypi| image:: https://badge.fury.io/py/dapr-ext-grpc.svg
7 | :target: https://pypi.org/project/dapr-ext-grpc/
8 |
9 | This gRPC extension is used for gRPC appcallback
10 |
11 | Installation
12 | ------------
13 |
14 | ::
15 |
16 | pip install dapr-ext-grpc
17 |
18 | References
19 | ----------
20 |
21 | * `Dapr `_
22 | * `Dapr Python-SDK `_
23 |
--------------------------------------------------------------------------------
/docs/proto/proto.common.v1.rst:
--------------------------------------------------------------------------------
1 | proto.common.v1 package
2 | =======================
3 |
4 | Submodules
5 | ----------
6 |
7 |
8 | .. automodule:: proto.common.v1.common_pb2
9 | :members:
10 | :undoc-members:
11 | :show-inheritance:
12 |
13 |
14 | .. automodule:: proto.common.v1.common_pb2_grpc
15 | :members:
16 | :undoc-members:
17 | :show-inheritance:
18 |
19 |
20 | Module contents
21 | ---------------
22 |
23 | .. automodule:: proto.common.v1
24 | :members:
25 | :undoc-members:
26 | :show-inheritance:
27 |
--------------------------------------------------------------------------------
/ext/dapr-ext-fastapi/README.rst:
--------------------------------------------------------------------------------
1 | dapr-ext-fastapi extension
2 | ==========================
3 |
4 | |pypi|
5 |
6 | .. |pypi| image:: https://badge.fury.io/py/dapr-ext-fastapi.svg
7 | :target: https://pypi.org/project/dapr-ext-fastapi/
8 |
9 | This FastAPI extension is used for FastAPI http server.
10 |
11 | Installation
12 | ------------
13 |
14 | ::
15 |
16 | pip install dapr-ext-fastapi
17 |
18 | References
19 | ----------
20 |
21 | * `Dapr `_
22 | * `Dapr Python-SDK `_
23 |
--------------------------------------------------------------------------------
/tests/actor/utils.py:
--------------------------------------------------------------------------------
1 | import asyncio
2 | from unittest import mock
3 |
4 |
5 | def _async_mock(*args, **kwargs):
6 | m = mock.MagicMock(*args, **kwargs)
7 |
8 | async def mock_coro(*args, **kwargs):
9 | return m(*args, **kwargs)
10 |
11 | mock_coro.mock = m
12 | return mock_coro
13 |
14 |
15 | def _run(coro):
16 | try:
17 | loop = asyncio.get_running_loop()
18 | except RuntimeError:
19 | loop = asyncio.new_event_loop()
20 | asyncio.set_event_loop(loop)
21 | return loop.run_until_complete(coro)
22 |
--------------------------------------------------------------------------------
/ext/dapr-ext-langgraph/README.rst:
--------------------------------------------------------------------------------
1 | dapr-ext-langgraph extension
2 | =======================
3 |
4 | |pypi|
5 |
6 | .. |pypi| image:: https://badge.fury.io/py/dapr-ext-langgraph.svg
7 | :target: https://pypi.org/project/dapr-ext-langgraph/
8 |
9 | This is the Dapr Checkpointer extension for LangGraph
10 |
11 | Installation
12 | ------------
13 |
14 | ::
15 |
16 | pip install dapr-ext-langgraph
17 |
18 | References
19 | ----------
20 |
21 | * `Dapr `_
22 | * `Dapr Python-SDK `_
23 |
--------------------------------------------------------------------------------
/examples/invoke-binding/invoke-output-binding.py:
--------------------------------------------------------------------------------
1 | import json
2 | import time
3 |
4 | from dapr.clients import DaprClient
5 |
6 | with DaprClient() as d:
7 | n = 0
8 | while True:
9 | n += 1
10 | req_data = {'id': n, 'message': 'hello world'}
11 |
12 | print(f'Sending message id: {req_data["id"]}, message "{req_data["message"]}"', flush=True)
13 |
14 | # Create a typed message with content type and body
15 | resp = d.invoke_binding('kafkaBinding', 'create', json.dumps(req_data))
16 |
17 | time.sleep(1)
18 |
--------------------------------------------------------------------------------
/docs/proto/proto.daprclient.v1.rst:
--------------------------------------------------------------------------------
1 | proto.daprclient.v1 package
2 | ===========================
3 |
4 | Submodules
5 | ----------
6 |
7 |
8 | .. automodule:: proto.daprclient.v1.daprclient_pb2
9 | :members:
10 | :undoc-members:
11 | :show-inheritance:
12 |
13 |
14 | .. automodule:: proto.daprclient.v1.daprclient_pb2_grpc
15 | :members:
16 | :undoc-members:
17 | :show-inheritance:
18 |
19 |
20 | Module contents
21 | ---------------
22 |
23 | .. automodule:: proto.daprclient.v1
24 | :members:
25 | :undoc-members:
26 | :show-inheritance:
27 |
--------------------------------------------------------------------------------
/ext/dapr-ext-workflow/README.rst:
--------------------------------------------------------------------------------
1 | dapr-ext-workflow extension
2 | ===========================
3 |
4 | |pypi|
5 |
6 | .. |pypi| image:: https://badge.fury.io/py/dapr-ext-workflow.svg
7 | :target: https://pypi.org/project/dapr-ext-workflow/
8 |
9 | This is the workflow authoring extension for Dapr Workflow
10 |
11 |
12 | Installation
13 | ------------
14 |
15 | ::
16 |
17 | pip install dapr-ext-workflow
18 |
19 | References
20 | ----------
21 |
22 | * `Dapr `_
23 | * `Dapr Python-SDK `_
24 |
--------------------------------------------------------------------------------
/mypy.ini:
--------------------------------------------------------------------------------
1 | [mypy]
2 | python_version = 3.9
3 | warn_unused_configs = True
4 | warn_redundant_casts = True
5 | show_error_codes = True
6 | check_untyped_defs = True
7 | install_types = True
8 | non_interactive = True
9 |
10 | files =
11 | dapr/actor/**/*.py,
12 | dapr/clients/**/*.py,
13 | dapr/conf/**/*.py,
14 | dapr/serializers/**/*.py,
15 | ext/dapr-ext-grpc/dapr/**/*.py,
16 | ext/dapr-ext-fastapi/dapr/**/*.py,
17 | ext/flask_dapr/flask_dapr/*.py,
18 | examples/demo_actor/**/*.py
19 |
20 | [mypy-dapr.proto.*]
21 | ignore_errors = True
22 |
--------------------------------------------------------------------------------
/.github/pull_request_template.md:
--------------------------------------------------------------------------------
1 | # Description
2 |
3 | _Please explain the changes you've made_
4 |
5 | ## Issue reference
6 |
7 | We strive to have all PR being opened based on an issue, where the problem or feature have been discussed prior to implementation.
8 |
9 | Please reference the issue this PR will close: #_[issue number]_
10 |
11 | ## Checklist
12 |
13 | Please make sure you've completed the relevant tasks for this PR, out of the following list:
14 |
15 | * [ ] Code compiles correctly
16 | * [ ] Created/updated tests
17 | * [ ] Extended the documentation
18 |
--------------------------------------------------------------------------------
/examples/conversation/.env.example:
--------------------------------------------------------------------------------
1 | # LLM Provider API Keys
2 | # Add your API keys for the providers you want to test
3 |
4 | # OpenAI
5 | OPENAI_API_KEY=your_openai_api_key_here
6 |
7 | # Anthropic
8 | ANTHROPIC_API_KEY=your_anthropic_api_key_here
9 |
10 | # Mistral AI
11 | MISTRAL_API_KEY=your_mistral_api_key_here
12 |
13 | # DeepSeek
14 | DEEPSEEK_API_KEY=your_deepseek_api_key_here
15 |
16 | # Google AI (Gemini/Vertex)
17 | GOOGLE_API_KEY=your_google_api_key_here
18 |
19 | # Optional: Default component to use if not specified
20 | DAPR_LLM_COMPONENT_DEFAULT=openai
21 |
--------------------------------------------------------------------------------
/examples/invoke-custom-data/invoke-caller.py:
--------------------------------------------------------------------------------
1 | import proto.response_pb2 as response_messages
2 |
3 | from dapr.clients import DaprClient
4 |
5 | with DaprClient() as d:
6 | # Create a typed message with content type and body
7 | resp = d.invoke_method(
8 | app_id='invoke-receiver',
9 | method_name='my_method',
10 | data=b'SOME_DATA',
11 | content_type='text/plain; charset=UTF-8',
12 | )
13 |
14 | res = response_messages.CustomResponse()
15 | resp.unpack(res)
16 |
17 | # Print Result
18 | print(res, flush=True)
19 |
--------------------------------------------------------------------------------
/examples/invoke-binding/components/kafka-binding.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: dapr.io/v1alpha1
2 | kind: Component
3 | metadata:
4 | name: kafkaBinding
5 | spec:
6 | type: bindings.kafka
7 | metadata:
8 | # Kafka broker connection setting
9 | - name: brokers
10 | value: localhost:9092
11 | # consumer configuration: topic and consumer group
12 | - name: topics
13 | value: sample
14 | - name: consumerGroup
15 | value: group1
16 | # publisher configuration: topic
17 | - name: publishTopic
18 | value: sample
19 | - name: authRequired
20 | value: "false"
21 |
--------------------------------------------------------------------------------
/docs/clients/clients.rst:
--------------------------------------------------------------------------------
1 | clients package
2 | ===============
3 |
4 | Subpackages
5 | -----------
6 |
7 | .. toctree::
8 | :maxdepth: 4
9 |
10 | clients.http
11 |
12 | Submodules
13 | ----------
14 |
15 |
16 | .. automodule:: clients.base
17 | :members:
18 | :undoc-members:
19 | :show-inheritance:
20 |
21 |
22 | .. automodule:: clients.exceptions
23 | :members:
24 | :undoc-members:
25 | :show-inheritance:
26 |
27 |
28 | Module contents
29 | ---------------
30 |
31 | .. automodule:: clients
32 | :members:
33 | :undoc-members:
34 | :show-inheritance:
35 |
--------------------------------------------------------------------------------
/docs/actor/actor.rst:
--------------------------------------------------------------------------------
1 | actor package
2 | =============
3 |
4 | Subpackages
5 | -----------
6 |
7 | .. toctree::
8 | :maxdepth: 4
9 |
10 | actor.client
11 | actor.runtime
12 |
13 | Submodules
14 | ----------
15 |
16 |
17 | .. automodule:: actor.actor_interface
18 | :members:
19 | :undoc-members:
20 | :show-inheritance:
21 |
22 |
23 | .. automodule:: actor.id
24 | :members:
25 | :undoc-members:
26 | :show-inheritance:
27 |
28 |
29 | Module contents
30 | ---------------
31 |
32 | .. automodule:: actor
33 | :members:
34 | :undoc-members:
35 | :show-inheritance:
36 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | updates:
3 | - package-ecosystem: "pip"
4 | directory: "/"
5 | schedule:
6 | interval: "daily"
7 | - package-ecosystem: "pip"
8 | directory: "/ext/dapr-ext-fastapi"
9 | schedule:
10 | interval: "daily"
11 | - package-ecosystem: "pip"
12 | directory: "/ext/dapr-ext-grpc"
13 | schedule:
14 | interval: "daily"
15 | - package-ecosystem: "pip"
16 | directory: "/ext/flask_dapr"
17 | schedule:
18 | interval: "daily"
19 | - package-ecosystem: "github-actions"
20 | directory: "/"
21 | schedule:
22 | interval: "daily"
--------------------------------------------------------------------------------
/docs/serializers/serializers.rst:
--------------------------------------------------------------------------------
1 | serializers package
2 | ===================
3 |
4 | Submodules
5 | ----------
6 |
7 |
8 | .. automodule:: serializers.base
9 | :members:
10 | :undoc-members:
11 | :show-inheritance:
12 |
13 |
14 | .. automodule:: serializers.json
15 | :members:
16 | :undoc-members:
17 | :show-inheritance:
18 |
19 |
20 | .. automodule:: serializers.util
21 | :members:
22 | :undoc-members:
23 | :show-inheritance:
24 |
25 |
26 | Module contents
27 | ---------------
28 |
29 | .. automodule:: serializers
30 | :members:
31 | :undoc-members:
32 | :show-inheritance:
33 |
--------------------------------------------------------------------------------
/docs/clients/clients.grpc.rst:
--------------------------------------------------------------------------------
1 | clients.grpc package
2 | ====================
3 |
4 | Submodules
5 | ----------
6 |
7 |
8 | .. automodule:: clients.grpc.client
9 | :members:
10 | :undoc-members:
11 | :show-inheritance:
12 |
13 |
14 | .. automodule:: clients.grpc.interceptors
15 | :members:
16 | :undoc-members:
17 | :show-inheritance:
18 |
19 |
20 | .. automodule:: clients.grpc.subscription
21 | :members:
22 | :undoc-members:
23 | :show-inheritance:
24 |
25 | Module contents
26 | ---------------
27 |
28 | .. automodule:: clients.grpc
29 | :members:
30 | :undoc-members:
31 | :show-inheritance:
32 |
--------------------------------------------------------------------------------
/dev-requirements.txt:
--------------------------------------------------------------------------------
1 | mypy>=1.2.0
2 | mypy-extensions>=0.4.3
3 | mypy-protobuf>=2.9
4 | tox>=4.3.0
5 | coverage>=5.3
6 | wheel
7 | # used in unit test only
8 | opentelemetry-sdk
9 | opentelemetry-instrumentation-grpc
10 | httpx>=0.24
11 | pyOpenSSL>=23.2.0
12 | # needed for type checking
13 | Flask>=1.1
14 | # needed for auto fix
15 | ruff===0.14.1
16 | # needed for dapr-ext-workflow
17 | durabletask-dapr >= 0.2.0a9
18 | # needed for .env file loading in examples
19 | python-dotenv>=1.0.0
20 | # needed for enhanced schema generation from function features
21 | pydantic>=2.0.0
22 | # needed for yaml file generation in examples
23 | PyYAML>=6.0.2
24 |
--------------------------------------------------------------------------------
/pyproject.toml:
--------------------------------------------------------------------------------
1 | [tool.ruff]
2 | target-version = "py310"
3 | line-length = 100
4 | fix = true
5 | extend-exclude = [".github", "dapr/proto"]
6 |
7 | [tool.ruff.lint]
8 | select = [
9 | "I", # isort
10 | "W", # pycodestyle warnings
11 | "F", # pyflakes
12 | "E", # pycodestyle errors
13 |
14 | # TODO: Add those back progressively as we fix the issues
15 | # "C", # flake8-comprehensions
16 | # "B", # flake8-bugbear
17 | # "UP", # pyupgrade
18 | ]
19 |
20 | # TODO: Add those back progressively as we fix the issues
21 | ignore = ["E501","E203", "E712", "E722", "E713"]
22 |
23 | [tool.ruff.format]
24 | quote-style = 'single'
25 |
--------------------------------------------------------------------------------
/docs/index.rst:
--------------------------------------------------------------------------------
1 | .. dapr-python-sdk documentation master file, created by
2 | sphinx-quickstart on Mon May 25 22:52:51 2020.
3 | You can adapt this file completely to your liking, but it should at least
4 | contain the root `toctree` directive.
5 |
6 | ============================
7 | Welcome to Dapr-Python-Sdk
8 | ============================
9 | .. toctree::
10 | :maxdepth: 4
11 | :caption: Contents:
12 |
13 | actor/modules
14 | client/modules
15 | proto/modules
16 | serializers/modules
17 |
18 |
19 | Indices and tables
20 | ==================
21 |
22 | * :ref:`genindex`
23 | * :ref:`modindex`
24 | * :ref:`search`
25 |
--------------------------------------------------------------------------------
/tests/actor/__init__.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | """
4 | Copyright 2021 The Dapr Authors
5 | Licensed under the Apache License, Version 2.0 (the "License");
6 | you may not use this file except in compliance with the License.
7 | You may obtain a copy of the License at
8 | http://www.apache.org/licenses/LICENSE-2.0
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 | """
15 |
--------------------------------------------------------------------------------
/tests/clients/__init__.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | """
4 | Copyright 2021 The Dapr Authors
5 | Licensed under the Apache License, Version 2.0 (the "License");
6 | you may not use this file except in compliance with the License.
7 | You may obtain a copy of the License at
8 | http://www.apache.org/licenses/LICENSE-2.0
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 | """
15 |
--------------------------------------------------------------------------------
/dapr/actor/client/__init__.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | """
4 | Copyright 2023 The Dapr Authors
5 | Licensed under the Apache License, Version 2.0 (the "License");
6 | you may not use this file except in compliance with the License.
7 | You may obtain a copy of the License at
8 | http://www.apache.org/licenses/LICENSE-2.0
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 | """
15 |
--------------------------------------------------------------------------------
/dapr/actor/runtime/__init__.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | """
4 | Copyright 2023 The Dapr Authors
5 | Licensed under the Apache License, Version 2.0 (the "License");
6 | you may not use this file except in compliance with the License.
7 | You may obtain a copy of the License at
8 | http://www.apache.org/licenses/LICENSE-2.0
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 | """
15 |
--------------------------------------------------------------------------------
/dapr/clients/grpc/__init__.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | """
4 | Copyright 2023 The Dapr Authors
5 | Licensed under the Apache License, Version 2.0 (the "License");
6 | you may not use this file except in compliance with the License.
7 | You may obtain a copy of the License at
8 | http://www.apache.org/licenses/LICENSE-2.0
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 | """
15 |
--------------------------------------------------------------------------------
/dapr/clients/http/__init__.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | """
4 | Copyright 2023 The Dapr Authors
5 | Licensed under the Apache License, Version 2.0 (the "License");
6 | you may not use this file except in compliance with the License.
7 | You may obtain a copy of the License at
8 | http://www.apache.org/licenses/LICENSE-2.0
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 | """
15 |
--------------------------------------------------------------------------------
/dapr/proto/common/__init__.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | """
4 | Copyright 2023 The Dapr Authors
5 | Licensed under the Apache License, Version 2.0 (the "License");
6 | you may not use this file except in compliance with the License.
7 | You may obtain a copy of the License at
8 | http://www.apache.org/licenses/LICENSE-2.0
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 | """
15 |
--------------------------------------------------------------------------------
/dapr/proto/runtime/__init__.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | """
4 | Copyright 2023 The Dapr Authors
5 | Licensed under the Apache License, Version 2.0 (the "License");
6 | you may not use this file except in compliance with the License.
7 | You may obtain a copy of the License at
8 | http://www.apache.org/licenses/LICENSE-2.0
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 | """
15 |
--------------------------------------------------------------------------------
/examples/invoke-simple/invoke-caller.py:
--------------------------------------------------------------------------------
1 | import json
2 | import time
3 |
4 | from dapr.clients import DaprClient
5 |
6 | with DaprClient() as d:
7 | req_data = {'id': 1, 'message': 'hello world'}
8 |
9 | while True:
10 | # Create a typed message with content type and body
11 | resp = d.invoke_method(
12 | 'invoke-receiver',
13 | 'my-method',
14 | data=json.dumps(req_data),
15 | )
16 |
17 | # Print the response
18 | print(resp.content_type, flush=True)
19 | print(resp.text(), flush=True)
20 | print(str(resp.status_code), flush=True)
21 |
22 | time.sleep(2)
23 |
--------------------------------------------------------------------------------
/tests/serializers/__init__.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | """
4 | Copyright 2021 The Dapr Authors
5 | Licensed under the Apache License, Version 2.0 (the "License");
6 | you may not use this file except in compliance with the License.
7 | You may obtain a copy of the License at
8 | http://www.apache.org/licenses/LICENSE-2.0
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 | """
15 |
--------------------------------------------------------------------------------
/dapr/aio/clients/grpc/__init__.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | """
4 | Copyright 2023 The Dapr Authors
5 | Licensed under the Apache License, Version 2.0 (the "License");
6 | you may not use this file except in compliance with the License.
7 | You may obtain a copy of the License at
8 | http://www.apache.org/licenses/LICENSE-2.0
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 | """
15 |
--------------------------------------------------------------------------------
/dapr/proto/common/v1/__init__.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | """
4 | Copyright 2023 The Dapr Authors
5 | Licensed under the Apache License, Version 2.0 (the "License");
6 | you may not use this file except in compliance with the License.
7 | You may obtain a copy of the License at
8 | http://www.apache.org/licenses/LICENSE-2.0
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 | """
15 |
--------------------------------------------------------------------------------
/dapr/proto/runtime/v1/__init__.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | """
4 | Copyright 2023 The Dapr Authors
5 | Licensed under the Apache License, Version 2.0 (the "License");
6 | you may not use this file except in compliance with the License.
7 | You may obtain a copy of the License at
8 | http://www.apache.org/licenses/LICENSE-2.0
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 | """
15 |
--------------------------------------------------------------------------------
/ext/dapr-ext-langgraph/tests/__init__.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | """
4 | Copyright 2025 The Dapr Authors
5 | Licensed under the Apache License, Version 2.0 (the "License");
6 | you may not use this file except in compliance with the License.
7 | You may obtain a copy of the License at
8 | http://www.apache.org/licenses/LICENSE-2.0
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 | """
15 |
--------------------------------------------------------------------------------
/ext/dapr-ext-workflow/tests/__init__.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | """
4 | Copyright 2023 The Dapr Authors
5 | Licensed under the Apache License, Version 2.0 (the "License");
6 | you may not use this file except in compliance with the License.
7 | You may obtain a copy of the License at
8 | http://www.apache.org/licenses/LICENSE-2.0
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 | """
15 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Python Dapr Client SDK Feature Request (not workflow)
3 | about: Create a Feature Request for python-sdk (not dapr-ext-workflow)
4 | title: '[FEATURE REQUEST] '
5 | labels: kind/enhancement
6 | assignees: ''
7 |
8 | ---
9 | ## Describe the feature
10 |
11 | ## Release Note
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 | RELEASE NOTE:
20 |
--------------------------------------------------------------------------------
/dapr/version/version.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | """
4 | Copyright 2023 The Dapr Authors
5 | Licensed under the Apache License, Version 2.0 (the "License");
6 | you may not use this file except in compliance with the License.
7 | You may obtain a copy of the License at
8 | http://www.apache.org/licenses/LICENSE-2.0
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 | """
15 |
16 | __version__ = '1.16.0.dev'
17 |
--------------------------------------------------------------------------------
/ext/flask_dapr/flask_dapr/version.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | """
4 | Copyright 2023 The Dapr Authors
5 | Licensed under the Apache License, Version 2.0 (the "License");
6 | you may not use this file except in compliance with the License.
7 | You may obtain a copy of the License at
8 | http://www.apache.org/licenses/LICENSE-2.0
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 | """
15 |
16 | __version__ = '1.16.0.dev'
17 |
--------------------------------------------------------------------------------
/ext/dapr-ext-grpc/dapr/ext/grpc/version.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | """
4 | Copyright 2023 The Dapr Authors
5 | Licensed under the Apache License, Version 2.0 (the "License");
6 | you may not use this file except in compliance with the License.
7 | You may obtain a copy of the License at
8 | http://www.apache.org/licenses/LICENSE-2.0
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 | """
15 |
16 | __version__ = '1.16.0.dev'
17 |
--------------------------------------------------------------------------------
/docs/Makefile:
--------------------------------------------------------------------------------
1 | # Minimal makefile for Sphinx documentation
2 | #
3 |
4 | # You can set these variables from the command line, and also
5 | # from the environment for the first two.
6 | SPHINXOPTS ?=
7 | SPHINXBUILD ?= sphinx-build
8 | SOURCEDIR = .
9 | BUILDDIR = _build
10 |
11 | # Put it first so that "make" without argument is like "make help".
12 | help:
13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
14 |
15 | .PHONY: help Makefile
16 |
17 | # Catch-all target: route all unknown targets to Sphinx using the new
18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
19 | %: Makefile
20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
21 |
--------------------------------------------------------------------------------
/ext/dapr-ext-fastapi/dapr/ext/fastapi/version.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | """
4 | Copyright 2023 The Dapr Authors
5 | Licensed under the Apache License, Version 2.0 (the "License");
6 | you may not use this file except in compliance with the License.
7 | You may obtain a copy of the License at
8 | http://www.apache.org/licenses/LICENSE-2.0
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 | """
15 |
16 | __version__ = '1.16.0.dev'
17 |
--------------------------------------------------------------------------------
/ext/dapr-ext-langgraph/dapr/ext/langgraph/version.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | """
4 | Copyright 2025 The Dapr Authors
5 | Licensed under the Apache License, Version 2.0 (the "License");
6 | you may not use this file except in compliance with the License.
7 | You may obtain a copy of the License at
8 | http://www.apache.org/licenses/LICENSE-2.0
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 | """
15 |
16 | __version__ = '1.16.0.dev'
17 |
--------------------------------------------------------------------------------
/ext/dapr-ext-workflow/dapr/ext/workflow/version.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | """
4 | Copyright 2023 The Dapr Authors
5 | Licensed under the Apache License, Version 2.0 (the "License");
6 | you may not use this file except in compliance with the License.
7 | You may obtain a copy of the License at
8 | http://www.apache.org/licenses/LICENSE-2.0
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 | """
15 |
16 | __version__ = '1.16.0.dev'
17 |
--------------------------------------------------------------------------------
/examples/grpc_proxying/invoke-caller.py:
--------------------------------------------------------------------------------
1 | import asyncio
2 | import logging
3 |
4 | import grpc
5 | import helloworld_service_pb2_grpc
6 | from helloworld_service_pb2 import HelloRequest
7 |
8 |
9 | async def run() -> None:
10 | async with grpc.aio.insecure_channel('127.0.0.1:50007') as channel:
11 | metadata = (('dapr-app-id', 'invoke-receiver'),)
12 | stub = helloworld_service_pb2_grpc.HelloWorldServiceStub(channel)
13 | response = await stub.SayHello(request=HelloRequest(name='you'), metadata=metadata)
14 | print('Greeter client received: ' + response.message)
15 |
16 |
17 | if __name__ == '__main__':
18 | print('I am in main')
19 | logging.basicConfig()
20 | asyncio.run(run())
21 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/workflow_feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: WORKFLOW SDK Feature Request
3 | about: Create a Feature Request for dapr-ext-workflow
4 | title: '[WORKFLOW SDK FEATURE REQUEST] '
5 | labels: ["kind/enhancement","dapr-ext-workflow"]
6 | assignees:
7 | - cgillum
8 | - DeepanshuA
9 |
10 | ---
11 | ## Describe the WORKFLOW SDK feature
12 |
13 | ## Release Note
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 | RELEASE NOTE:
22 |
--------------------------------------------------------------------------------
/dapr/proto/README.md:
--------------------------------------------------------------------------------
1 | ## Generating gRPC interface and Protobuf
2 |
3 | As a good practice create a python virtual environment:
4 |
5 | ```sh
6 | python3 -m venv
7 | source /bin/activate
8 | ```
9 |
10 | ### Linux and MacOS
11 |
12 | Run the following commands:
13 |
14 | ```sh
15 | pip3 install -r tools/requirements.txt
16 | export DAPR_BRANCH=release-1.16 # Optional, defaults to master
17 | ./tools/regen_grpcclient.sh
18 | ```
19 |
20 | > Note: To use the newly generated protobuf stubs and gRPC interface replace `daprd` with `edge` version of `daprd` built from master branch. Refer [this](https://github.com/dapr/dapr/blob/master/docs/development/developing-dapr.md#build-the-dapr-binaries) for instructions on how to build `daprd` from master.
21 |
--------------------------------------------------------------------------------
/examples/state_store_query/query.json:
--------------------------------------------------------------------------------
1 | {
2 | "filter": {
3 | "OR": [
4 | {
5 | "EQ": { "person.org": "Dev Ops" }
6 | },
7 | {
8 | "AND": [
9 | {
10 | "EQ": { "person.org": "Finance" }
11 | },
12 | {
13 | "IN": { "state": [ "CA", "WA" ] }
14 | }
15 | ]
16 | }
17 | ]
18 | },
19 | "sort": [
20 | {
21 | "key": "state",
22 | "order": "DESC"
23 | },
24 | {
25 | "key": "person.id"
26 | }
27 | ],
28 | "page": {
29 | "limit": 3
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/ext/flask_dapr/flask_dapr/__init__.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | """
4 | Copyright 2023 The Dapr Authors
5 | Licensed under the Apache License, Version 2.0 (the "License");
6 | you may not use this file except in compliance with the License.
7 | You may obtain a copy of the License at
8 | http://www.apache.org/licenses/LICENSE-2.0
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 | """
15 |
16 | from .actor import DaprActor
17 | from .app import DaprApp
18 |
19 | __all__ = ['DaprActor', 'DaprApp']
20 |
--------------------------------------------------------------------------------
/examples/state_store_query/query-token.json:
--------------------------------------------------------------------------------
1 | {
2 | "filter": {
3 | "OR": [
4 | {
5 | "EQ": { "person.org": "Dev Ops" }
6 | },
7 | {
8 | "AND": [
9 | {
10 | "EQ": { "person.org": "Finance" }
11 | },
12 | {
13 | "IN": { "state": [ "CA", "WA" ] }
14 | }
15 | ]
16 | }
17 | ]
18 | },
19 | "sort": [
20 | {
21 | "key": "state",
22 | "order": "DESC"
23 | },
24 | {
25 | "key": "person.id"
26 | }
27 | ],
28 | "page": {
29 | "limit": 3,
30 | "token": "3"
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/ext/dapr-ext-fastapi/dapr/ext/fastapi/__init__.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | """
4 | Copyright 2023 The Dapr Authors
5 | Licensed under the Apache License, Version 2.0 (the "License");
6 | you may not use this file except in compliance with the License.
7 | You may obtain a copy of the License at
8 | http://www.apache.org/licenses/LICENSE-2.0
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 | """
15 |
16 | from .actor import DaprActor
17 | from .app import DaprApp
18 |
19 | __all__ = ['DaprActor', 'DaprApp']
20 |
--------------------------------------------------------------------------------
/docs/proto/proto.runtime.v1.rst:
--------------------------------------------------------------------------------
1 | proto.runtime.v1 package
2 | ========================
3 |
4 | Submodules
5 | ----------
6 |
7 |
8 | .. automodule:: proto.runtime.v1.appcallback_pb2
9 | :members:
10 | :undoc-members:
11 | :show-inheritance:
12 |
13 |
14 | .. automodule:: proto.runtime.v1.appcallback_pb2_grpc
15 | :members:
16 | :undoc-members:
17 | :show-inheritance:
18 |
19 |
20 | .. automodule:: proto.runtime.v1.dapr_pb2
21 | :members:
22 | :undoc-members:
23 | :show-inheritance:
24 |
25 |
26 | .. automodule:: proto.runtime.v1.dapr_pb2_grpc
27 | :members:
28 | :undoc-members:
29 | :show-inheritance:
30 |
31 | Module contents
32 | ---------------
33 |
34 | .. automodule:: proto.runtime.v1
35 | :members:
36 | :undoc-members:
37 | :show-inheritance:
38 |
--------------------------------------------------------------------------------
/ext/dapr-ext-workflow/dapr/ext/workflow/aio/__init__.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | """
4 | Copyright 2025 The Dapr Authors
5 | Licensed under the Apache License, Version 2.0 (the "License");
6 | you may not use this file except in compliance with the License.
7 | You may obtain a copy of the License at
8 | http://www.apache.org/licenses/LICENSE-2.0
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 | """
15 |
16 | from .dapr_workflow_client import DaprWorkflowClient
17 |
18 | __all__ = [
19 | 'DaprWorkflowClient',
20 | ]
21 |
--------------------------------------------------------------------------------
/examples/grpc_proxying/invoke-receiver.py:
--------------------------------------------------------------------------------
1 | import logging
2 |
3 | import grpc
4 | import helloworld_service_pb2_grpc
5 | from dapr.ext.grpc import App
6 | from helloworld_service_pb2 import HelloReply, HelloRequest
7 |
8 |
9 | class HelloWorldService(helloworld_service_pb2_grpc.HelloWorldService):
10 | def SayHello(self, request: HelloRequest, context: grpc.aio.ServicerContext) -> HelloReply:
11 | logging.info(request)
12 | return HelloReply(message='Hello, %s!' % request.name)
13 |
14 |
15 | app = App()
16 |
17 | if __name__ == '__main__':
18 | print('starting the HelloWorld Service')
19 | logging.basicConfig(level=logging.INFO)
20 | app.add_external_service(
21 | helloworld_service_pb2_grpc.add_HelloWorldServiceServicer_to_server, HelloWorldService()
22 | )
23 | app.run(50051)
24 |
--------------------------------------------------------------------------------
/examples/demo_actor/demo_actor/Dockerfile:
--------------------------------------------------------------------------------
1 | # Copyright 2021 The Dapr Authors
2 | # Licensed under the Apache License, Version 2.0 (the "License");
3 | # you may not use this file except in compliance with the License.
4 | # You may obtain a copy of the License at
5 | # http://www.apache.org/licenses/LICENSE-2.0
6 | # Unless required by applicable law or agreed to in writing, software
7 | # distributed under the License is distributed on an "AS IS" BASIS,
8 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 | # See the License for the specific language governing permissions and
10 | # limitations under the License.
11 |
12 | FROM python:3.9-slim-buster
13 |
14 | WORKDIR /app
15 | COPY . .
16 |
17 | RUN pip install -r requirements.txt
18 |
19 | ENTRYPOINT ["python"]
20 | CMD ["demo_actor_service.py"]
21 |
--------------------------------------------------------------------------------
/dapr/serializers/__init__.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | """
4 | Copyright 2023 The Dapr Authors
5 | Licensed under the Apache License, Version 2.0 (the "License");
6 | you may not use this file except in compliance with the License.
7 | You may obtain a copy of the License at
8 | http://www.apache.org/licenses/LICENSE-2.0
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 | """
15 |
16 | from dapr.serializers.base import Serializer
17 | from dapr.serializers.json import DefaultJSONSerializer
18 |
19 | __all__ = ['Serializer', 'DefaultJSONSerializer']
20 |
--------------------------------------------------------------------------------
/tests/clients/test_http_helpers.py:
--------------------------------------------------------------------------------
1 | import unittest
2 | from unittest.mock import patch
3 |
4 | from dapr.clients.http.helpers import get_api_url
5 | from dapr.conf import settings
6 |
7 |
8 | class DaprHttpClientHelpersTests(unittest.TestCase):
9 | def test_get_api_url_default(self, dapr=None):
10 | self.assertEqual(
11 | 'http://{}:{}/{}'.format(
12 | settings.DAPR_RUNTIME_HOST, settings.DAPR_HTTP_PORT, settings.DAPR_API_VERSION
13 | ),
14 | get_api_url(),
15 | )
16 |
17 | @patch.object(settings, 'DAPR_HTTP_ENDPOINT', 'https://domain1.com:5000')
18 | def test_get_api_url_endpoint_as_env_variable(self):
19 | self.assertEqual(
20 | 'https://domain1.com:5000/{}'.format(settings.DAPR_API_VERSION),
21 | get_api_url(),
22 | )
23 |
--------------------------------------------------------------------------------
/dapr/actor/runtime/reentrancy_context.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | """
4 | Copyright 2023 The Dapr Authors
5 | Licensed under the Apache License, Version 2.0 (the "License");
6 | you may not use this file except in compliance with the License.
7 | You may obtain a copy of the License at
8 | http://www.apache.org/licenses/LICENSE-2.0
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 | """
15 |
16 | from contextvars import ContextVar
17 | from typing import Optional
18 |
19 | reentrancy_ctx: ContextVar[Optional[str]] = ContextVar('reentrancy_ctx', default=None)
20 |
--------------------------------------------------------------------------------
/ext/dapr-ext-grpc/tests/test_health_servicer.py:
--------------------------------------------------------------------------------
1 | import unittest
2 | from unittest.mock import MagicMock
3 |
4 | from dapr.ext.grpc._health_servicer import _HealthCheckServicer
5 |
6 |
7 | class OnInvokeTests(unittest.TestCase):
8 | def setUp(self):
9 | self._health_servicer = _HealthCheckServicer()
10 |
11 | def test_healthcheck_cb_called(self):
12 | health_cb = MagicMock()
13 | self._health_servicer.register_health_check(health_cb)
14 | self._health_servicer.HealthCheck(None, MagicMock())
15 | health_cb.assert_called_once()
16 |
17 | def test_no_healthcheck_cb(self):
18 | with self.assertRaises(NotImplementedError) as exception_context:
19 | self._health_servicer.HealthCheck(None, MagicMock())
20 | self.assertIn('Method not implemented!', exception_context.exception.args[0])
21 |
--------------------------------------------------------------------------------
/ext/dapr-ext-langgraph/dapr/ext/langgraph/__init__.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | """
4 | Copyright 2025 The Dapr Authors
5 | Licensed under the Apache License, Version 2.0 (the "License");
6 | you may not use this file except in compliance with the License.
7 | You may obtain a copy of the License at
8 | http://www.apache.org/licenses/LICENSE-2.0
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 | """
15 |
16 | # Import your main classes here
17 | from dapr.ext.langgraph.dapr_checkpointer import DaprCheckpointer
18 |
19 | __all__ = [
20 | 'DaprCheckpointer',
21 | ]
22 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/config.yml:
--------------------------------------------------------------------------------
1 | blank_issues_enabled: false
2 | contact_links:
3 | - name: Dapr Discord Python SDK channel
4 | url: https://discord.com/channels/778680217417809931/782286950983663617
5 | about: Please use this channel for general Dapr Python SDK questions.
6 | - name: Dapr Discord Workflow SDK channel
7 | url: https://discord.com/channels/778680217417809931/1075836407156850698
8 | about: Please use this channel for general Dapr Workflow questions.
9 | - name: Dapr Community Support (Discord Invitation, Community meetings, etc.)
10 | url: https://github.com/dapr/community
11 | about: More information about the Dapr community and how to get involved.
12 | - name: Reporting security issues
13 | url: https://docs.dapr.io/operations/support/support-security-issues/
14 | about: Please report security vulnerabilities here.
--------------------------------------------------------------------------------
/examples/invoke-http/invoke-receiver.py:
--------------------------------------------------------------------------------
1 | # from dapr.ext.grpc import App, InvokeMethodRequest, InvokeMethodResponse
2 | import json
3 |
4 | from flask import Flask, request
5 |
6 | app = Flask(__name__)
7 |
8 |
9 | @app.route('/my-method', methods=['POST'])
10 | def getOrder():
11 | data = request.json
12 | print('Order received : ' + json.dumps(data), flush=True)
13 | return json.dumps({'success': True}), 200, {'ContentType': 'application/json'}
14 |
15 |
16 | @app.route('/my-method-err', methods=['POST'])
17 | def getOrderErr():
18 | data = request.json
19 | print('Order error : ' + json.dumps(data), flush=True)
20 | resp = {'message': 'error occurred', 'errorCode': 'MY_CODE'}
21 | return json.dumps(resp), 503, {'ContentType': 'application/json'}
22 |
23 |
24 | print('Starting Flask app on port 8088...', flush=True)
25 | app.run(port=8088)
26 |
--------------------------------------------------------------------------------
/examples/state_store_query/state_store_query.py:
--------------------------------------------------------------------------------
1 | """
2 | dapr run python3 state_store_query.py
3 | """
4 |
5 | import json
6 |
7 | from dapr.clients import DaprClient
8 |
9 | with DaprClient() as d:
10 | store_name = 'statestore'
11 |
12 | # Query the state store
13 |
14 | query = open('query.json', 'r').read()
15 | res = d.query_state(store_name=store_name, query=query)
16 | for r in res.results:
17 | print(r.key, json.dumps(json.loads(str(r.value, 'UTF-8')), sort_keys=True))
18 | print('Token:', res.token)
19 |
20 | # Get more results using a pagination token
21 |
22 | query = open('query-token.json', 'r').read()
23 | res = d.query_state(store_name=store_name, query=query)
24 | for r in res.results:
25 | print(r.key, json.dumps(json.loads(str(r.value, 'UTF-8')), sort_keys=True))
26 | print('Token:', res.token)
27 |
--------------------------------------------------------------------------------
/dapr/clients/http/conf.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | """
4 | Copyright 2023 The Dapr Authors
5 | Licensed under the Apache License, Version 2.0 (the "License");
6 | you may not use this file except in compliance with the License.
7 | You may obtain a copy of the License at
8 | http://www.apache.org/licenses/LICENSE-2.0
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 | """
15 |
16 | from dapr.version import __version__
17 |
18 | CONTENT_TYPE_HEADER = 'content-type'
19 | DAPR_API_TOKEN_HEADER = 'dapr-api-token'
20 | USER_AGENT_HEADER = 'User-Agent'
21 | DAPR_USER_AGENT = f'dapr-sdk-python/{__version__}'
22 |
--------------------------------------------------------------------------------
/ext/flask_dapr/README.rst:
--------------------------------------------------------------------------------
1 | Dapr flask extension
2 | ====================
3 |
4 | |pypi|
5 |
6 | .. |pypi| image:: https://badge.fury.io/py/flask-dapr.svg
7 | :target: https://pypi.org/project/flask-dapr/
8 |
9 | This flask extension is used to:
10 | - run the actor service
11 | - subscribe to PubSub events
12 |
13 | Installation
14 | ------------
15 |
16 | ::
17 |
18 | pip install flask-dapr
19 |
20 | PubSub Events
21 | -------------
22 |
23 | ```python
24 | from flask import Flask, request
25 | from flask_dapr import DaprApp
26 |
27 | app = Flask('myapp')
28 | dapr_app = DaprApp(app)
29 | @dapr_app.subscribe(pubsub='pubsub', topic='some_topic', route='/some_endpoint')
30 | def my_event_handler():
31 | # request.data contains pubsub event
32 | pass
33 | ```
34 |
35 | References
36 | ----------
37 |
38 | * `Dapr `_
39 | * `Dapr Python-SDK `_
40 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Python Dapr Client SDK Bug report (not workflow SDK)
3 | about: Report a bug in python-sdk (not dapr-ext-workflow)
4 | title: '[BUG] '
5 | labels: kind/bug
6 | assignees: ''
7 |
8 | ---
9 | ## Expected Behavior
10 |
11 |
12 |
13 |
14 | ## Actual Behavior
15 |
16 |
17 |
18 |
19 | ## Steps to Reproduce the Problem
20 |
21 |
22 |
23 | ## Release Note
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 | RELEASE NOTE:
32 |
--------------------------------------------------------------------------------
/docs/make.bat:
--------------------------------------------------------------------------------
1 | @ECHO OFF
2 |
3 | pushd %~dp0
4 |
5 | REM Command file for Sphinx documentation
6 |
7 | if "%SPHINXBUILD%" == "" (
8 | set SPHINXBUILD=sphinx-build
9 | )
10 | set SOURCEDIR=.
11 | set BUILDDIR=_build
12 |
13 | if "%1" == "" goto help
14 |
15 | %SPHINXBUILD% >NUL 2>NUL
16 | if errorlevel 9009 (
17 | echo.
18 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
19 | echo.installed, then set the SPHINXBUILD environment variable to point
20 | echo.to the full path of the 'sphinx-build' executable. Alternatively you
21 | echo.may add the Sphinx directory to PATH.
22 | echo.
23 | echo.If you don't have Sphinx installed, grab it from
24 | echo.http://sphinx-doc.org/
25 | exit /b 1
26 | )
27 |
28 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
29 | goto end
30 |
31 | :help
32 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
33 |
34 | :end
35 | popd
36 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/workflow_bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: WORKFLOW SDK Bug report
3 | about: Report a bug in dapr-ext-workflow
4 | title: '[WORKFLOW SDK BUG] '
5 | labels: ["kind/enhancement","dapr-ext-workflow"]
6 | assignees:
7 | - cgillum
8 | - DeepanshuA
9 |
10 | ---
11 | ## Expected Behavior
12 |
13 |
14 |
15 |
16 | ## Actual Behavior
17 |
18 |
19 |
20 |
21 | ## Steps to Reproduce the Problem
22 |
23 |
24 |
25 | ## Release Note
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 | RELEASE NOTE:
34 |
--------------------------------------------------------------------------------
/dapr/clients/http/helpers.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | """
4 | Copyright 2023 The Dapr Authors
5 | Licensed under the Apache License, Version 2.0 (the "License");
6 | you may not use this file except in compliance with the License.
7 | You may obtain a copy of the License at
8 | http://www.apache.org/licenses/LICENSE-2.0
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 | """
15 |
16 | from dapr.conf import settings
17 |
18 |
19 | def get_api_url() -> str:
20 | if settings.DAPR_HTTP_ENDPOINT:
21 | return '{}/{}'.format(settings.DAPR_HTTP_ENDPOINT, settings.DAPR_API_VERSION)
22 |
23 | return 'http://{}:{}/{}'.format(
24 | settings.DAPR_RUNTIME_HOST, settings.DAPR_HTTP_PORT, settings.DAPR_API_VERSION
25 | )
26 |
--------------------------------------------------------------------------------
/dapr/clients/_constants.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | """
4 | Copyright 2025 The Dapr Authors
5 | Licensed under the Apache License, Version 2.0 (the "License");
6 | you may not use this file except in compliance with the License.
7 | You may obtain a copy of the License at
8 | http://www.apache.org/licenses/LICENSE-2.0
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 | """
15 |
16 | """
17 | Internal constants for the Dapr clients package.
18 |
19 | This module contains shared constants that can be imported by various
20 | client modules without creating circular dependencies.
21 | """
22 |
23 | # Encoding and content type constants
24 | DEFAULT_ENCODING = 'utf-8'
25 | DEFAULT_JSON_CONTENT_TYPE = f'application/json; charset={DEFAULT_ENCODING}'
26 |
--------------------------------------------------------------------------------
/ext/flask_dapr/setup.cfg:
--------------------------------------------------------------------------------
1 | [metadata]
2 | url = https://dapr.io/
3 | author = Dapr Authors
4 | author_email = daprweb@microsoft.com
5 | license = Apache
6 | license_file = LICENSE
7 | classifiers =
8 | Development Status :: 5 - Production/Stable
9 | Intended Audience :: Developers
10 | License :: OSI Approved :: Apache Software License
11 | Operating System :: OS Independent
12 | Programming Language :: Python
13 | Programming Language :: Python :: 3.9
14 | Programming Language :: Python :: 3.10
15 | Programming Language :: Python :: 3.11
16 | Programming Language :: Python :: 3.12
17 | Programming Language :: Python :: 3.13
18 | project_urls =
19 | Documentation = https://github.com/dapr/docs
20 | Source = https://github.com/dapr/python-sdk
21 |
22 | [options]
23 | python_requires = >=3.9
24 | packages = find:
25 | include_package_data = true
26 | zip_safe = false
27 | install_requires =
28 | Flask >= 1.1
29 | dapr >= 1.16.0.dev
30 |
31 | [options.package_data]
32 | flask_dapr =
33 | py.typed
34 |
--------------------------------------------------------------------------------
/ext/dapr-ext-grpc/setup.cfg:
--------------------------------------------------------------------------------
1 | [metadata]
2 | url = https://dapr.io/
3 | author = Dapr Authors
4 | author_email = daprweb@microsoft.com
5 | license = Apache
6 | license_file = LICENSE
7 | classifiers =
8 | Development Status :: 5 - Production/Stable
9 | Intended Audience :: Developers
10 | License :: OSI Approved :: Apache Software License
11 | Operating System :: OS Independent
12 | Programming Language :: Python
13 | Programming Language :: Python :: 3.9
14 | Programming Language :: Python :: 3.10
15 | Programming Language :: Python :: 3.11
16 | Programming Language :: Python :: 3.12
17 | Programming Language :: Python :: 3.13
18 | project_urls =
19 | Documentation = https://github.com/dapr/docs
20 | Source = https://github.com/dapr/python-sdk
21 |
22 | [options]
23 | python_requires = >=3.9
24 | packages = find_namespace:
25 | include_package_data = True
26 | install_requires =
27 | dapr >= 1.16.0.dev
28 | cloudevents >= 1.0.0
29 |
30 | [options.packages.find]
31 | include =
32 | dapr.*
33 |
34 | exclude =
35 | tests
36 |
37 | [options.package_data]
38 | dapr.ext.grpc =
39 | py.typed
--------------------------------------------------------------------------------
/.devcontainer/devcontainer.json:
--------------------------------------------------------------------------------
1 | // For format details, see https://aka.ms/vscode-remote/devcontainer.json.
2 | {
3 | "name": "Dapr - Python SDK",
4 | "context": "..",
5 | "dockerFile": "Dockerfile",
6 |
7 | // Set *default* container specific settings.json values on container create.
8 | "settings": {
9 | "terminal.integrated.shell.linux": "/bin/bash",
10 | "python.pythonPath": "/usr/local/bin/python",
11 | "python.linting.enabled": true,
12 | "python.linting.mypyEnabled": true,
13 | },
14 |
15 | // Add the IDs of extensions you want installed when the container is created.
16 | "extensions": [
17 | "ms-python.python",
18 | "ms-azuretools.vscode-dapr"
19 | ],
20 |
21 | "mounts": [
22 | "source=/var/run/docker.sock,target=/var/run/docker.sock,type=bind",
23 | ],
24 |
25 | "postCreateCommand": ".devcontainer/postCreateCommand.sh",
26 |
27 | // Use 'forwardPorts' to make a list of ports inside the container available locally.
28 | // "forwardPorts": [],
29 | // Uncomment to connect as a non-root user. See https://aka.ms/vscode-remote/containers/non-root.
30 | // "remoteUser": "vscode"
31 | }
32 |
--------------------------------------------------------------------------------
/ext/dapr-ext-workflow/setup.cfg:
--------------------------------------------------------------------------------
1 | [metadata]
2 | url = https://dapr.io/
3 | author = Dapr Authors
4 | author_email = daprweb@microsoft.com
5 | license = Apache
6 | license_file = LICENSE
7 | classifiers =
8 | Development Status :: 5 - Production/Stable
9 | Intended Audience :: Developers
10 | License :: OSI Approved :: Apache Software License
11 | Operating System :: OS Independent
12 | Programming Language :: Python
13 | Programming Language :: Python :: 3.9
14 | Programming Language :: Python :: 3.10
15 | Programming Language :: Python :: 3.11
16 | Programming Language :: Python :: 3.12
17 | Programming Language :: Python :: 3.13
18 | project_urls =
19 | Documentation = https://github.com/dapr/docs
20 | Source = https://github.com/dapr/python-sdk
21 |
22 | [options]
23 | python_requires = >=3.9
24 | packages = find_namespace:
25 | include_package_data = True
26 | install_requires =
27 | dapr >= 1.16.0.dev
28 | durabletask-dapr >= 0.2.0a12
29 |
30 | [options.packages.find]
31 | include =
32 | dapr.*
33 |
34 | exclude =
35 | tests
36 |
37 | [options.package_data]
38 | dapr.ext.workflow =
39 | py.typed
40 |
--------------------------------------------------------------------------------
/ext/dapr-ext-fastapi/setup.cfg:
--------------------------------------------------------------------------------
1 | [metadata]
2 | url = https://dapr.io/
3 | author = Dapr Authors
4 | author_email = daprweb@microsoft.com
5 | license = Apache
6 | license_file = LICENSE
7 | classifiers =
8 | Development Status :: 5 - Production/Stable
9 | Intended Audience :: Developers
10 | License :: OSI Approved :: Apache Software License
11 | Operating System :: OS Independent
12 | Programming Language :: Python
13 | Programming Language :: Python :: 3.9
14 | Programming Language :: Python :: 3.10
15 | Programming Language :: Python :: 3.11
16 | Programming Language :: Python :: 3.12
17 | Programming Language :: Python :: 3.13
18 | project_urls =
19 | Documentation = https://github.com/dapr/docs
20 | Source = https://github.com/dapr/python-sdk
21 |
22 | [options]
23 | python_requires = >=3.9
24 | packages = find_namespace:
25 | include_package_data = True
26 | install_requires =
27 | dapr >= 1.16.0.dev
28 | uvicorn >= 0.11.6
29 | fastapi >= 0.60.1
30 |
31 | [options.packages.find]
32 | include =
33 | dapr.*
34 |
35 | exclude =
36 | tests
37 |
38 | [options.package_data]
39 | dapr.ext.fastapi =
40 | py.typed
41 |
--------------------------------------------------------------------------------
/examples/invoke-binding/docker-compose-single-kafka.yml:
--------------------------------------------------------------------------------
1 | # ------------------------------------------------------------
2 | # Copyright 2021 The Dapr Authors
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | # http://www.apache.org/licenses/LICENSE-2.0
7 | # Unless required by applicable law or agreed to in writing, software
8 | # distributed under the License is distributed on an "AS IS" BASIS,
9 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10 | # See the License for the specific language governing permissions and
11 | # limitations under the License.
12 | # ------------------------------------------------------------
13 |
14 | version: '2'
15 | services:
16 | zookeeper:
17 | image: wurstmeister/zookeeper:latest
18 | ports:
19 | - "2181:2181"
20 | kafka:
21 | image: wurstmeister/kafka:latest
22 | ports:
23 | - "9092:9092"
24 | environment:
25 | KAFKA_ADVERTISED_HOST_NAME: 127.0.0.1
26 | KAFKA_CREATE_TOPICS: "sample:1:1"
27 | KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
28 |
--------------------------------------------------------------------------------
/dapr/actor/__init__.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | """
4 | Copyright 2023 The Dapr Authors
5 | Licensed under the Apache License, Version 2.0 (the "License");
6 | you may not use this file except in compliance with the License.
7 | You may obtain a copy of the License at
8 | http://www.apache.org/licenses/LICENSE-2.0
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 | """
15 |
16 | from dapr.actor.actor_interface import ActorInterface, actormethod
17 | from dapr.actor.client.proxy import ActorProxy, ActorProxyFactory
18 | from dapr.actor.id import ActorId
19 | from dapr.actor.runtime.actor import Actor
20 | from dapr.actor.runtime.remindable import Remindable
21 | from dapr.actor.runtime.runtime import ActorRuntime
22 |
23 | __all__ = [
24 | 'ActorInterface',
25 | 'ActorProxy',
26 | 'ActorProxyFactory',
27 | 'ActorId',
28 | 'Actor',
29 | 'ActorRuntime',
30 | 'Remindable',
31 | 'actormethod',
32 | ]
33 |
--------------------------------------------------------------------------------
/ext/dapr-ext-workflow/dapr/ext/workflow/util.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | """
4 | Copyright 2023 The Dapr Authors
5 | Licensed under the Apache License, Version 2.0 (the "License");
6 | you may not use this file except in compliance with the License.
7 | You may obtain a copy of the License at
8 | http://www.apache.org/licenses/LICENSE-2.0
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 | """
15 |
16 | from typing import Optional
17 |
18 | from dapr.conf import settings
19 |
20 |
21 | def getAddress(host: Optional[str] = None, port: Optional[str] = None) -> str:
22 | if not host and not port:
23 | address = settings.DAPR_GRPC_ENDPOINT or (
24 | f'{settings.DAPR_RUNTIME_HOST}:{settings.DAPR_GRPC_PORT}'
25 | )
26 | else:
27 | host = host or settings.DAPR_RUNTIME_HOST
28 | port = port or settings.DAPR_GRPC_PORT
29 | address = f'{host}:{port}'
30 |
31 | return address
32 |
--------------------------------------------------------------------------------
/dapr/serializers/base.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | """
4 | Copyright 2023 The Dapr Authors
5 | Licensed under the Apache License, Version 2.0 (the "License");
6 | you may not use this file except in compliance with the License.
7 | You may obtain a copy of the License at
8 | http://www.apache.org/licenses/LICENSE-2.0
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 | """
15 |
16 | from abc import ABC, abstractmethod
17 | from typing import Any, Callable, Optional, Type
18 |
19 |
20 | class Serializer(ABC):
21 | """Serializer base class."""
22 |
23 | @abstractmethod
24 | def serialize(
25 | self, obj: object, custom_hook: Optional[Callable[[object], bytes]] = None
26 | ) -> bytes: ...
27 |
28 | @abstractmethod
29 | def deserialize(
30 | self,
31 | data: bytes,
32 | data_type: Optional[Type] = object,
33 | custom_hook: Optional[Callable[[bytes], object]] = None,
34 | ) -> Any: ...
35 |
--------------------------------------------------------------------------------
/examples/invoke-http/invoke-caller.py:
--------------------------------------------------------------------------------
1 | import json
2 |
3 | from dapr.clients import DaprClient
4 | from dapr.clients.exceptions import DaprHttpError
5 |
6 | with DaprClient() as d:
7 | req_data = {'id': 1, 'message': 'hello world'}
8 |
9 | # First message: success
10 | # Create a typed message with content type and body
11 | resp1 = d.invoke_method(
12 | 'invoke-receiver',
13 | 'my-method',
14 | http_verb='POST',
15 | data=json.dumps(req_data),
16 | )
17 |
18 | # Print the response
19 | print(resp1.content_type, flush=True)
20 | print(resp1.text(), flush=True)
21 | print(str(resp1.status_code), flush=True)
22 |
23 | # Second message: error
24 | req_data = {'id': 2, 'message': 'hello world'}
25 | try:
26 | resp2 = d.invoke_method(
27 | 'invoke-receiver',
28 | 'my-method-err',
29 | http_verb='POST',
30 | data=json.dumps(req_data),
31 | )
32 | except DaprHttpError as e:
33 | print(e.message, flush=True)
34 | print(e.error_code, flush=True)
35 | print(e.raw_response_bytes, flush=True)
36 | print(str(e.status_code), flush=True)
37 | print(e.reason, flush=True)
38 |
--------------------------------------------------------------------------------
/ext/dapr-ext-langgraph/setup.cfg:
--------------------------------------------------------------------------------
1 | [metadata]
2 | url = https://dapr.io/
3 | author = Dapr Authors
4 | author_email = daprweb@microsoft.com
5 | license = Apache
6 | license_file = LICENSE
7 | classifiers =
8 | Development Status :: 5 - Production/Stable
9 | Intended Audience :: Developers
10 | License :: OSI Approved :: Apache Software License
11 | Operating System :: OS Independent
12 | Programming Language :: Python
13 | Programming Language :: Python :: 3.10
14 | Programming Language :: Python :: 3.11
15 | Programming Language :: Python :: 3.12
16 | Programming Language :: Python :: 3.13
17 | Programming Language :: Python :: 3.14
18 | project_urls =
19 | Documentation = https://github.com/dapr/docs
20 | Source = https://github.com/dapr/python-sdk
21 |
22 | [options]
23 | python_requires = >=3.10
24 | packages = find_namespace:
25 | include_package_data = True
26 | install_requires =
27 | dapr >= 1.16.1rc1
28 | langgraph >= 0.3.6
29 | langchain >= 0.1.17
30 | python-ulid >= 3.0.0
31 | msgpack-python >= 0.4.5
32 |
33 | [options.packages.find]
34 | include =
35 | dapr.*
36 |
37 | exclude =
38 | tests
39 |
40 | [options.package_data]
41 | dapr.ext.langgraph =
42 | py.typed
--------------------------------------------------------------------------------
/ext/dapr-ext-grpc/dapr/ext/grpc/_health_servicer.py:
--------------------------------------------------------------------------------
1 | from typing import Callable, Optional
2 |
3 | import grpc
4 | from dapr.proto import appcallback_service_v1
5 | from dapr.proto.runtime.v1.appcallback_pb2 import HealthCheckResponse
6 |
7 | HealthCheckCallable = Optional[Callable[[], None]]
8 |
9 |
10 | class _HealthCheckServicer(appcallback_service_v1.AppCallbackHealthCheckServicer):
11 | """The implementation of HealthCheck Server.
12 |
13 | :class:`App` provides useful decorators to register method, topic, input bindings.
14 | """
15 |
16 | def __init__(self):
17 | self._health_check_cb: Optional[HealthCheckCallable] = None
18 |
19 | def register_health_check(self, cb: HealthCheckCallable) -> None:
20 | if not cb:
21 | raise ValueError('health check callback must be defined')
22 | self._health_check_cb = cb
23 |
24 | def HealthCheck(self, request, context):
25 | """Health check."""
26 |
27 | if not self._health_check_cb:
28 | context.set_code(grpc.StatusCode.UNIMPLEMENTED) # type: ignore
29 | context.set_details('Method not implemented!')
30 | raise NotImplementedError('Method not implemented!')
31 | self._health_check_cb()
32 | return HealthCheckResponse()
33 |
--------------------------------------------------------------------------------
/setup.cfg:
--------------------------------------------------------------------------------
1 | [metadata]
2 | url = https://dapr.io/
3 | author = Dapr Authors
4 | author_email = dapr@dapr.io
5 | license = Apache
6 | license_file = LICENSE
7 | classifiers =
8 | Development Status :: 5 - Production/Stable
9 | Intended Audience :: Developers
10 | License :: OSI Approved :: Apache Software License
11 | Operating System :: OS Independent
12 | Programming Language :: Python
13 | Programming Language :: Python :: 3.9
14 | Programming Language :: Python :: 3.10
15 | Programming Language :: Python :: 3.11
16 | Programming Language :: Python :: 3.12
17 | Programming Language :: Python :: 3.13
18 | project_urls =
19 | Documentation = https://github.com/dapr/docs
20 | Source = https://github.com/dapr/python-sdk
21 |
22 | [options]
23 | python_requires = >=3.9
24 | packages = find_namespace:
25 | include_package_data = True
26 | zip_safe = False
27 | install_requires =
28 | protobuf >= 4.22
29 | grpcio >= 1.37.0
30 | grpcio-status>=1.37.0
31 | aiohttp >= 3.9.0b0
32 | python-dateutil >= 2.8.1
33 | typing-extensions>=4.4.0
34 |
35 | [options.packages.find]
36 | include =
37 | dapr
38 | dapr.*
39 | exclude =
40 | ext
41 | examples
42 | tests
43 |
44 | [options.package_data]
45 | dapr =
46 | py.typed
47 |
--------------------------------------------------------------------------------
/ext/dapr-ext-grpc/dapr/ext/grpc/__init__.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | """
4 | Copyright 2023 The Dapr Authors
5 | Licensed under the Apache License, Version 2.0 (the "License");
6 | you may not use this file except in compliance with the License.
7 | You may obtain a copy of the License at
8 | http://www.apache.org/licenses/LICENSE-2.0
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 | """
15 |
16 | from dapr.ext.grpc.app import App, Rule # type:ignore
17 |
18 | from dapr.clients.grpc._jobs import ConstantFailurePolicy, DropFailurePolicy, FailurePolicy, Job
19 | from dapr.clients.grpc._request import BindingRequest, InvokeMethodRequest, JobEvent
20 | from dapr.clients.grpc._response import InvokeMethodResponse, TopicEventResponse
21 |
22 | __all__ = [
23 | 'App',
24 | 'Rule',
25 | 'InvokeMethodRequest',
26 | 'InvokeMethodResponse',
27 | 'BindingRequest',
28 | 'TopicEventResponse',
29 | 'Job',
30 | 'JobEvent',
31 | 'FailurePolicy',
32 | 'DropFailurePolicy',
33 | 'ConstantFailurePolicy',
34 | ]
35 |
--------------------------------------------------------------------------------
/dapr/actor/runtime/_call_type.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | """
4 | Copyright 2023 The Dapr Authors
5 | Licensed under the Apache License, Version 2.0 (the "License");
6 | you may not use this file except in compliance with the License.
7 | You may obtain a copy of the License at
8 | http://www.apache.org/licenses/LICENSE-2.0
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 | """
15 |
16 | from enum import Enum
17 |
18 |
19 | class ActorCallType(Enum):
20 | """A enumeration that represents the call-type associated with the actor method.
21 | :class:`ActorMethodContext` includes :class:`ActorCallType` passing to
22 | :meth:`Actor._on_pre_actor_method` and :meth:`Actor._on_post_actor_method`
23 | """
24 |
25 | # Specifies that the method invoked is an actor interface method for a given client request.
26 | actor_interface_method = 0
27 | # Specifies that the method invoked is a timer callback method.
28 | timer_method = 1
29 | # Specifies that the method is when a reminder fires.
30 | reminder_method = 2
31 |
--------------------------------------------------------------------------------
/examples/invoke-simple/deploy/invoke-caller.yaml:
--------------------------------------------------------------------------------
1 | # Copyright 2021 The Dapr Authors
2 | # Licensed under the Apache License, Version 2.0 (the "License");
3 | # you may not use this file except in compliance with the License.
4 | # You may obtain a copy of the License at
5 | # http://www.apache.org/licenses/LICENSE-2.0
6 | # Unless required by applicable law or agreed to in writing, software
7 | # distributed under the License is distributed on an "AS IS" BASIS,
8 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 | # See the License for the specific language governing permissions and
10 | # limitations under the License.
11 |
12 | apiVersion: apps/v1
13 | kind: Deployment
14 | metadata:
15 | name: invokecaller
16 | labels:
17 | app: invokecaller
18 | spec:
19 | replicas: 1
20 | selector:
21 | matchLabels:
22 | app: invokecaller
23 | template:
24 | metadata:
25 | labels:
26 | app: invokecaller
27 | annotations:
28 | dapr.io/enabled: "true"
29 | dapr.io/app-id: "invoke-caller"
30 | dapr.io/app-protocol: "grpc"
31 | spec:
32 | containers:
33 | - name: invokecaller
34 | image: invokesimple:latest # EDIT HERE: Replace the image name
35 | command: ["python"]
36 | args: ["/app/invoke-caller.py"]
37 | imagePullPolicy: Always
38 |
--------------------------------------------------------------------------------
/examples/grpc_proxying/deploy/invoke-caller.yaml:
--------------------------------------------------------------------------------
1 | # Copyright 2021 The Dapr Authors
2 | # Licensed under the Apache License, Version 2.0 (the "License");
3 | # you may not use this file except in compliance with the License.
4 | # You may obtain a copy of the License at
5 | # http://www.apache.org/licenses/LICENSE-2.0
6 | # Unless required by applicable law or agreed to in writing, software
7 | # distributed under the License is distributed on an "AS IS" BASIS,
8 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 | # See the License for the specific language governing permissions and
10 | # limitations under the License.
11 |
12 | apiVersion: apps/v1
13 | kind: Deployment
14 | metadata:
15 | name: invokecaller
16 | labels:
17 | app: invokecaller
18 | spec:
19 | replicas: 1
20 | selector:
21 | matchLabels:
22 | app: invokecaller
23 | template:
24 | metadata:
25 | labels:
26 | app: invokecaller
27 | annotations:
28 | dapr.io/enabled: "true"
29 | dapr.io/app-id: "invoke-caller"
30 | dapr.io/app-protocol: "grpc"
31 | spec:
32 | containers:
33 | - name: invokecaller
34 | image: invokegrpcproxy:latest # EDIT HERE: Replace the image name
35 | command: ["python"]
36 | args: ["/app/invoke-caller.py"]
37 | imagePullPolicy: Always
38 |
--------------------------------------------------------------------------------
/ext/dapr-ext-workflow/tests/test_workflow_util.py:
--------------------------------------------------------------------------------
1 | import unittest
2 | from unittest.mock import patch
3 |
4 | from dapr.ext.workflow.util import getAddress
5 |
6 | from dapr.conf import settings
7 |
8 |
9 | class DaprWorkflowUtilTest(unittest.TestCase):
10 | def test_get_address_default(self):
11 | expected = f'{settings.DAPR_RUNTIME_HOST}:{settings.DAPR_GRPC_PORT}'
12 | self.assertEqual(expected, getAddress())
13 |
14 | def test_get_address_with_constructor_arguments(self):
15 | self.assertEqual('test.com:5000', getAddress('test.com', '5000'))
16 |
17 | def test_get_address_with_partial_constructor_arguments(self):
18 | expected = f'{settings.DAPR_RUNTIME_HOST}:5000'
19 | self.assertEqual(expected, getAddress(port='5000'))
20 |
21 | expected = f'test.com:{settings.DAPR_GRPC_PORT}'
22 | self.assertEqual(expected, getAddress(host='test.com'))
23 |
24 | @patch.object(settings, 'DAPR_GRPC_ENDPOINT', 'https://domain1.com:5000')
25 | def test_get_address_with_constructor_arguments_and_env_variable(self):
26 | self.assertEqual('test.com:5000', getAddress('test.com', '5000'))
27 |
28 | @patch.object(settings, 'DAPR_GRPC_ENDPOINT', 'https://domain1.com:5000')
29 | def test_get_address_with_env_variable(self):
30 | self.assertEqual('https://domain1.com:5000', getAddress())
31 |
--------------------------------------------------------------------------------
/ext/dapr-ext-workflow/dapr/ext/workflow/logger/logger.py:
--------------------------------------------------------------------------------
1 | import logging
2 | from typing import Union
3 |
4 | from dapr.ext.workflow.logger.options import LoggerOptions
5 |
6 |
7 | class Logger:
8 | def __init__(self, name: str, options: Union[LoggerOptions, None] = None):
9 | # If options is None, then create a new LoggerOptions object
10 | if options is None:
11 | options = LoggerOptions()
12 | log_handler = options.log_handler
13 | log_handler.setLevel(options.log_level)
14 | log_handler.setFormatter(options.log_formatter)
15 | logger = logging.getLogger(name)
16 | logger.handlers.append(log_handler)
17 | self._logger_options = options
18 | self._logger = logger
19 |
20 | def get_options(self) -> LoggerOptions:
21 | return self._logger_options
22 |
23 | def debug(self, msg, *args, **kwargs):
24 | self._logger.debug(msg, *args, **kwargs)
25 |
26 | def info(self, msg, *args, **kwargs):
27 | self._logger.info(msg, *args, **kwargs)
28 |
29 | def warning(self, msg, *args, **kwargs):
30 | self._logger.warning(msg, *args, **kwargs)
31 |
32 | def error(self, msg, *args, **kwargs):
33 | self._logger.error(msg, *args, **kwargs)
34 |
35 | def critical(self, msg, *args, **kwargs):
36 | self._logger.critical(msg, *args, **kwargs)
37 |
--------------------------------------------------------------------------------
/examples/workflow/cross-app3.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Copyright 2025 The Dapr Authors
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | # http://www.apache.org/licenses/LICENSE-2.0
7 | # Unless required by applicable law or agreed to in writing, software
8 | # distributed under the License is distributed on an "AS IS" BASIS,
9 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10 | # See the License for the specific language governing permissions and
11 | # limitations under the License.
12 | import os
13 | import time
14 |
15 | import dapr.ext.workflow as wf
16 |
17 | wfr = wf.WorkflowRuntime()
18 |
19 |
20 | @wfr.activity
21 | def app3_activity(ctx: wf.DaprWorkflowContext) -> int:
22 | print('app3 - received activity call', flush=True)
23 | if os.getenv('ERROR_ACTIVITY_MODE', 'false') == 'true':
24 | print('app3 - raising error in activity due to error mode being enabled', flush=True)
25 | raise ValueError('Error in activity due to error mode being enabled')
26 | print('app3 - returning activity result', flush=True)
27 | return 3
28 |
29 |
30 | if __name__ == '__main__':
31 | wfr.start()
32 | time.sleep(15) # wait for workflow runtime to start
33 | wfr.shutdown()
34 |
--------------------------------------------------------------------------------
/examples/demo_actor/deploy/demo_actor_client.yml:
--------------------------------------------------------------------------------
1 | # Copyright 2021 The Dapr Authors
2 | # Licensed under the Apache License, Version 2.0 (the "License");
3 | # you may not use this file except in compliance with the License.
4 | # You may obtain a copy of the License at
5 | # http://www.apache.org/licenses/LICENSE-2.0
6 | # Unless required by applicable law or agreed to in writing, software
7 | # distributed under the License is distributed on an "AS IS" BASIS,
8 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 | # See the License for the specific language governing permissions and
10 | # limitations under the License.
11 |
12 | apiVersion: apps/v1
13 | kind: Deployment
14 | metadata:
15 | name: demoactor-client-app
16 | labels:
17 | app: demoactor-client
18 | spec:
19 | replicas: 1
20 | selector:
21 | matchLabels:
22 | app: demoactor-client
23 | template:
24 | metadata:
25 | labels:
26 | app: demoactor-client
27 | annotations:
28 | dapr.io/enabled: "true"
29 | dapr.io/app-id: "demoactor-client"
30 | spec:
31 | containers:
32 | - name: demoactor-client
33 | image: demo_actor:latest # EDIT HERE: Replace the image nmae with [docker registry]/demo_actor:latest
34 | command: ["python"]
35 | args: ["/app/demo_actor_client.py"]
36 | imagePullPolicy: Always
37 |
--------------------------------------------------------------------------------
/examples/pubsub-streaming/subscriber-handler.py:
--------------------------------------------------------------------------------
1 | import argparse
2 | import time
3 |
4 | from dapr.clients import DaprClient
5 | from dapr.clients.grpc._response import TopicEventResponse
6 |
7 | counter = 0
8 |
9 | parser = argparse.ArgumentParser(description='Publish events to a Dapr pub/sub topic.')
10 | parser.add_argument('--topic', type=str, required=True, help='The topic name to publish to.')
11 | args = parser.parse_args()
12 |
13 | topic_name = args.topic
14 | dlq_topic_name = topic_name + '_DEAD'
15 |
16 |
17 | def process_message(message):
18 | # Process the message here
19 | global counter
20 | counter += 1
21 | print(f'Processing message: {message.data()} from {message.topic()}...', flush=True)
22 | return TopicEventResponse('success')
23 |
24 |
25 | def main():
26 | with DaprClient() as client:
27 | # This will start a new thread that will listen for messages
28 | # and process them in the `process_message` function
29 | close_fn = client.subscribe_with_handler(
30 | pubsub_name='pubsub',
31 | topic=topic_name,
32 | handler_fn=process_message,
33 | dead_letter_topic=dlq_topic_name,
34 | )
35 |
36 | while counter < 5:
37 | time.sleep(1)
38 |
39 | print('Closing subscription...')
40 | close_fn()
41 |
42 |
43 | if __name__ == '__main__':
44 | main()
45 |
--------------------------------------------------------------------------------
/examples/invoke-simple/deploy/invoke-receiver.yaml:
--------------------------------------------------------------------------------
1 | # Copyright 2021 The Dapr Authors
2 | # Licensed under the Apache License, Version 2.0 (the "License");
3 | # you may not use this file except in compliance with the License.
4 | # You may obtain a copy of the License at
5 | # http://www.apache.org/licenses/LICENSE-2.0
6 | # Unless required by applicable law or agreed to in writing, software
7 | # distributed under the License is distributed on an "AS IS" BASIS,
8 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 | # See the License for the specific language governing permissions and
10 | # limitations under the License.
11 |
12 | apiVersion: apps/v1
13 | kind: Deployment
14 | metadata:
15 | name: invokereceiver
16 | labels:
17 | app: invokereceiver
18 | spec:
19 | replicas: 1
20 | selector:
21 | matchLabels:
22 | app: invokereceiver
23 | template:
24 | metadata:
25 | labels:
26 | app: invokereceiver
27 | annotations:
28 | dapr.io/enabled: "true"
29 | dapr.io/app-id: "invoke-receiver"
30 | dapr.io/app-protocol: "grpc"
31 | dapr.io/app-port: "50051"
32 | spec:
33 | containers:
34 | - name: invokereceiver
35 | image: invokesimple:latest # EDIT HERE: Replace the image name
36 | command: ["python"]
37 | args: ["/app/invoke-receiver.py"]
38 | ports:
39 | - containerPort: 3000
40 | imagePullPolicy: Always
41 |
--------------------------------------------------------------------------------
/examples/grpc_proxying/deploy/invoke-receiver.yaml:
--------------------------------------------------------------------------------
1 | # Copyright 2021 The Dapr Authors
2 | # Licensed under the Apache License, Version 2.0 (the "License");
3 | # you may not use this file except in compliance with the License.
4 | # You may obtain a copy of the License at
5 | # http://www.apache.org/licenses/LICENSE-2.0
6 | # Unless required by applicable law or agreed to in writing, software
7 | # distributed under the License is distributed on an "AS IS" BASIS,
8 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 | # See the License for the specific language governing permissions and
10 | # limitations under the License.
11 |
12 | apiVersion: apps/v1
13 | kind: Deployment
14 | metadata:
15 | name: invokereceiver
16 | labels:
17 | app: invokereceiver
18 | spec:
19 | replicas: 1
20 | selector:
21 | matchLabels:
22 | app: invokereceiver
23 | template:
24 | metadata:
25 | labels:
26 | app: invokereceiver
27 | annotations:
28 | dapr.io/enabled: "true"
29 | dapr.io/app-id: "invoke-receiver"
30 | dapr.io/app-protocol: "grpc"
31 | dapr.io/app-port: "50051"
32 | spec:
33 | containers:
34 | - name: invokereceiver
35 | image: invokegrpcproxy:latest # EDIT HERE: Replace the image name
36 | command: ["python"]
37 | args: ["/app/invoke-receiver.py"]
38 | ports:
39 | - containerPort: 50051
40 | imagePullPolicy: Always
41 |
--------------------------------------------------------------------------------
/examples/secret_store/example.py:
--------------------------------------------------------------------------------
1 | # ------------------------------------------------------------
2 | # Copyright 2021 The Dapr Authors
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | # http://www.apache.org/licenses/LICENSE-2.0
7 | # Unless required by applicable law or agreed to in writing, software
8 | # distributed under the License is distributed on an "AS IS" BASIS,
9 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10 | # See the License for the specific language governing permissions and
11 | # limitations under the License.
12 | # ------------------------------------------------------------
13 |
14 | from dapr.clients import DaprClient
15 |
16 | with DaprClient() as d:
17 | key = 'secretKey'
18 | randomKey = 'random'
19 | storeName = 'localsecretstore'
20 |
21 | resp = d.get_secret(store_name=storeName, key=key)
22 | print('Got!')
23 | print(resp.secret)
24 | resp = d.get_bulk_secret(store_name=storeName)
25 | print('Got!')
26 | # Converts dict into sorted list of tuples for deterministic output.
27 | print(sorted(resp.secrets.items()))
28 | try:
29 | resp = d.get_secret(store_name=storeName, key=randomKey)
30 | print('Got!')
31 | print(resp.secret)
32 | except:
33 | print('Got expected error for accessing random key')
34 |
--------------------------------------------------------------------------------
/examples/demo_actor/deploy/demo_actor_service.yml:
--------------------------------------------------------------------------------
1 | # Copyright 2021 The Dapr Authors
2 | # Licensed under the Apache License, Version 2.0 (the "License");
3 | # you may not use this file except in compliance with the License.
4 | # You may obtain a copy of the License at
5 | # http://www.apache.org/licenses/LICENSE-2.0
6 | # Unless required by applicable law or agreed to in writing, software
7 | # distributed under the License is distributed on an "AS IS" BASIS,
8 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 | # See the License for the specific language governing permissions and
10 | # limitations under the License.
11 |
12 | apiVersion: apps/v1
13 | kind: Deployment
14 | metadata:
15 | name: demoactorapp
16 | labels:
17 | app: demoactor
18 | spec:
19 | replicas: 1
20 | selector:
21 | matchLabels:
22 | app: demoactor
23 | template:
24 | metadata:
25 | labels:
26 | app: demoactor
27 | annotations:
28 | dapr.io/enabled: "true"
29 | dapr.io/app-id: "demoactor"
30 | dapr.io/app-port: "3000"
31 | spec:
32 | containers:
33 | - name: demoactor
34 | image: demo_actor:latest # EDIT HERE: Replace the image nmae with [docker registry]/demo_actor:latest
35 | command: ["uvicorn"]
36 | args: ["--port", "3000", "--reload-dir", "/app", "demo_actor_service:app"]
37 | ports:
38 | - containerPort: 3000
39 | imagePullPolicy: Always
40 |
--------------------------------------------------------------------------------
/ext/dapr-ext-workflow/dapr/ext/workflow/__init__.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | """
4 | Copyright 2023 The Dapr Authors
5 | Licensed under the Apache License, Version 2.0 (the "License");
6 | you may not use this file except in compliance with the License.
7 | You may obtain a copy of the License at
8 | http://www.apache.org/licenses/LICENSE-2.0
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 | """
15 |
16 | # Import your main classes here
17 | from dapr.ext.workflow.dapr_workflow_client import DaprWorkflowClient
18 | from dapr.ext.workflow.dapr_workflow_context import DaprWorkflowContext, when_all, when_any
19 | from dapr.ext.workflow.retry_policy import RetryPolicy
20 | from dapr.ext.workflow.workflow_activity_context import WorkflowActivityContext
21 | from dapr.ext.workflow.workflow_runtime import WorkflowRuntime, alternate_name
22 | from dapr.ext.workflow.workflow_state import WorkflowState, WorkflowStatus
23 |
24 | __all__ = [
25 | 'WorkflowRuntime',
26 | 'DaprWorkflowClient',
27 | 'DaprWorkflowContext',
28 | 'WorkflowActivityContext',
29 | 'WorkflowState',
30 | 'WorkflowStatus',
31 | 'when_all',
32 | 'when_any',
33 | 'alternate_name',
34 | 'RetryPolicy',
35 | ]
36 |
--------------------------------------------------------------------------------
/examples/conversation/conversation_alpha1.py:
--------------------------------------------------------------------------------
1 | # ------------------------------------------------------------
2 | # Copyright 2025 The Dapr Authors
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | # http://www.apache.org/licenses/LICENSE-2.0
7 | # Unless required by applicable law or agreed to in writing, software
8 | # distributed under the License is distributed on an "AS IS" BASIS,
9 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10 | # See the License for the specific language governing permissions and
11 | # limitations under the License.
12 | # ------------------------------------------------------------
13 | from dapr.clients import DaprClient
14 | from dapr.clients.grpc.conversation import ConversationInput
15 |
16 | with DaprClient() as d:
17 | inputs = [
18 | ConversationInput(content="What's Dapr?", role='user', scrub_pii=True),
19 | ConversationInput(content='Give a brief overview.', role='user', scrub_pii=True),
20 | ]
21 |
22 | metadata = {
23 | 'model': 'foo',
24 | 'key': 'authKey',
25 | 'cacheTTL': '10m',
26 | }
27 |
28 | response = d.converse_alpha1(
29 | name='echo', inputs=inputs, temperature=0.7, context_id='chat-123', metadata=metadata
30 | )
31 |
32 | print('Result: ', end='')
33 | for output in response.outputs:
34 | print(output.result)
35 |
--------------------------------------------------------------------------------
/examples/invoke-custom-data/proto/response_pb2.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Generated by the protocol buffer compiler. DO NOT EDIT!
3 | # source: response.proto
4 | """Generated protocol buffer code."""
5 |
6 | from google.protobuf import descriptor as _descriptor
7 | from google.protobuf import descriptor_pool as _descriptor_pool
8 | from google.protobuf import message as _message
9 | from google.protobuf import reflection as _reflection
10 | from google.protobuf import symbol_database as _symbol_database
11 |
12 | # @@protoc_insertion_point(imports)
13 |
14 | _sym_db = _symbol_database.Default()
15 |
16 |
17 | DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(
18 | b'\n\x0eresponse.proto"B\n\x0e\x43ustomResponse\x12\x11\n\tisSuccess\x18\x01 \x01(\x08\x12\x0c\n\x04\x63ode\x18\x02 \x01(\x05\x12\x0f\n\x07message\x18\x03 \x01(\tb\x06proto3'
19 | )
20 |
21 |
22 | _CUSTOMRESPONSE = DESCRIPTOR.message_types_by_name['CustomResponse']
23 | CustomResponse = _reflection.GeneratedProtocolMessageType(
24 | 'CustomResponse',
25 | (_message.Message,),
26 | {
27 | 'DESCRIPTOR': _CUSTOMRESPONSE,
28 | '__module__': 'response_pb2',
29 | # @@protoc_insertion_point(class_scope:CustomResponse)
30 | },
31 | )
32 | _sym_db.RegisterMessage(CustomResponse)
33 |
34 | if _descriptor._USE_C_DESCRIPTORS == False:
35 | DESCRIPTOR._options = None
36 | _CUSTOMRESPONSE._serialized_start = 18
37 | _CUSTOMRESPONSE._serialized_end = 84
38 | # @@protoc_insertion_point(module_scope)
39 |
--------------------------------------------------------------------------------
/tests/actor/test_actor_id.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | """
4 | Copyright 2021 The Dapr Authors
5 | Licensed under the Apache License, Version 2.0 (the "License");
6 | you may not use this file except in compliance with the License.
7 | You may obtain a copy of the License at
8 | http://www.apache.org/licenses/LICENSE-2.0
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 | """
15 |
16 | import unittest
17 |
18 | from dapr.actor.id import ActorId
19 |
20 |
21 | class ActorIdTests(unittest.TestCase):
22 | def test_create_actor_id(self):
23 | actor_id_1 = ActorId('1')
24 | self.assertEqual('1', actor_id_1.id)
25 |
26 | def test_create_random_id(self):
27 | actor_id_random = ActorId.create_random_id()
28 | self.assertEqual(len('f56d5aec5b3b11ea9121acde48001122'), len(actor_id_random.id))
29 |
30 | def test_get_hash(self):
31 | actor_test_id = ActorId('testId')
32 | self.assertIsNotNone(actor_test_id.__hash__)
33 |
34 | def test_comparison(self):
35 | actor_id_1 = ActorId('1')
36 | actor_id_1a = ActorId('1')
37 | self.assertTrue(actor_id_1 == actor_id_1a)
38 |
39 | actor_id_2 = ActorId('2')
40 | self.assertFalse(actor_id_1 == actor_id_2)
41 |
--------------------------------------------------------------------------------
/dapr/conf/__init__.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | """
4 | Copyright 2023 The Dapr Authors
5 | Licensed under the Apache License, Version 2.0 (the "License");
6 | you may not use this file except in compliance with the License.
7 | You may obtain a copy of the License at
8 | http://www.apache.org/licenses/LICENSE-2.0
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 | """
15 |
16 | import os
17 |
18 | from dapr.conf import global_settings
19 |
20 |
21 | class Settings:
22 | def __init__(self):
23 | for setting in dir(global_settings):
24 | default_value = getattr(global_settings, setting)
25 | env_variable = os.environ.get(setting)
26 | if env_variable:
27 | val = (
28 | type(default_value)(env_variable) if default_value is not None else env_variable
29 | )
30 | setattr(self, setting, val)
31 | else:
32 | setattr(self, setting, default_value)
33 |
34 | def __getattr__(self, name):
35 | if name not in dir(global_settings):
36 | raise AttributeError(f"'{self.__class__.__name__}' object has no attribute '{name}'")
37 | return getattr(self, name)
38 |
39 |
40 | settings = Settings()
41 |
--------------------------------------------------------------------------------
/dapr/proto/__init__.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | """
4 | Copyright 2023 The Dapr Authors
5 | Licensed under the Apache License, Version 2.0 (the "License");
6 | you may not use this file except in compliance with the License.
7 | You may obtain a copy of the License at
8 | http://www.apache.org/licenses/LICENSE-2.0
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 | """
15 |
16 | import os
17 | import grpc
18 |
19 | from contextlib import contextmanager
20 | from typing import Optional
21 | from dapr.conf import settings
22 |
23 | from dapr.proto.common.v1 import common_pb2 as common_v1
24 | from dapr.proto.runtime.v1 import dapr_pb2 as api_v1
25 | from dapr.proto.runtime.v1 import dapr_pb2_grpc as api_service_v1
26 | from dapr.proto.runtime.v1 import appcallback_pb2 as appcallback_v1
27 | from dapr.proto.runtime.v1 import appcallback_pb2_grpc as appcallback_service_v1
28 |
29 |
30 | @contextmanager
31 | def connect_dapr(port: Optional[int] = -1):
32 | if port == -1:
33 | port = settings.DAPR_GRPC_PORT
34 | channel = grpc.insecure_channel(f"127.0.0.1:{port}")
35 | stub = api_service_v1.DaprStub(channel)
36 | yield stub
37 | channel.close()
38 |
39 |
40 | __all__ = [
41 | 'connect_dapr',
42 | 'common_v1',
43 | 'api_v1',
44 | 'appcallback_v1',
45 | 'appcallback_service_v1',
46 | ]
47 |
--------------------------------------------------------------------------------
/examples/demo_actor/demo_actor/demo_actor_interface.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Copyright 2021 The Dapr Authors
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | # http://www.apache.org/licenses/LICENSE-2.0
7 | # Unless required by applicable law or agreed to in writing, software
8 | # distributed under the License is distributed on an "AS IS" BASIS,
9 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10 | # See the License for the specific language governing permissions and
11 | # limitations under the License.
12 |
13 | from abc import abstractmethod
14 |
15 | from dapr.actor import ActorInterface, actormethod
16 |
17 |
18 | class DemoActorInterface(ActorInterface):
19 | @abstractmethod
20 | @actormethod(name='GetMyData')
21 | async def get_my_data(self) -> object: ...
22 |
23 | @abstractmethod
24 | @actormethod(name='SetMyData')
25 | async def set_my_data(self, data: object) -> None: ...
26 |
27 | @abstractmethod
28 | @actormethod(name='ClearMyData')
29 | async def clear_my_data(self) -> None: ...
30 |
31 | @abstractmethod
32 | @actormethod(name='SetReminder')
33 | async def set_reminder(self, enabled: bool) -> None: ...
34 |
35 | @abstractmethod
36 | @actormethod(name='SetTimer')
37 | async def set_timer(self, enabled: bool) -> None: ...
38 |
39 | @abstractmethod
40 | @actormethod(name='GetReentrancyStatus')
41 | async def get_reentrancy_status(self) -> bool: ...
42 |
--------------------------------------------------------------------------------
/examples/conversation/conversation_alpha2.py:
--------------------------------------------------------------------------------
1 | # ------------------------------------------------------------
2 | # Copyright 2025 The Dapr Authors
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | # http://www.apache.org/licenses/LICENSE-2.0
7 | # Unless required by applicable law or agreed to in writing, software
8 | # distributed under the License is distributed on an "AS IS" BASIS,
9 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10 | # See the License for the specific language governing permissions and
11 | # limitations under the License.
12 | # ------------------------------------------------------------
13 | from dapr.clients import DaprClient
14 | from dapr.clients.grpc.conversation import (
15 | ConversationInputAlpha2,
16 | create_user_message,
17 | )
18 |
19 | with DaprClient() as d:
20 | inputs = [
21 | ConversationInputAlpha2(messages=[create_user_message("What's Dapr?")], scrub_pii=True),
22 | ConversationInputAlpha2(
23 | messages=[create_user_message('Give a brief overview.')], scrub_pii=True
24 | ),
25 | ]
26 |
27 | metadata = {
28 | 'model': 'foo',
29 | 'key': 'authKey',
30 | 'cacheTTL': '10m',
31 | }
32 |
33 | response = d.converse_alpha2(
34 | name='echo', inputs=inputs, temperature=0.7, context_id='chat-123', metadata=metadata
35 | )
36 |
37 | print('Result: ', end='')
38 | for output in response.outputs:
39 | print(output.choices[0].message.content)
40 |
--------------------------------------------------------------------------------
/examples/langgraph-checkpointer/README.md:
--------------------------------------------------------------------------------
1 | # Dapr For Agents - LangGraph Checkpointer
2 |
3 | Supporting Dapr backed Checkpointer for LangGraph based Agents.
4 |
5 | ## Pre-requisites
6 |
7 | - [Dapr CLI and initialized environment](https://docs.dapr.io/getting-started)
8 | - [Install Python 3.10+](https://www.python.org/downloads/)
9 |
10 | ## Install Dapr python-SDK
11 |
12 |
13 |
14 |
17 |
18 | ```sh
19 | pip3 install -r requirements.txt
20 | ```
21 |
22 |
23 |
24 | ## Run the example
25 |
26 | Export your `OPENAI_API_KEY`:
27 |
28 | ```bash
29 | export OPENAI_API_KEY="SK-..."
30 | ```
31 |
32 | Run the following command in a terminal/command prompt:
33 |
34 |
51 |
52 | ```bash
53 | # 1. Run the LangGraph agent
54 | dapr run --app-id langgraph-checkpointer --app-port 5001 --resources-path ./components -- python3 agent.py
55 | ```
56 |
57 |
58 |
59 | ## Cleanup
60 |
61 | Either press CTRL + C to quit the app or run the following command in a new terminal to stop the app:
62 |
63 | ```bash
64 | dapr stop --app-id langgraph-checkpointer
65 | ```
66 |
67 |
--------------------------------------------------------------------------------
/examples/README.md:
--------------------------------------------------------------------------------
1 | # Dapr Python SDK examples
2 |
3 | These examples demonstrate how to use the Dapr Python SDK:
4 |
5 | | Example | Description |
6 | |-------------------------------------------------------|-------------|
7 | | [Service invocation](./invoke-simple) | Invoke service by passing bytes data
8 | | [Service invocation (advanced)](./invoke-custom-data) | Invoke service by using custom protobuf message
9 | | [State management](./state_store) | Save and get state to/from the state store
10 | | [Publish & subscribe](./pubsub-simple) | Publish and subscribe to events
11 | | [Error handling](./error_handling) | Error handling
12 | | [Bindings](./invoke-binding) | Invoke an output binding to interact with external resources
13 | | [Virtual actors](./demo_actor) | Try Dapr virtual actor features
14 | | [Secrets](./secret_store) | Get secrets from a defined secret store
15 | | [Distributed tracing](./w3c-tracing) | Leverage Dapr's built-in tracing support
16 | | [Distributed lock](./distributed_lock) | Keep your application safe from race conditions by using distributed locks
17 | | [Workflow](./demo_workflow) | Run a workflow to simulate an order processor
18 | | [Cryptography](./crypto) | Perform cryptographic operations without exposing keys to your application
19 |
20 | ## More information
21 |
22 | - [Dapr Python SDK docs](https://docs.dapr.io/developing-applications/sdks/python)
23 |
--------------------------------------------------------------------------------
/dapr/conf/global_settings.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | """
4 | Copyright 2023 The Dapr Authors
5 | Licensed under the Apache License, Version 2.0 (the "License");
6 | you may not use this file except in compliance with the License.
7 | You may obtain a copy of the License at
8 | http://www.apache.org/licenses/LICENSE-2.0
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 | """
15 |
16 | # Default environment settings that environment variables overrides
17 |
18 | HTTP_APP_PORT = 3000
19 | GRPC_APP_PORT = 3010
20 |
21 | DAPR_API_TOKEN = None
22 | DAPR_HTTP_ENDPOINT = None
23 | DAPR_GRPC_ENDPOINT = None
24 | DAPR_RUNTIME_HOST = '127.0.0.1'
25 | DAPR_HTTP_PORT = 3500
26 | DAPR_GRPC_PORT = 50001
27 | DAPR_API_VERSION = 'v1.0'
28 | DAPR_HEALTH_TIMEOUT = 60 # seconds
29 |
30 | DAPR_API_MAX_RETRIES = 0
31 | DAPR_API_TIMEOUT_SECONDS = 60
32 |
33 | DAPR_API_METHOD_INVOCATION_PROTOCOL = 'http'
34 |
35 | DAPR_HTTP_TIMEOUT_SECONDS = 60
36 |
37 | # ----- Conversation API settings ------
38 |
39 | # Configuration for handling large enums to avoid massive JSON schemas that can exceed LLM token limits
40 | DAPR_CONVERSATION_TOOLS_MAX_ENUM_ITEMS = 100
41 | # What to do when an enum has more than DAPR_CONVERSATION_TOOLS_MAX_ENUM_ITEMS items. Convert to String message or raise an exception
42 | # possible values: 'string' (default), 'error'
43 | DAPR_CONVERSATION_TOOLS_LARGE_ENUM_BEHAVIOR = 'string'
44 |
--------------------------------------------------------------------------------
/examples/error_handling/error_handling.py:
--------------------------------------------------------------------------------
1 | from dapr.clients import DaprClient
2 | from dapr.clients.exceptions import DaprGrpcError
3 |
4 | with DaprClient() as d:
5 | storeName = 'statestore'
6 |
7 | key = 'key||'
8 | value = 'value_1'
9 |
10 | # Save single state.
11 | try:
12 | d.save_state(store_name=storeName, key=key, value=value)
13 | except DaprGrpcError as err:
14 | print(f'Status code: {err.code()}', flush=True)
15 | print(f'Message: {err.details()}', flush=True)
16 | print(f'Error code: {err.error_code()}', flush=True)
17 |
18 | if err.status_details().error_info is not None:
19 | print(f'Error info(reason): {err.status_details().error_info["reason"]}', flush=True)
20 | if err.status_details().resource_info is not None:
21 | print(
22 | f'Resource info (resource type): {err.status_details().resource_info["resource_type"]}',
23 | flush=True,
24 | )
25 | print(
26 | f'Resource info (resource name): {err.status_details().resource_info["resource_name"]}',
27 | flush=True,
28 | )
29 | if err.status_details().bad_request is not None:
30 | print(
31 | f'Bad request (field): {err.status_details().bad_request["field_violations"][0]["field"]}',
32 | flush=True,
33 | )
34 | print(
35 | f'Bad request (description): {err.status_details().bad_request["field_violations"][0]["description"]}',
36 | flush=True,
37 | )
38 | print(f'JSON: {err.json()}', flush=True)
39 |
--------------------------------------------------------------------------------
/examples/pubsub-streaming-async/subscriber-handler.py:
--------------------------------------------------------------------------------
1 | import argparse
2 | import asyncio
3 |
4 | from dapr.aio.clients import DaprClient
5 | from dapr.clients.grpc._response import TopicEventResponse
6 |
7 | parser = argparse.ArgumentParser(description='Publish events to a Dapr pub/sub topic.')
8 | parser.add_argument('--topic', type=str, required=True, help='The topic name to publish to.')
9 | args = parser.parse_args()
10 |
11 | topic_name = args.topic
12 | dlq_topic_name = topic_name + '_DEAD'
13 |
14 | counter = 0
15 |
16 |
17 | async def process_message(message) -> TopicEventResponse:
18 | """
19 | Asynchronously processes the message and returns a TopicEventResponse.
20 | """
21 |
22 | print(f'Processing message: {message.data()} from {message.topic()}...', flush=True)
23 | global counter
24 | counter += 1
25 | return TopicEventResponse('success')
26 |
27 |
28 | async def main():
29 | """
30 | Main function to subscribe to a pubsub topic and handle messages asynchronously.
31 | """
32 | async with DaprClient() as client:
33 | # Subscribe to the pubsub topic with the message handler
34 | close_fn = await client.subscribe_with_handler(
35 | pubsub_name='pubsub',
36 | topic=topic_name,
37 | handler_fn=process_message,
38 | dead_letter_topic=dlq_topic_name,
39 | )
40 |
41 | # Wait until 5 messages are processed
42 | global counter
43 | while counter < 5:
44 | await asyncio.sleep(1)
45 |
46 | print('Closing subscription...')
47 | await close_fn()
48 |
49 |
50 | if __name__ == '__main__':
51 | asyncio.run(main())
52 |
--------------------------------------------------------------------------------
/examples/demo_actor/demo_actor/demo_actor_service.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Copyright 2021 The Dapr Authors
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | # http://www.apache.org/licenses/LICENSE-2.0
7 | # Unless required by applicable law or agreed to in writing, software
8 | # distributed under the License is distributed on an "AS IS" BASIS,
9 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10 | # See the License for the specific language governing permissions and
11 | # limitations under the License.
12 |
13 | from dapr.ext.fastapi import DaprActor # type: ignore
14 | from demo_actor import DemoActor
15 | from fastapi import FastAPI # type: ignore
16 |
17 | from dapr.actor.runtime.config import ActorReentrancyConfig, ActorRuntimeConfig, ActorTypeConfig
18 | from dapr.actor.runtime.runtime import ActorRuntime
19 |
20 | app = FastAPI(title=f'{DemoActor.__name__}Service')
21 |
22 | # This is an optional advanced configuration which enables reentrancy only for the
23 | # specified actor type. By default reentrancy is not enabled for all actor types.
24 | config = ActorRuntimeConfig() # init with default values
25 | config.update_actor_type_configs(
26 | [ActorTypeConfig(actor_type=DemoActor.__name__, reentrancy=ActorReentrancyConfig(enabled=True))]
27 | )
28 | ActorRuntime.set_actor_config(config)
29 |
30 | # Add Dapr Actor Extension
31 | actor = DaprActor(app)
32 |
33 |
34 | @app.on_event('startup')
35 | async def startup_event():
36 | # Register DemoActor
37 | await actor.register_actor(DemoActor)
38 |
--------------------------------------------------------------------------------
/ext/dapr-ext-workflow/dapr/ext/workflow/workflow_activity_context.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | """
4 | Copyright 2023 The Dapr Authors
5 | Licensed under the Apache License, Version 2.0 (the "License");
6 | you may not use this file except in compliance with the License.
7 | You may obtain a copy of the License at
8 | http://www.apache.org/licenses/LICENSE-2.0
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 | """
15 |
16 | from __future__ import annotations
17 |
18 | from typing import Callable, TypeVar
19 |
20 | from durabletask import task
21 |
22 | T = TypeVar('T')
23 | TInput = TypeVar('TInput')
24 | TOutput = TypeVar('TOutput')
25 |
26 |
27 | class WorkflowActivityContext:
28 | """Defines properties and methods for task activity context objects."""
29 |
30 | def __init__(self, ctx: task.ActivityContext):
31 | self.__obj = ctx
32 |
33 | @property
34 | def workflow_id(self) -> str:
35 | """Gets the unique ID of the current workflow instance"""
36 | return self.__obj.orchestration_id
37 |
38 | @property
39 | def task_id(self) -> int:
40 | """Gets the unique ID of the current workflow task"""
41 | return self.__obj.task_id
42 |
43 | def get_inner_context(self) -> task.ActivityContext:
44 | return self.__obj
45 |
46 |
47 | # Activities are simple functions that can be scheduled by workflows
48 | Activity = Callable[..., TOutput]
49 |
--------------------------------------------------------------------------------
/ext/dapr-ext-workflow/dapr/ext/workflow/logger/options.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | """
4 | Copyright 2023 The Dapr Authors
5 | Licensed under the Apache License, Version 2.0 (the "License");
6 | you may not use this file except in compliance with the License.
7 | You may obtain a copy of the License at
8 | http://www.apache.org/licenses/LICENSE-2.0
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 | """
15 |
16 | import logging
17 | from typing import Union
18 |
19 |
20 | class LoggerOptions:
21 | def __init__(
22 | self,
23 | log_level: Union[str, None] = None,
24 | log_handler: Union[logging.Handler, None] = None,
25 | log_formatter: Union[logging.Formatter, None] = None,
26 | ):
27 | # Set default log level to INFO if none is provided
28 | if log_level is None:
29 | log_level = logging.INFO
30 | # Add a default log handler if none is provided
31 | if log_handler is None:
32 | log_handler = logging.StreamHandler()
33 | # Set a default log formatter if none is provided
34 | if log_formatter is None:
35 | log_formatter = logging.Formatter(
36 | fmt='%(asctime)s.%(msecs)03d %(name)s %(levelname)s: %(message)s',
37 | datefmt='%Y-%m-%d %H:%M:%S',
38 | )
39 | self.log_level = log_level
40 | self.log_handler = log_handler
41 | self.log_formatter = log_formatter
42 |
--------------------------------------------------------------------------------
/examples/pubsub-streaming/publisher.py:
--------------------------------------------------------------------------------
1 | # ------------------------------------------------------------
2 | # Copyright 2022 The Dapr Authors
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | # http://www.apache.org/licenses/LICENSE-2.0
7 | # Unless required by applicable law or agreed to in writing, software
8 | # distributed under the License is distributed on an "AS IS" BASIS,
9 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10 | # See the License for the specific language governing permissions and
11 | # limitations under the License.
12 | # ------------------------------------------------------------
13 | import argparse
14 | import json
15 | import time
16 |
17 | from dapr.clients import DaprClient
18 |
19 | parser = argparse.ArgumentParser(description='Publish events to a Dapr pub/sub topic.')
20 | parser.add_argument('--topic', type=str, required=True, help='The topic name to publish to.')
21 | args = parser.parse_args()
22 |
23 | topic_name = args.topic
24 |
25 | with DaprClient() as d:
26 | id = 0
27 | while id < 5:
28 | id += 1
29 | req_data = {'id': id, 'message': 'hello world'}
30 |
31 | # Create a typed message with content type and body
32 | resp = d.publish_event(
33 | pubsub_name='pubsub',
34 | topic_name=topic_name,
35 | data=json.dumps(req_data),
36 | data_content_type='application/json',
37 | publish_metadata={'ttlInSeconds': '100', 'rawPayload': 'false'},
38 | )
39 |
40 | # Print the request
41 | print(req_data, flush=True)
42 |
43 | time.sleep(1)
44 |
--------------------------------------------------------------------------------
/examples/demo_actor/demo_actor/test_demo_actor.py:
--------------------------------------------------------------------------------
1 | import unittest
2 |
3 | from demo_actor import DemoActor
4 |
5 | from dapr.actor.runtime.mock_actor import create_mock_actor
6 |
7 |
8 | class DemoActorTests(unittest.IsolatedAsyncioTestCase):
9 | def test_create_actor(self):
10 | mockactor = create_mock_actor(DemoActor, '1')
11 | self.assertEqual(mockactor.id.id, '1')
12 |
13 | async def test_get_data(self):
14 | mockactor = create_mock_actor(DemoActor, '1')
15 | self.assertFalse(mockactor._state_manager._mock_state) # type: ignore
16 | val = await mockactor.get_my_data()
17 | self.assertIsNone(val)
18 |
19 | async def test_set_data(self):
20 | mockactor = create_mock_actor(DemoActor, '1')
21 | await mockactor.set_my_data({'state': 5})
22 | val = await mockactor.get_my_data()
23 | self.assertIs(val['state'], 5) # type: ignore
24 |
25 | async def test_clear_data(self):
26 | mockactor = create_mock_actor(DemoActor, '1')
27 | await mockactor.set_my_data({'state': 5})
28 | val = await mockactor.get_my_data()
29 | self.assertIs(val['state'], 5) # type: ignore
30 | await mockactor.clear_my_data()
31 | val = await mockactor.get_my_data()
32 | self.assertIsNone(val)
33 |
34 | async def test_reminder(self):
35 | mockactor = create_mock_actor(DemoActor, '1')
36 | self.assertFalse(mockactor._state_manager._mock_reminders) # type: ignore
37 | await mockactor.set_reminder(True)
38 | self.assertTrue('demo_reminder' in mockactor._state_manager._mock_reminders) # type: ignore
39 | await mockactor.set_reminder(False)
40 | self.assertFalse(mockactor._state_manager._mock_reminders) # type: ignore
41 |
--------------------------------------------------------------------------------
/ext/dapr-ext-grpc/tests/test_topic_event_response.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | """
4 | Copyright 2023 The Dapr Authors
5 | Licensed under the Apache License, Version 2.0 (the "License");
6 | you may not use this file except in compliance with the License.
7 | You may obtain a copy of the License at
8 | http://www.apache.org/licenses/LICENSE-2.0
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 | """
15 |
16 | import unittest
17 |
18 | from dapr.clients.grpc._response import TopicEventResponse, TopicEventResponseStatus
19 |
20 |
21 | class TopicEventResponseTests(unittest.TestCase):
22 | def test_topic_event_response_creation_from_enum(self):
23 | for status in TopicEventResponseStatus:
24 | response = TopicEventResponse(status)
25 | self.assertEqual(response.status.value, status.value)
26 |
27 | def test_topic_event_response_creation_fails(self):
28 | with self.assertRaises(KeyError):
29 | TopicEventResponse('invalid')
30 |
31 | def test_topic_event_response_creation_from_str(self):
32 | for status in TopicEventResponseStatus:
33 | response = TopicEventResponse(status.name)
34 | self.assertEqual(response.status.value, status.value)
35 |
36 | def test_topic_event_response_creation_fails_with_object(self):
37 | with self.assertRaises(ValueError):
38 | TopicEventResponse(None)
39 |
40 |
41 | if __name__ == '__main__':
42 | unittest.main()
43 |
--------------------------------------------------------------------------------
/examples/workflow/child_workflow.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Copyright 2023 The Dapr Authors
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | # http://www.apache.org/licenses/LICENSE-2.0
7 | # Unless required by applicable law or agreed to in writing, software
8 | # distributed under the License is distributed on an "AS IS" BASIS,
9 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10 | # See the License for the specific language governing permissions and
11 | # limitations under the License.
12 |
13 | import time
14 |
15 | import dapr.ext.workflow as wf
16 |
17 | wfr = wf.WorkflowRuntime()
18 |
19 |
20 | @wfr.workflow
21 | def main_workflow(ctx: wf.DaprWorkflowContext):
22 | try:
23 | instance_id = ctx.instance_id
24 | child_instance_id = instance_id + '-child'
25 | print(f'*** Calling child workflow {child_instance_id}', flush=True)
26 | yield ctx.call_child_workflow(
27 | workflow=child_workflow, input=None, instance_id=child_instance_id
28 | )
29 | except Exception as e:
30 | print(f'*** Exception: {e}')
31 |
32 | return
33 |
34 |
35 | @wfr.workflow
36 | def child_workflow(ctx: wf.DaprWorkflowContext):
37 | instance_id = ctx.instance_id
38 | print(f'*** Child workflow {instance_id} called', flush=True)
39 |
40 |
41 | if __name__ == '__main__':
42 | wfr.start()
43 | time.sleep(10) # wait for workflow runtime to start
44 |
45 | wf_client = wf.DaprWorkflowClient()
46 | instance_id = wf_client.schedule_new_workflow(workflow=main_workflow)
47 |
48 | # Wait for the workflow to complete
49 | time.sleep(5)
50 |
51 | wfr.shutdown()
52 |
--------------------------------------------------------------------------------
/.github/workflows/build.yaml:
--------------------------------------------------------------------------------
1 | name: dapr-python
2 |
3 | on:
4 | push:
5 | branches:
6 | - feature/*
7 | pull_request:
8 | branches:
9 | - main
10 | - release-*
11 | - feature/*
12 | workflow_dispatch:
13 | merge_group:
14 |
15 | jobs:
16 | lint:
17 | runs-on: ubuntu-latest
18 | steps:
19 | - uses: actions/checkout@v6
20 | - name: Set up Python 3.10
21 | uses: actions/setup-python@v6
22 | with:
23 | python-version: '3.10'
24 | - name: Install dependencies
25 | run: |
26 | python -m pip install --upgrade pip
27 | pip install setuptools wheel tox
28 | - name: Run Autoformatter
29 | run: |
30 | tox -e ruff
31 | statusResult=$(git status -u --porcelain)
32 | if [ -z $statusResult ]
33 | then
34 | exit 0
35 | else
36 | echo "Source files are not formatted correctly. Run 'tox -e ruff' to autoformat."
37 | exit 1
38 | fi
39 |
40 | build:
41 | needs: lint
42 | runs-on: ubuntu-latest
43 | strategy:
44 | fail-fast: false
45 | matrix:
46 | python_ver: ["3.10", "3.11", "3.12", "3.13"]
47 | steps:
48 | - uses: actions/checkout@v6
49 | - name: Set up Python ${{ matrix.python_ver }}
50 | uses: actions/setup-python@v6
51 | with:
52 | python-version: ${{ matrix.python_ver }}
53 | - name: Install dependencies
54 | run: |
55 | python -m pip install --upgrade pip
56 | pip install setuptools wheel tox
57 | - name: Check Typing
58 | run: |
59 | tox -e type
60 | - name: Run unit-tests
61 | run: |
62 | tox -e py`echo "${{ matrix.python_ver }}" | sed 's/\.//g'`
63 | - name: Upload test coverage
64 | uses: codecov/codecov-action@v5
65 |
--------------------------------------------------------------------------------
/examples/demo_actor/demo_actor/demo_actor_flask.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Copyright 2021 The Dapr Authors
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | # http://www.apache.org/licenses/LICENSE-2.0
7 | # Unless required by applicable law or agreed to in writing, software
8 | # distributed under the License is distributed on an "AS IS" BASIS,
9 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10 | # See the License for the specific language governing permissions and
11 | # limitations under the License.
12 |
13 | from demo_actor import DemoActor
14 | from flask import Flask, jsonify
15 | from flask_dapr.actor import DaprActor
16 |
17 | from dapr.actor.runtime.config import ActorReentrancyConfig, ActorRuntimeConfig, ActorTypeConfig
18 | from dapr.actor.runtime.runtime import ActorRuntime
19 | from dapr.conf import settings
20 |
21 | app = Flask(f'{DemoActor.__name__}Service')
22 |
23 | # This is an optional advanced configuration which enables reentrancy only for the
24 | # specified actor type. By default reentrancy is not enabled for all actor types.
25 | config = ActorRuntimeConfig() # init with default values
26 | config.update_actor_type_configs(
27 | [ActorTypeConfig(actor_type=DemoActor.__name__, reentrancy=ActorReentrancyConfig(enabled=True))]
28 | )
29 | ActorRuntime.set_actor_config(config)
30 |
31 | # Enable DaprActor Flask extension
32 | actor = DaprActor(app)
33 | # Register DemoActor
34 | actor.register_actor(DemoActor)
35 |
36 |
37 | # This route is optional.
38 | @app.route('/')
39 | def index():
40 | return jsonify({'status': 'ok'}), 200
41 |
42 |
43 | if __name__ == '__main__':
44 | app.run(port=settings.HTTP_APP_PORT)
45 |
--------------------------------------------------------------------------------
/ext/dapr-ext-workflow/tests/test_workflow_activity_context.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | """
4 | Copyright 2023 The Dapr Authors
5 | Licensed under the Apache License, Version 2.0 (the "License");
6 | you may not use this file except in compliance with the License.
7 | You may obtain a copy of the License at
8 | http://www.apache.org/licenses/LICENSE-2.0
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 | """
15 |
16 | import unittest
17 | from unittest import mock
18 |
19 | from dapr.ext.workflow.workflow_activity_context import WorkflowActivityContext
20 | from durabletask import task
21 |
22 | mock_orchestration_id = 'orchestration001'
23 | mock_task = 10
24 |
25 |
26 | class FakeActivityContext:
27 | @property
28 | def orchestration_id(self):
29 | return mock_orchestration_id
30 |
31 | @property
32 | def task_id(self):
33 | return mock_task
34 |
35 |
36 | class WorkflowActivityContextTest(unittest.TestCase):
37 | def test_workflow_activity_context(self):
38 | with mock.patch('durabletask.task.ActivityContext', return_value=FakeActivityContext()):
39 | fake_act_ctx = task.ActivityContext(
40 | orchestration_id=mock_orchestration_id, task_id=mock_task
41 | )
42 | act_ctx = WorkflowActivityContext(fake_act_ctx)
43 | actual_orchestration_id = act_ctx.workflow_id
44 | assert actual_orchestration_id == mock_orchestration_id
45 |
46 | actual_task_id = act_ctx.task_id
47 | assert actual_task_id == mock_task
48 |
--------------------------------------------------------------------------------
/.github/workflows/fossa.yaml:
--------------------------------------------------------------------------------
1 | #
2 | # Copyright 2021 The Dapr Authors
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | # http://www.apache.org/licenses/LICENSE-2.0
7 | # Unless required by applicable law or agreed to in writing, software
8 | # distributed under the License is distributed on an "AS IS" BASIS,
9 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10 | # See the License for the specific language governing permissions and
11 | # limitations under the License.
12 | #
13 |
14 | name: fossa
15 | on:
16 | repository_dispatch:
17 | types: [fossa]
18 | push:
19 | branches:
20 | - main
21 | - release-*
22 | - feature/*
23 | tags:
24 | - v*
25 | - workflow-v*
26 | - grpc-v*
27 | - flask-v*
28 | - fastapi-v*
29 | pull_request:
30 | branches:
31 | - main
32 | - release-*
33 | - feature/*
34 | workflow_dispatch: {}
35 | jobs:
36 | fossa-scan:
37 | if: github.repository_owner == 'dapr' # FOSSA is not intended to run on forks.
38 | runs-on: ubuntu-latest
39 | env:
40 | FOSSA_API_KEY: b88e1f4287c3108c8751bf106fb46db6 # This is a push-only token that is safe to be exposed.
41 | steps:
42 | - name: "Checkout code"
43 | uses: actions/checkout@v6
44 |
45 | - name: "Run FOSSA Scan"
46 | uses: fossas/fossa-action@v1.7.0 # Use a specific version if locking is preferred
47 | with:
48 | api-key: ${{ env.FOSSA_API_KEY }}
49 |
50 | - name: "Run FOSSA Test"
51 | uses: fossas/fossa-action@v1.7.0 # Use a specific version if locking is preferred
52 | with:
53 | api-key: ${{ env.FOSSA_API_KEY }}
54 | run-tests: true
55 |
--------------------------------------------------------------------------------
/dapr/clients/base.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | """
4 | Copyright 2023 The Dapr Authors
5 | Licensed under the Apache License, Version 2.0 (the "License");
6 | you may not use this file except in compliance with the License.
7 | You may obtain a copy of the License at
8 | http://www.apache.org/licenses/LICENSE-2.0
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 | """
15 |
16 | from abc import ABC, abstractmethod
17 | from typing import Optional
18 |
19 |
20 | class DaprActorClientBase(ABC):
21 | """A base class that represents Dapr Actor Client."""
22 |
23 | @abstractmethod
24 | async def invoke_method(
25 | self, actor_type: str, actor_id: str, method: str, data: Optional[bytes] = None
26 | ) -> bytes: ...
27 |
28 | @abstractmethod
29 | async def save_state_transactionally(
30 | self, actor_type: str, actor_id: str, data: bytes
31 | ) -> None: ...
32 |
33 | @abstractmethod
34 | async def get_state(self, actor_type: str, actor_id: str, name: str) -> bytes: ...
35 |
36 | @abstractmethod
37 | async def register_reminder(
38 | self, actor_type: str, actor_id: str, name: str, data: bytes
39 | ) -> None: ...
40 |
41 | @abstractmethod
42 | async def unregister_reminder(self, actor_type: str, actor_id: str, name: str) -> None: ...
43 |
44 | @abstractmethod
45 | async def register_timer(
46 | self, actor_type: str, actor_id: str, name: str, data: bytes
47 | ) -> None: ...
48 |
49 | @abstractmethod
50 | async def unregister_timer(self, actor_type: str, actor_id: str, name: str) -> None: ...
51 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Byte-compiled / optimized / DLL files
2 | __pycache__/
3 | *.py[cod]
4 | *$py.class
5 |
6 | # C extensions
7 | *.so
8 |
9 | # Distribution / packaging
10 | .Python
11 | build/
12 | develop-eggs/
13 | dist/
14 | downloads/
15 | eggs/
16 | .eggs/
17 | lib/
18 | lib64/
19 | parts/
20 | sdist/
21 | var/
22 | wheels/
23 | *.egg-info/
24 | .installed.cfg
25 | *.egg
26 | MANIFEST
27 |
28 | # PyInstaller
29 | # Usually these files are written by a python script from a template
30 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
31 | *.manifest
32 | *.spec
33 |
34 | # Installer logs
35 | pip-log.txt
36 | pip-delete-this-directory.txt
37 |
38 | # Unit test / coverage reports
39 | htmlcov/
40 | .tox/
41 | .coverage
42 | .coverage.*
43 | .cache
44 | nosetests.xml
45 | coverage.xml
46 | *.cover
47 | .hypothesis/
48 | .pytest_cache/
49 |
50 | # Editor config
51 | .idea
52 | .vscode
53 |
54 | # Translations
55 | *.mo
56 | *.pot
57 |
58 | # Django stuff:
59 | *.log
60 | local_settings.py
61 | db.sqlite3
62 |
63 | # Flask stuff:
64 | instance/
65 | .webassets-cache
66 |
67 | # Scrapy stuff:
68 | .scrapy
69 |
70 | # Sphinx documentation
71 | docs/_build/
72 |
73 | # PyBuilder
74 | target/
75 |
76 | # Jupyter Notebook
77 | .ipynb_checkpoints
78 |
79 | # pyenv
80 | .python-version
81 |
82 | # celery beat schedule file
83 | celerybeat-schedule
84 |
85 | # SageMath parsed files
86 | *.sage.py
87 |
88 | # Environments
89 | .env
90 | .venv
91 | env/
92 | venv/
93 | ENV/
94 | env.bak/
95 | venv.bak/
96 |
97 | # Spyder project settings
98 | .spyderproject
99 | .spyproject
100 |
101 | # Rope project settings
102 | .ropeproject
103 |
104 | # mkdocs documentation
105 | /site
106 |
107 | # mypy
108 | .mypy_cache/
109 |
110 | # macOS specific files
111 | .DS_Store
112 |
--------------------------------------------------------------------------------
/dapr/actor/runtime/remindable.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | """
4 | Copyright 2023 The Dapr Authors
5 | Licensed under the Apache License, Version 2.0 (the "License");
6 | you may not use this file except in compliance with the License.
7 | You may obtain a copy of the License at
8 | http://www.apache.org/licenses/LICENSE-2.0
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 | """
15 |
16 | from abc import ABC, abstractmethod
17 | from datetime import timedelta
18 | from typing import Optional
19 |
20 |
21 | class Remindable(ABC):
22 | """An interface that actors must implement to consume reminders registered
23 | using :meth:`Remindable.register_reminder`.
24 | """
25 |
26 | @abstractmethod
27 | async def receive_reminder(
28 | self,
29 | name: str,
30 | state: bytes,
31 | due_time: timedelta,
32 | period: timedelta,
33 | ttl: Optional[timedelta] = None,
34 | ) -> None:
35 | """A callback which will be called when reminder is triggered.
36 |
37 | Args:
38 | name (str): the name of the reminder to register. the name must be unique per actor.
39 | state (bytes): the user state passed to the reminder invocation.
40 | due_time (datetime.timedelta): the amount of time to delay before invoking the reminder
41 | for the first time.
42 | period (datetime.timedelta): the time interval between reminder invocations
43 | after the first invocation.
44 | ttl (datetime.timedelta): the time interval before the reminder stops firing
45 | """
46 | ...
47 |
--------------------------------------------------------------------------------
/dapr/actor/id.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | """
4 | Copyright 2023 The Dapr Authors
5 | Licensed under the Apache License, Version 2.0 (the "License");
6 | you may not use this file except in compliance with the License.
7 | You may obtain a copy of the License at
8 | http://www.apache.org/licenses/LICENSE-2.0
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 | """
15 |
16 | import uuid
17 |
18 |
19 | class ActorId:
20 | """ActorId that represents the identity of an actor.
21 |
22 | Example::
23 |
24 | # create actorid with id 1
25 | actor_id = ActorId('1')
26 |
27 | # create random hex ActorId
28 | actor_random_id = ActorId.create_random_id()
29 |
30 | """
31 |
32 | def __init__(self, actor_id: str):
33 | if not isinstance(actor_id, str):
34 | raise TypeError(f'Argument actor_id must be of type str, not {type(actor_id)}')
35 | self._id = actor_id
36 |
37 | @classmethod
38 | def create_random_id(cls):
39 | """Creates new object of :class:`ActorId` with the random id value."""
40 | random_id = uuid.uuid1().hex
41 | return ActorId(random_id)
42 |
43 | @property
44 | def id(self) -> str:
45 | """Gets Actor ID string."""
46 | return self._id
47 |
48 | def __hash__(self):
49 | return hash(self._id)
50 |
51 | def __str__(self):
52 | return self._id
53 |
54 | def __eq__(self, other):
55 | if not other:
56 | return False
57 | return self._id == other.id
58 |
59 | def __ne__(self, other):
60 | if not other:
61 | return False
62 |
63 | return self._id != other.id
64 |
--------------------------------------------------------------------------------
/dapr/actor/actor_interface.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | """
4 | Copyright 2023 The Dapr Authors
5 | Licensed under the Apache License, Version 2.0 (the "License");
6 | you may not use this file except in compliance with the License.
7 | You may obtain a copy of the License at
8 | http://www.apache.org/licenses/LICENSE-2.0
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 | """
15 |
16 | from abc import ABC
17 | from typing import Optional
18 |
19 |
20 | class ActorInterface(ABC):
21 | """A base class that Dapr Actor inherits.
22 |
23 | Actor requires to inherit ActorInterface as a base class.
24 |
25 | Example::
26 |
27 | class DaprActorInterface(ActorInterface):
28 | @actormethod('DoActorMethod1')
29 | async def do_actor_method1(self, param):
30 | ...
31 |
32 | @actormethod('DoActorMethod2')
33 | async def do_actor_method2(self, param):
34 | ...
35 | """
36 |
37 | ...
38 |
39 |
40 | def actormethod(name: Optional[str] = None):
41 | """Decorate actor method to define the method invoked by the remote actor.
42 |
43 | This allows users to call the decorated name via the proxy client.
44 |
45 | Example::
46 |
47 | class DaprActorInterface(ActorInterface):
48 | @actormethod(name='DoActorCall')
49 | async def do_actor_call(self, param):
50 | ...
51 |
52 | Args:
53 | name (str, optional): the name of actor method.
54 | """
55 |
56 | def wrapper(funcobj):
57 | funcobj.__actormethod__ = name
58 | funcobj.__isabstractmethod__ = True
59 | return funcobj
60 |
61 | return wrapper
62 |
--------------------------------------------------------------------------------
/examples/invoke-http/README.md:
--------------------------------------------------------------------------------
1 | # Example - Invoke a service
2 |
3 | This example utilizes a receiver and a caller for the `invoke_method` functionality.
4 |
5 | > **Note:** Make sure to use the latest proto bindings
6 |
7 | ## Pre-requisites
8 |
9 | - [Dapr CLI and initialized environment](https://docs.dapr.io/getting-started)
10 | - [Install Python 3.8+](https://www.python.org/downloads/)
11 |
12 | ### Install requirements
13 |
14 | You can install dapr SDK package using pip command:
15 |
16 |
19 |
20 | ```sh
21 | pip3 install dapr Flask
22 | ```
23 |
24 |
25 |
26 | ## Run the example
27 |
28 | To run this example, the following code can be utilized:
29 |
30 | Start the receiver:
31 |
39 |
40 | ```bash
41 | dapr run --app-id=invoke-receiver --app-port=8088 --app-protocol http -- python3 invoke-receiver.py
42 | ```
43 |
44 |
45 | Start the caller:
46 |
60 |
61 | ```bash
62 | dapr run --app-id=invoke-caller -- python3 invoke-caller.py
63 | ```
64 |
65 |
66 | ## Cleanup
67 |
68 |
73 |
74 | ```bash
75 | dapr stop --app-id invoke-receiver
76 | ```
77 |
78 |
--------------------------------------------------------------------------------
/examples/configuration/configuration.py:
--------------------------------------------------------------------------------
1 | """
2 | dapr run --app-id configexample --resources-path components/ -- python3 configuration.py
3 | """
4 |
5 | import asyncio
6 | from time import sleep
7 |
8 | from dapr.clients import DaprClient
9 | from dapr.clients.grpc._response import ConfigurationResponse, ConfigurationWatcher
10 |
11 | configuration: ConfigurationWatcher = ConfigurationWatcher()
12 |
13 |
14 | def handler(id: str, resp: ConfigurationResponse):
15 | for key in resp.items:
16 | print(
17 | f'Subscribe key={key} value={resp.items[key].value} '
18 | f'version={resp.items[key].version} '
19 | f'metadata={resp.items[key].metadata}',
20 | flush=True,
21 | )
22 |
23 |
24 | async def executeConfiguration():
25 | with DaprClient() as d:
26 | storeName = 'configurationstore'
27 |
28 | keys = ['orderId1', 'orderId2']
29 |
30 | global configuration
31 |
32 | # Get one configuration by key.
33 | configuration = d.get_configuration(store_name=storeName, keys=keys, config_metadata={})
34 | for key in configuration.items:
35 | print(
36 | f'Got key={key} '
37 | f'value={configuration.items[key].value} '
38 | f'version={configuration.items[key].version} '
39 | f'metadata={configuration.items[key].metadata}',
40 | flush=True,
41 | )
42 |
43 | # Subscribe to configuration for keys {orderId1,orderId2}.
44 | id = d.subscribe_configuration(
45 | store_name=storeName, keys=keys, handler=handler, config_metadata={}
46 | )
47 | print('Subscription ID is', id, flush=True)
48 | sleep(10)
49 |
50 | # Unsubscribe from configuration
51 | isSuccess = d.unsubscribe_configuration(store_name=storeName, id=id)
52 | print(f'Unsubscribed successfully? {isSuccess}', flush=True)
53 |
54 |
55 | asyncio.run(executeConfiguration())
56 |
--------------------------------------------------------------------------------
/docs/actor/actor.runtime.rst:
--------------------------------------------------------------------------------
1 | actor.runtime package
2 | =====================
3 |
4 | Submodules
5 | ----------
6 |
7 |
8 | .. automodule:: actor.runtime.actor
9 | :members:
10 | :undoc-members:
11 | :show-inheritance:
12 |
13 |
14 | .. automodule:: actor.runtime._call_type
15 | :members:
16 | :undoc-members:
17 | :show-inheritance:
18 |
19 |
20 | .. automodule:: actor.runtime.config
21 | :members:
22 | :undoc-members:
23 | :show-inheritance:
24 |
25 |
26 | .. automodule:: actor.runtime.context
27 | :members:
28 | :undoc-members:
29 | :show-inheritance:
30 |
31 |
32 | .. automodule:: actor.runtime.manager
33 | :members:
34 | :undoc-members:
35 | :show-inheritance:
36 |
37 |
38 | .. automodule:: actor.runtime._method_context
39 | :members:
40 | :undoc-members:
41 | :show-inheritance:
42 |
43 |
44 | .. automodule:: actor.runtime.method_dispatcher
45 | :members:
46 | :undoc-members:
47 | :show-inheritance:
48 |
49 |
50 | .. automodule:: actor.runtime.remindable
51 | :members:
52 | :undoc-members:
53 | :show-inheritance:
54 |
55 |
56 | .. automodule:: actor.runtime._reminder_data
57 | :members:
58 | :undoc-members:
59 | :show-inheritance:
60 |
61 |
62 | .. automodule:: actor.runtime.runtime
63 | :members:
64 | :undoc-members:
65 | :show-inheritance:
66 |
67 |
68 | .. automodule:: actor.runtime.state_change
69 | :members:
70 | :undoc-members:
71 | :show-inheritance:
72 |
73 |
74 | .. automodule:: actor.runtime.state_manager
75 | :members:
76 | :undoc-members:
77 | :show-inheritance:
78 |
79 |
80 | .. automodule:: actor.runtime._state_provider
81 | :members:
82 | :undoc-members:
83 | :show-inheritance:
84 |
85 |
86 | .. automodule:: actor.runtime._timer_data
87 | :members:
88 | :undoc-members:
89 | :show-inheritance:
90 |
91 |
92 | Module contents
93 | ---------------
94 |
95 | .. automodule:: actor.runtime
96 | :members:
97 | :undoc-members:
98 | :show-inheritance:
99 |
--------------------------------------------------------------------------------
/examples/langgraph-checkpointer/agent.py:
--------------------------------------------------------------------------------
1 | from dapr.ext.langgraph import DaprCheckpointer
2 | from langchain_core.messages import HumanMessage, SystemMessage
3 | from langchain_ollama import ChatOllama
4 | from langgraph.graph import START, MessagesState, StateGraph
5 | from langgraph.prebuilt import ToolNode, tools_condition
6 |
7 |
8 | def add(a: int, b: int) -> int:
9 | """Adds a and b.
10 |
11 | Args:
12 | a: first int
13 | b: second int
14 | """
15 | return a + b
16 |
17 |
18 | def multiply(a: int, b: int) -> int:
19 | """Multiply a and b.
20 |
21 | Args:
22 | a: first int
23 | b: second int
24 | """
25 | return a * b
26 |
27 |
28 | tools = [add, multiply]
29 | llm = ChatOllama(model='llama3.2:latest')
30 | llm_with_tools = llm.bind_tools(tools)
31 |
32 | sys_msg = SystemMessage(
33 | content='You are a helpful assistant tasked with performing arithmetic on a set of inputs.'
34 | )
35 |
36 |
37 | def assistant(state: MessagesState):
38 | return {'messages': [llm_with_tools.invoke([sys_msg] + state['messages'])]}
39 |
40 |
41 | builder = StateGraph(MessagesState)
42 |
43 | builder.add_node('assistant', assistant)
44 | builder.add_node('tools', ToolNode(tools))
45 |
46 | builder.add_edge(START, 'assistant')
47 | builder.add_conditional_edges(
48 | 'assistant',
49 | tools_condition,
50 | )
51 | builder.add_edge('tools', 'assistant')
52 |
53 | memory = DaprCheckpointer(store_name='statestore', key_prefix='dapr')
54 | react_graph_memory = builder.compile(checkpointer=memory)
55 |
56 | config = {'configurable': {'thread_id': '1'}}
57 |
58 | messages = [HumanMessage(content='Add 3 and 4.')]
59 | messages = react_graph_memory.invoke({'messages': messages}, config)
60 | for m in messages['messages']:
61 | m.pretty_print()
62 |
63 | messages = [HumanMessage(content='Multiply the result by 2.')]
64 | messages = react_graph_memory.invoke({'messages': messages}, config)
65 | for m in messages['messages']:
66 | m.pretty_print()
67 |
--------------------------------------------------------------------------------
/examples/pubsub-streaming-async/publisher.py:
--------------------------------------------------------------------------------
1 | # ------------------------------------------------------------
2 | # Copyright 2022 The Dapr Authors
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | # http://www.apache.org/licenses/LICENSE-2.0
7 | # Unless required by applicable law or agreed to in writing, software
8 | # distributed under the License is distributed on an "AS IS" BASIS,
9 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10 | # See the License for the specific language governing permissions and
11 | # limitations under the License.
12 | # ------------------------------------------------------------
13 | import argparse
14 | import asyncio
15 | import json
16 |
17 | from dapr.aio.clients import DaprClient
18 |
19 | parser = argparse.ArgumentParser(description='Publish events to a Dapr pub/sub topic.')
20 | parser.add_argument('--topic', type=str, required=True, help='The topic name to publish to.')
21 | args = parser.parse_args()
22 |
23 | topic_name = args.topic
24 |
25 |
26 | async def publish_events():
27 | """
28 | Publishes events to a pubsub topic asynchronously
29 | """
30 |
31 | async with DaprClient() as d:
32 | id = 0
33 | while id < 5:
34 | id += 1
35 | req_data = {'id': id, 'message': 'hello world'}
36 |
37 | # Create a typed message with content type and body
38 | await d.publish_event(
39 | pubsub_name='pubsub',
40 | topic_name=topic_name,
41 | data=json.dumps(req_data),
42 | data_content_type='application/json',
43 | publish_metadata={'ttlInSeconds': '100', 'rawPayload': 'false'},
44 | )
45 |
46 | # Print the request
47 | print(req_data, flush=True)
48 |
49 | await asyncio.sleep(1)
50 |
51 |
52 | asyncio.run(publish_events())
53 |
--------------------------------------------------------------------------------
/dapr/actor/runtime/state_change.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | """
4 | Copyright 2023 The Dapr Authors
5 | Licensed under the Apache License, Version 2.0 (the "License");
6 | you may not use this file except in compliance with the License.
7 | You may obtain a copy of the License at
8 | http://www.apache.org/licenses/LICENSE-2.0
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 | """
15 |
16 | from enum import Enum
17 | from typing import Generic, Optional, TypeVar
18 |
19 | T = TypeVar('T')
20 |
21 |
22 | class StateChangeKind(Enum):
23 | """A enumeration that represents the kind of state change for an actor state
24 | when saves change is called to a set of actor states.
25 | """
26 |
27 | # No change in state
28 | none = 0
29 | # The state needs to be added
30 | add = 1
31 | # The state needs to be updated
32 | update = 2
33 | # The state needs to be removed
34 | remove = 3
35 |
36 |
37 | class ActorStateChange(Generic[T]):
38 | def __init__(
39 | self,
40 | state_name: str,
41 | value: T,
42 | change_kind: StateChangeKind,
43 | ttl_in_seconds: Optional[int] = None,
44 | ):
45 | self._state_name = state_name
46 | self._value = value
47 | self._change_kind = change_kind
48 | self._ttl_in_seconds = ttl_in_seconds
49 |
50 | @property
51 | def state_name(self) -> str:
52 | return self._state_name
53 |
54 | @property
55 | def value(self) -> T:
56 | return self._value
57 |
58 | @property
59 | def change_kind(self) -> StateChangeKind:
60 | return self._change_kind
61 |
62 | @property
63 | def ttl_in_seconds(self) -> Optional[int]:
64 | return self._ttl_in_seconds
65 |
--------------------------------------------------------------------------------
/dapr/actor/runtime/method_dispatcher.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | """
4 | Copyright 2023 The Dapr Authors
5 | Licensed under the Apache License, Version 2.0 (the "License");
6 | you may not use this file except in compliance with the License.
7 | You may obtain a copy of the License at
8 | http://www.apache.org/licenses/LICENSE-2.0
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 | """
15 |
16 | from typing import Any, Dict, List
17 |
18 | from dapr.actor.runtime._type_information import ActorTypeInformation
19 | from dapr.actor.runtime._type_utils import get_dispatchable_attrs
20 | from dapr.actor.runtime.actor import Actor
21 |
22 |
23 | class ActorMethodDispatcher:
24 | def __init__(self, type_info: ActorTypeInformation):
25 | self._dispatch_mapping = get_dispatchable_attrs(type_info.implementation_type)
26 |
27 | async def dispatch(self, actor: Actor, name: str, *args, **kwargs) -> Any:
28 | self._check_name_exist(name)
29 | return await getattr(actor, self._dispatch_mapping[name]['method_name'])(*args, **kwargs)
30 |
31 | def get_arg_names(self, name: str) -> List[str]:
32 | self._check_name_exist(name)
33 | return self._dispatch_mapping[name]['arg_names']
34 |
35 | def get_arg_types(self, name: str) -> List[Any]:
36 | self._check_name_exist(name)
37 | return self._dispatch_mapping[name]['arg_types']
38 |
39 | def get_return_type(self, name: str) -> Dict[str, Any]:
40 | self._check_name_exist(name)
41 | return self._dispatch_mapping[name]['return_types']
42 |
43 | def _check_name_exist(self, name: str):
44 | if name not in self._dispatch_mapping:
45 | raise AttributeError(f'type object {self.__class__.__name__} has no method {name}')
46 |
--------------------------------------------------------------------------------
/tests/actor/test_type_information.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | """
4 | Copyright 2021 The Dapr Authors
5 | Licensed under the Apache License, Version 2.0 (the "License");
6 | you may not use this file except in compliance with the License.
7 | You may obtain a copy of the License at
8 | http://www.apache.org/licenses/LICENSE-2.0
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 | """
15 |
16 | import unittest
17 |
18 | from dapr.actor.runtime._type_information import ActorTypeInformation
19 | from tests.actor.fake_actor_classes import (
20 | FakeActorCls1Interface,
21 | FakeActorCls2Interface,
22 | FakeMultiInterfacesActor,
23 | FakeSimpleActor,
24 | ReentrantActorInterface,
25 | )
26 |
27 |
28 | class ActorTypeInformationTests(unittest.TestCase):
29 | def setUp(self):
30 | pass
31 |
32 | def test_actor_type_name(self):
33 | type_info = ActorTypeInformation.create(FakeSimpleActor)
34 | self.assertEqual(FakeSimpleActor.__name__, type_info.type_name)
35 |
36 | def test_implementation_type_returns_correct_type(self):
37 | type_info = ActorTypeInformation.create(FakeSimpleActor)
38 | self.assertEqual(FakeSimpleActor, type_info.implementation_type)
39 |
40 | def test_actor_interfaces_returns_actor_classes(self):
41 | type_info = ActorTypeInformation.create(FakeMultiInterfacesActor)
42 |
43 | self.assertEqual(FakeMultiInterfacesActor.__name__, type_info.type_name)
44 | self.assertEqual(3, len(type_info.actor_interfaces))
45 | self.assertTrue(type_info.actor_interfaces.index(FakeActorCls1Interface) >= 0)
46 | self.assertTrue(type_info.actor_interfaces.index(FakeActorCls2Interface) >= 0)
47 | self.assertTrue(type_info.actor_interfaces.index(ReentrantActorInterface) >= 0)
48 |
--------------------------------------------------------------------------------
/examples/workflow/cross-app2.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Copyright 2025 The Dapr Authors
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | # http://www.apache.org/licenses/LICENSE-2.0
7 | # Unless required by applicable law or agreed to in writing, software
8 | # distributed under the License is distributed on an "AS IS" BASIS,
9 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10 | # See the License for the specific language governing permissions and
11 | # limitations under the License.
12 |
13 | import os
14 | import time
15 | from datetime import timedelta
16 |
17 | import dapr.ext.workflow as wf
18 | from durabletask.task import TaskFailedError
19 |
20 | wfr = wf.WorkflowRuntime()
21 |
22 |
23 | @wfr.workflow
24 | def app2_workflow(ctx: wf.DaprWorkflowContext):
25 | print('app2 - received workflow call', flush=True)
26 | if os.getenv('ERROR_WORKFLOW_MODE', 'false') == 'true':
27 | print('app2 - raising error in workflow due to error mode being enabled', flush=True)
28 | raise ValueError('Error in workflow due to error mode being enabled')
29 | print('app2 - triggering app3 activity', flush=True)
30 | try:
31 | retry_policy = wf.RetryPolicy(
32 | max_number_of_attempts=2,
33 | first_retry_interval=timedelta(milliseconds=100),
34 | max_retry_interval=timedelta(seconds=3),
35 | )
36 | yield ctx.call_activity(
37 | 'app3_activity', input=None, app_id='wfexample3', retry_policy=retry_policy
38 | )
39 | print('app2 - received activity result', flush=True)
40 | except TaskFailedError:
41 | print('app2 - received activity error from app3', flush=True)
42 |
43 | print('app2 - returning workflow result', flush=True)
44 | return 2
45 |
46 |
47 | if __name__ == '__main__':
48 | wfr.start()
49 | time.sleep(15) # wait for workflow runtime to start
50 | wfr.shutdown()
51 |
--------------------------------------------------------------------------------
/dapr/actor/runtime/_method_context.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | """
4 | Copyright 2023 The Dapr Authors
5 | Licensed under the Apache License, Version 2.0 (the "License");
6 | you may not use this file except in compliance with the License.
7 | You may obtain a copy of the License at
8 | http://www.apache.org/licenses/LICENSE-2.0
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 | """
15 |
16 | from dapr.actor.runtime._call_type import ActorCallType
17 |
18 |
19 | class ActorMethodContext:
20 | """A Actor method context that contains method information invoked
21 | by :class:`ActorRuntime`.
22 | """
23 |
24 | def __init__(self, method_name: str, call_type: ActorCallType):
25 | self._method_name = method_name
26 | self._calltype = call_type
27 |
28 | @property
29 | def method_name(self) -> str:
30 | """Gets the method name."""
31 | return self._method_name
32 |
33 | @property
34 | def call_type(self) -> ActorCallType:
35 | """Gets :class:`ActorCallType` for this method."""
36 | return self._calltype
37 |
38 | @classmethod
39 | def create_for_actor(cls, method_name: str):
40 | """Creates :class:`ActorMethodContext` object for actor method."""
41 | return ActorMethodContext(method_name, ActorCallType.actor_interface_method)
42 |
43 | @classmethod
44 | def create_for_timer(cls, method_name: str):
45 | """Creates :class:`ActorMethodContext` object for timer_method."""
46 | return ActorMethodContext(method_name, ActorCallType.timer_method)
47 |
48 | @classmethod
49 | def create_for_reminder(cls, method_name: str):
50 | """Creates :class:`ActorMethodContext` object for reminder_method."""
51 | return ActorMethodContext(method_name, ActorCallType.reminder_method)
52 |
--------------------------------------------------------------------------------
/tests/clients/test_dapr_grpc_response_async.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | """
4 | Copyright 2023 The Dapr Authors
5 | Licensed under the Apache License, Version 2.0 (the "License");
6 | you may not use this file except in compliance with the License.
7 | You may obtain a copy of the License at
8 | http://www.apache.org/licenses/LICENSE-2.0
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 | """
15 |
16 | import unittest
17 |
18 | from dapr.aio.clients.grpc._response import DecryptResponse, EncryptResponse
19 | from dapr.proto import api_v1, common_v1
20 |
21 |
22 | class CryptoResponseAsyncTests(unittest.IsolatedAsyncioTestCase):
23 | async def response_stream(self):
24 | stream1 = common_v1.StreamPayload(data=b'hello', seq=0)
25 | stream2 = common_v1.StreamPayload(data=b' dapr', seq=1)
26 | for strm in (stream1, stream2):
27 | yield api_v1.EncryptResponse(payload=strm)
28 |
29 | async def test_encrypt_response_read_bytes(self):
30 | resp = EncryptResponse(stream=self.response_stream())
31 | self.assertEqual(await resp.read(5), b'hello')
32 | self.assertEqual(await resp.read(5), b' dapr')
33 |
34 | async def test_encrypt_response_read_all(self):
35 | resp = EncryptResponse(stream=self.response_stream())
36 | self.assertEqual(await resp.read(), b'hello dapr')
37 |
38 | async def test_decrypt_response_read_bytes(self):
39 | resp = DecryptResponse(stream=self.response_stream())
40 | self.assertEqual(await resp.read(5), b'hello')
41 | self.assertEqual(await resp.read(5), b' dapr')
42 |
43 | async def test_decrypt_response_read_all(self):
44 | resp = DecryptResponse(stream=self.response_stream())
45 | self.assertEqual(await resp.read(), b'hello dapr')
46 |
47 |
48 | if __name__ == '__main__':
49 | unittest.main()
50 |
--------------------------------------------------------------------------------
/examples/workflow/cross-app1.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Copyright 2025 The Dapr Authors
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | # http://www.apache.org/licenses/LICENSE-2.0
7 | # Unless required by applicable law or agreed to in writing, software
8 | # distributed under the License is distributed on an "AS IS" BASIS,
9 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10 | # See the License for the specific language governing permissions and
11 | # limitations under the License.
12 |
13 | import time
14 | from datetime import timedelta
15 |
16 | import dapr.ext.workflow as wf
17 | from durabletask.task import TaskFailedError
18 |
19 | wfr = wf.WorkflowRuntime()
20 |
21 |
22 | @wfr.workflow
23 | def app1_workflow(ctx: wf.DaprWorkflowContext):
24 | print('app1 - received workflow call', flush=True)
25 | print('app1 - triggering app2 workflow', flush=True)
26 |
27 | try:
28 | retry_policy = wf.RetryPolicy(
29 | max_number_of_attempts=2,
30 | first_retry_interval=timedelta(milliseconds=100),
31 | max_retry_interval=timedelta(seconds=3),
32 | )
33 | yield ctx.call_child_workflow(
34 | workflow='app2_workflow',
35 | input=None,
36 | app_id='wfexample2',
37 | retry_policy=retry_policy,
38 | )
39 | print('app1 - received workflow result', flush=True)
40 | except TaskFailedError:
41 | print('app1 - received workflow error from app2', flush=True)
42 |
43 | print('app1 - returning workflow result', flush=True)
44 | return 1
45 |
46 |
47 | if __name__ == '__main__':
48 | wfr.start()
49 | time.sleep(10) # wait for workflow runtime to start
50 |
51 | wf_client = wf.DaprWorkflowClient()
52 | print('app1 - triggering app1 workflow', flush=True)
53 | instance_id = wf_client.schedule_new_workflow(workflow=app1_workflow)
54 |
55 | # Wait for the workflow to complete
56 | time.sleep(7)
57 |
58 | wfr.shutdown()
59 |
--------------------------------------------------------------------------------
/examples/distributed_lock/lock.py:
--------------------------------------------------------------------------------
1 | # ------------------------------------------------------------
2 | # Copyright 2021 The Dapr Authors
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | # http://www.apache.org/licenses/LICENSE-2.0
7 | # Unless required by applicable law or agreed to in writing, software
8 | # distributed under the License is distributed on an "AS IS" BASIS,
9 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10 | # See the License for the specific language governing permissions and
11 | # limitations under the License.
12 | # ------------------------------------------------------------
13 |
14 | import warnings
15 |
16 | from dapr.clients import DaprClient
17 |
18 |
19 | def main():
20 | # Lock parameters
21 | store_name = 'lockstore' # as defined in components/lockstore.yaml
22 | resource_id = 'example-lock-resource'
23 | client_id = 'example-client-id'
24 | expiry_in_seconds = 60
25 |
26 | with DaprClient() as dapr:
27 | print('Will try to acquire a lock from lock store named [%s]' % store_name)
28 | print('The lock is for a resource named [%s]' % resource_id)
29 | print('The client identifier is [%s]' % client_id)
30 | print('The lock will will expire in %s seconds.' % expiry_in_seconds)
31 |
32 | with dapr.try_lock(store_name, resource_id, client_id, expiry_in_seconds) as lock_result:
33 | assert lock_result.success, 'Failed to acquire the lock. Aborting.'
34 | print('Lock acquired successfully!!!')
35 |
36 | # At this point the lock was released - by magic of the `with` clause ;)
37 | unlock_result = dapr.unlock(store_name, resource_id, client_id)
38 | print('We already released the lock so unlocking will not work.')
39 | print('We tried to unlock it anyway and got back [%s]' % unlock_result.status)
40 |
41 |
42 | if __name__ == '__main__':
43 | # Suppress "The Distributed Lock API is an Alpha" warnings
44 | warnings.simplefilter('ignore')
45 | main()
46 |
--------------------------------------------------------------------------------
/tests/clients/test_client_interceptor.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | """
4 | Copyright 2021 The Dapr Authors
5 | Licensed under the Apache License, Version 2.0 (the "License");
6 | you may not use this file except in compliance with the License.
7 | You may obtain a copy of the License at
8 | http://www.apache.org/licenses/LICENSE-2.0
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 | """
15 |
16 | import unittest
17 |
18 | from dapr.clients.grpc.interceptors import DaprClientInterceptor, _ClientCallDetails
19 |
20 |
21 | class DaprClientInterceptorTests(unittest.TestCase):
22 | def setUp(self):
23 | self._fake_request = 'fake request'
24 |
25 | def fake_continuation(self, call_details, request):
26 | return call_details
27 |
28 | def test_intercept_unary_unary_single_header(self):
29 | interceptor = DaprClientInterceptor([('api-token', 'test-token')])
30 | call_details = _ClientCallDetails('method1', 10, None, None, None, None)
31 | response = interceptor.intercept_unary_unary(
32 | self.fake_continuation, call_details, self._fake_request
33 | )
34 |
35 | self.assertIsNotNone(response)
36 | self.assertEqual(1, len(response.metadata))
37 | self.assertEqual([('api-token', 'test-token')], response.metadata)
38 |
39 | def test_intercept_unary_unary_existing_metadata(self):
40 | interceptor = DaprClientInterceptor([('api-token', 'test-token')])
41 | call_details = _ClientCallDetails('method1', 10, [('header', 'value')], None, None, None)
42 | response = interceptor.intercept_unary_unary(
43 | self.fake_continuation, call_details, self._fake_request
44 | )
45 |
46 | self.assertIsNotNone(response)
47 | self.assertEqual(2, len(response.metadata))
48 | self.assertEqual([('header', 'value'), ('api-token', 'test-token')], response.metadata)
49 |
--------------------------------------------------------------------------------
/examples/grpc_proxying/helloworld_service_pb2.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Generated by the protocol buffer compiler. DO NOT EDIT!
3 | # source: helloworld_service.proto
4 | """Generated protocol buffer code."""
5 |
6 | from google.protobuf import descriptor as _descriptor
7 | from google.protobuf import descriptor_pool as _descriptor_pool
8 | from google.protobuf import message as _message
9 | from google.protobuf import reflection as _reflection
10 | from google.protobuf import symbol_database as _symbol_database
11 |
12 | # @@protoc_insertion_point(imports)
13 |
14 | _sym_db = _symbol_database.Default()
15 |
16 |
17 | DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(
18 | b'\n\x18helloworld_service.proto"\x1c\n\x0cHelloRequest\x12\x0c\n\x04name\x18\x01 \x01(\t"\x1d\n\nHelloReply\x12\x0f\n\x07message\x18\x01 \x01(\t2=\n\x11HelloWorldService\x12(\n\x08SayHello\x12\r.HelloRequest\x1a\x0b.HelloReply"\x00\x62\x06proto3'
19 | )
20 |
21 |
22 | _HELLOREQUEST = DESCRIPTOR.message_types_by_name['HelloRequest']
23 | _HELLOREPLY = DESCRIPTOR.message_types_by_name['HelloReply']
24 | HelloRequest = _reflection.GeneratedProtocolMessageType(
25 | 'HelloRequest',
26 | (_message.Message,),
27 | {
28 | 'DESCRIPTOR': _HELLOREQUEST,
29 | '__module__': 'helloworld_service_pb2',
30 | # @@protoc_insertion_point(class_scope:HelloRequest)
31 | },
32 | )
33 | _sym_db.RegisterMessage(HelloRequest)
34 |
35 | HelloReply = _reflection.GeneratedProtocolMessageType(
36 | 'HelloReply',
37 | (_message.Message,),
38 | {
39 | 'DESCRIPTOR': _HELLOREPLY,
40 | '__module__': 'helloworld_service_pb2',
41 | # @@protoc_insertion_point(class_scope:HelloReply)
42 | },
43 | )
44 | _sym_db.RegisterMessage(HelloReply)
45 |
46 | _HELLOWORLDSERVICE = DESCRIPTOR.services_by_name['HelloWorldService']
47 | if _descriptor._USE_C_DESCRIPTORS == False:
48 | DESCRIPTOR._options = None
49 | _HELLOREQUEST._serialized_start = 28
50 | _HELLOREQUEST._serialized_end = 56
51 | _HELLOREPLY._serialized_start = 58
52 | _HELLOREPLY._serialized_end = 87
53 | _HELLOWORLDSERVICE._serialized_start = 89
54 | _HELLOWORLDSERVICE._serialized_end = 150
55 | # @@protoc_insertion_point(module_scope)
56 |
--------------------------------------------------------------------------------
/tests/actor/test_timer_data.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | """
4 | Copyright 2021 The Dapr Authors
5 | Licensed under the Apache License, Version 2.0 (the "License");
6 | you may not use this file except in compliance with the License.
7 | You may obtain a copy of the License at
8 | http://www.apache.org/licenses/LICENSE-2.0
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 | """
15 |
16 | import unittest
17 | from datetime import timedelta
18 | from typing import Any
19 |
20 | from dapr.actor.runtime._timer_data import ActorTimerData
21 |
22 |
23 | class ActorTimerDataTests(unittest.TestCase):
24 | def test_timer_data(self):
25 | def my_callback(input: Any):
26 | print(input)
27 |
28 | timer = ActorTimerData(
29 | 'timer_name',
30 | my_callback,
31 | 'called',
32 | timedelta(seconds=2),
33 | timedelta(seconds=1),
34 | timedelta(seconds=3),
35 | )
36 | self.assertEqual('timer_name', timer.timer_name)
37 | self.assertEqual('my_callback', timer.callback)
38 | self.assertEqual('called', timer.state)
39 | self.assertEqual(timedelta(seconds=2), timer.due_time)
40 | self.assertEqual(timedelta(seconds=1), timer.period)
41 | self.assertEqual(timedelta(seconds=3), timer.ttl)
42 |
43 | def test_as_dict(self):
44 | def my_callback(input: Any):
45 | print(input)
46 |
47 | timer = ActorTimerData(
48 | 'timer_name',
49 | my_callback,
50 | 'called',
51 | timedelta(seconds=1),
52 | timedelta(seconds=1),
53 | timedelta(seconds=1),
54 | )
55 | expected = {
56 | 'callback': 'my_callback',
57 | 'data': 'called',
58 | 'dueTime': timedelta(seconds=1),
59 | 'period': timedelta(seconds=1),
60 | 'ttl': timedelta(seconds=1),
61 | }
62 | self.assertDictEqual(expected, timer.as_dict())
63 |
--------------------------------------------------------------------------------
/examples/configuration/README.md:
--------------------------------------------------------------------------------
1 | # Example - Get Configuration
2 |
3 | This example demonstrates the Configuration APIs in Dapr.
4 | It demonstrates the following APIs:
5 | - **configuration**: Get configuration from statestore
6 |
7 | > **Note:** Make sure to use the latest proto bindings
8 |
9 | ## Pre-requisites
10 |
11 | - [Dapr CLI and initialized environment](https://docs.dapr.io/getting-started)
12 | - [Install Python 3.9+](https://www.python.org/downloads/)
13 |
14 | ## Install Dapr python-SDK
15 |
16 |
17 | ```bash
18 | pip3 install dapr dapr-ext-grpc
19 | ```
20 |
21 | ## Store the configuration in configurationstore
22 |
29 |
30 | ```bash
31 | docker exec dapr_redis redis-cli SET orderId1 "100||1"
32 | docker exec dapr_redis redis-cli SET orderId2 "200||1"
33 | ```
34 |
35 |
36 |
37 | ## Run configuration example
38 |
39 | Change directory to this folder:
40 | ```bash
41 | cd examples/configuration
42 | ```
43 |
44 | To run this example, use the following command:
45 |
46 |
58 |
59 | ```bash
60 | dapr run --app-id configexample --resources-path components/ -- python3 configuration.py
61 | ```
62 |
63 |
64 |
70 |
71 | ```bash
72 | docker exec dapr_redis redis-cli SET orderId2 "210||2"
73 | ```
74 |
75 |
76 | You should be able to see the following output:
77 | ```
78 | == APP == Got key=orderId1 value=100 version=1
79 | == APP == Got key=orderId2 value=200 version=1
80 | == APP == Subscribe key=orderId2 value=210 version=2
81 | ```
82 |
--------------------------------------------------------------------------------
/examples/state_store_query/dataset.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "key": "1",
4 | "value": {
5 | "person": {
6 | "org": "Dev Ops",
7 | "id": 1036
8 | },
9 | "city": "Seattle",
10 | "state": "WA"
11 | }
12 | },
13 | {
14 | "key": "2",
15 | "value": {
16 | "person": {
17 | "org": "Hardware",
18 | "id": 1028
19 | },
20 | "city": "Portland",
21 | "state": "OR"
22 | }
23 | },
24 | {
25 | "key": "3",
26 | "value": {
27 | "person": {
28 | "org": "Finance",
29 | "id": 1071
30 | },
31 | "city": "Sacramento",
32 | "state": "CA"
33 | }
34 | },
35 | {
36 | "key": "4",
37 | "value": {
38 | "person": {
39 | "org": "Dev Ops",
40 | "id": 1042
41 | },
42 | "city": "Spokane",
43 | "state": "WA"
44 | }
45 | },
46 | {
47 | "key": "5",
48 | "value": {
49 | "person": {
50 | "org": "Hardware",
51 | "id": 1007
52 | },
53 | "city": "Los Angeles",
54 | "state": "CA"
55 | }
56 | },
57 | {
58 | "key": "6",
59 | "value": {
60 | "person": {
61 | "org": "Finance",
62 | "id": 1094
63 | },
64 | "city": "Eugene",
65 | "state": "OR"
66 | }
67 | },
68 | {
69 | "key": "7",
70 | "value": {
71 | "person": {
72 | "org": "Dev Ops",
73 | "id": 1015
74 | },
75 | "city": "San Francisco",
76 | "state": "CA"
77 | }
78 | },
79 | {
80 | "key": "8",
81 | "value": {
82 | "person": {
83 | "org": "Hardware",
84 | "id": 1077
85 | },
86 | "city": "Redmond",
87 | "state": "WA"
88 | }
89 | },
90 | {
91 | "key": "9",
92 | "value": {
93 | "person": {
94 | "org": "Finance",
95 | "id": 1002
96 | },
97 | "city": "San Diego",
98 | "state": "CA"
99 | }
100 | },
101 | {
102 | "key": "10",
103 | "value": {
104 | "person": {
105 | "org": "Dev Ops",
106 | "id": 1054
107 | },
108 | "city": "New York",
109 | "state": "NY"
110 | }
111 | }
112 | ]
113 |
--------------------------------------------------------------------------------
/setup.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | """
4 | Copyright 2021 The Dapr Authors
5 | Licensed under the Apache License, Version 2.0 (the "License");
6 | you may not use this file except in compliance with the License.
7 | You may obtain a copy of the License at
8 | http://www.apache.org/licenses/LICENSE-2.0
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 | """
15 |
16 | import os
17 |
18 | from setuptools import setup
19 |
20 | # Load version in dapr package.
21 | version_info = {}
22 | with open('dapr/version/version.py') as fp:
23 | exec(fp.read(), version_info)
24 | __version__ = version_info['__version__']
25 |
26 |
27 | def is_release():
28 | return '.dev' not in __version__
29 |
30 |
31 | name = 'dapr'
32 | version = __version__
33 | description = 'The official release of Dapr Python SDK.'
34 | long_description = """
35 | Dapr is a portable, serverless, event-driven runtime that makes it easy for developers to
36 | build resilient, stateless and stateful microservices that run on the cloud and edge and
37 | embraces the diversity of languages and developer frameworks.
38 |
39 | Dapr codifies the best practices for building microservice applications into open,
40 | independent, building blocks that enable you to build portable applications with the language
41 | and framework of your choice. Each building block is independent and you can use one, some,
42 | or all of them in your application.
43 | """.lstrip()
44 |
45 | # Get build number from GITHUB_RUN_NUMBER environment variable
46 | build_number = os.environ.get('GITHUB_RUN_NUMBER', '0')
47 |
48 | if not is_release():
49 | name += '-dev'
50 | version = f'{__version__}{build_number}'
51 | description = 'The developmental release for Dapr Python SDK.'
52 | long_description = 'This is the developmental release for Dapr Python SDK.'
53 |
54 | print(f'package name: {name}, version: {version}', flush=True)
55 |
56 |
57 | setup(
58 | name=name,
59 | version=version,
60 | description=description,
61 | long_description=long_description,
62 | package_data={'': ['py.typed']},
63 | )
64 |
--------------------------------------------------------------------------------
/examples/metadata/app.py:
--------------------------------------------------------------------------------
1 | # ------------------------------------------------------------
2 | # Copyright 2021 The Dapr Authors
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | # http://www.apache.org/licenses/LICENSE-2.0
7 | # Unless required by applicable law or agreed to in writing, software
8 | # distributed under the License is distributed on an "AS IS" BASIS,
9 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10 | # See the License for the specific language governing permissions and
11 | # limitations under the License.
12 | # ------------------------------------------------------------
13 |
14 | from dapr.clients import DaprClient
15 |
16 |
17 | def main():
18 | extended_attribute_name = 'is-this-our-metadata-example'
19 |
20 | with DaprClient() as dapr:
21 | print('First, we will assign a new custom label to Dapr sidecar')
22 | # We do this so example can be made deterministic across
23 | # multiple invocations.
24 | original_value = 'yes'
25 | dapr.set_metadata(extended_attribute_name, original_value)
26 |
27 | print("Now, we will fetch the sidecar's metadata")
28 | metadata = dapr.get_metadata()
29 | old_value = metadata.extended_metadata[extended_attribute_name]
30 |
31 | print('And this is what we got:')
32 | print(f' application_id: {metadata.application_id}')
33 | print(f' active_actors_count: {metadata.active_actors_count}')
34 | print(' registered_components:')
35 | for name, type, version, caps in sorted(metadata.registered_components):
36 | print(f' name={name} type={type} version={version} capabilities={sorted(caps)}')
37 |
38 | print('We will update our custom label value and check it was persisted')
39 | dapr.set_metadata(extended_attribute_name, 'You bet it is!')
40 | metadata = dapr.get_metadata()
41 | new_value = metadata.extended_metadata[extended_attribute_name]
42 | print('We added a custom label named [%s]' % extended_attribute_name)
43 | print('Its old value was [%s] but now it is [%s]' % (old_value, new_value))
44 |
45 | print('And we are done 👋', flush=True)
46 |
47 |
48 | if __name__ == '__main__':
49 | main()
50 |
--------------------------------------------------------------------------------
/ext/flask_dapr/setup.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | """
4 | Copyright 2023 The Dapr Authors
5 | Licensed under the Apache License, Version 2.0 (the "License");
6 | you may not use this file except in compliance with the License.
7 | You may obtain a copy of the License at
8 | http://www.apache.org/licenses/LICENSE-2.0
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 | """
15 |
16 | import os
17 |
18 | from setuptools import setup
19 |
20 | # Load version in dapr package.
21 | version_info = {}
22 | with open('flask_dapr/version.py') as fp:
23 | exec(fp.read(), version_info)
24 | __version__ = version_info['__version__']
25 |
26 |
27 | def is_release():
28 | return '.dev' not in __version__
29 |
30 |
31 | name = 'flask-dapr'
32 | version = __version__
33 | description = 'The official release of Dapr Python SDK Flask Extension.'
34 | long_description = """
35 | This is the Flask extension for Dapr.
36 |
37 | Dapr is a portable, serverless, event-driven runtime that makes it easy for developers to
38 | build resilient, stateless and stateful microservices that run on the cloud and edge and
39 | embraces the diversity of languages and developer frameworks.
40 |
41 | Dapr codifies the best practices for building microservice applications into open,
42 | independent, building blocks that enable you to build portable applications with the language
43 | and framework of your choice. Each building block is independent and you can use one, some,
44 | or all of them in your application.
45 | """.lstrip()
46 |
47 | # Get build number from GITHUB_RUN_NUMBER environment variable
48 | build_number = os.environ.get('GITHUB_RUN_NUMBER', '0')
49 |
50 | if not is_release():
51 | name += '-dev'
52 | version = f'{__version__}{build_number}'
53 | description = 'The developmental release for Dapr Python SDK Flask.'
54 | long_description = 'This is the developmental release for Dapr Python SDK Flask.'
55 |
56 | print(f'package name: {name}, version: {version}', flush=True)
57 |
58 |
59 | setup(
60 | name=name,
61 | version=version,
62 | description=description,
63 | long_description=long_description,
64 | )
65 |
--------------------------------------------------------------------------------
/tests/clients/test_timeout_interceptor_async.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | """
4 | Copyright 2024 The Dapr Authors
5 | Licensed under the Apache License, Version 2.0 (the "License");
6 | you may not use this file except in compliance with the License.
7 | You may obtain a copy of the License at
8 | http://www.apache.org/licenses/LICENSE-2.0
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 | """
15 |
16 | import unittest
17 | from unittest.mock import Mock, patch
18 |
19 | from dapr.aio.clients.grpc.interceptors import DaprClientTimeoutInterceptorAsync
20 | from dapr.conf import settings
21 |
22 |
23 | class DaprClientTimeoutInterceptorAsyncTests(unittest.TestCase):
24 | def test_intercept_unary_unary_with_timeout(self):
25 | continuation = Mock()
26 | request = Mock()
27 | client_call_details = Mock()
28 | client_call_details.method = 'method'
29 | client_call_details.timeout = 10
30 | client_call_details.metadata = 'metadata'
31 | client_call_details.credentials = 'credentials'
32 | client_call_details.wait_for_ready = 'wait_for_ready'
33 |
34 | DaprClientTimeoutInterceptorAsync().intercept_unary_unary(
35 | continuation, client_call_details, request
36 | )
37 | continuation.assert_called_once_with(client_call_details, request)
38 |
39 | @patch.object(settings, 'DAPR_API_TIMEOUT_SECONDS', 7)
40 | def test_intercept_unary_unary_without_timeout(self):
41 | continuation = Mock()
42 | request = Mock()
43 | client_call_details = Mock()
44 | client_call_details.method = 'method'
45 | client_call_details.timeout = None
46 | client_call_details.metadata = 'metadata'
47 | client_call_details.credentials = 'credentials'
48 | client_call_details.wait_for_ready = 'wait_for_ready'
49 |
50 | DaprClientTimeoutInterceptorAsync().intercept_unary_unary(
51 | continuation, client_call_details, request
52 | )
53 | called_client_call_details = continuation.call_args[0][0]
54 | self.assertEqual(7, called_client_call_details.timeout)
55 |
--------------------------------------------------------------------------------
/ext/dapr-ext-grpc/setup.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | """
4 | Copyright 2023 The Dapr Authors
5 | Licensed under the Apache License, Version 2.0 (the "License");
6 | you may not use this file except in compliance with the License.
7 | You may obtain a copy of the License at
8 | http://www.apache.org/licenses/LICENSE-2.0
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 | """
15 |
16 | import os
17 |
18 | from setuptools import setup
19 |
20 | # Load version in dapr package.
21 | version_info = {}
22 | with open('dapr/ext/grpc/version.py') as fp:
23 | exec(fp.read(), version_info)
24 | __version__ = version_info['__version__']
25 |
26 |
27 | def is_release():
28 | return '.dev' not in __version__
29 |
30 |
31 | name = 'dapr-ext-grpc'
32 | version = __version__
33 | description = 'The official release of Dapr Python SDK gRPC Extension.'
34 | long_description = """
35 | This is the gRPC extension for Dapr.
36 |
37 | Dapr is a portable, serverless, event-driven runtime that makes it easy for developers to
38 | build resilient, stateless and stateful microservices that run on the cloud and edge and
39 | embraces the diversity of languages and developer frameworks.
40 |
41 | Dapr codifies the best practices for building microservice applications into open,
42 | independent, building blocks that enable you to build portable applications with the language
43 | and framework of your choice. Each building block is independent and you can use one, some,
44 | or all of them in your application.
45 | """.lstrip()
46 |
47 | # Get build number from GITHUB_RUN_NUMBER environment variable
48 | build_number = os.environ.get('GITHUB_RUN_NUMBER', '0')
49 |
50 | if not is_release():
51 | name += '-dev'
52 | version = f'{__version__}{build_number}'
53 | description = 'The developmental release for Dapr gRPC AppCallback.'
54 | long_description = 'This is the developmental release for Dapr gRPC AppCallback.'
55 |
56 | print(f'package name: {name}, version: {version}', flush=True)
57 |
58 |
59 | setup(
60 | name=name,
61 | version=version,
62 | description=description,
63 | long_description=long_description,
64 | )
65 |
--------------------------------------------------------------------------------
/ext/dapr-ext-fastapi/setup.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | """
4 | Copyright 2023 The Dapr Authors
5 | Licensed under the Apache License, Version 2.0 (the "License");
6 | you may not use this file except in compliance with the License.
7 | You may obtain a copy of the License at
8 | http://www.apache.org/licenses/LICENSE-2.0
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 | """
15 |
16 | import os
17 |
18 | from setuptools import setup
19 |
20 | # Load version in dapr package.
21 | version_info = {}
22 | with open('dapr/ext/fastapi/version.py') as fp:
23 | exec(fp.read(), version_info)
24 | __version__ = version_info['__version__']
25 |
26 |
27 | def is_release():
28 | return '.dev' not in __version__
29 |
30 |
31 | name = 'dapr-ext-fastapi'
32 | version = __version__
33 | description = 'The official release of Dapr FastAPI extension.'
34 | long_description = """
35 | This is the FastAPI extension for Dapr.
36 |
37 | Dapr is a portable, serverless, event-driven runtime that makes it easy for developers to
38 | build resilient, stateless and stateful microservices that run on the cloud and edge and
39 | embraces the diversity of languages and developer frameworks.
40 |
41 | Dapr codifies the best practices for building microservice applications into open,
42 | independent, building blocks that enable you to build portable applications with the language
43 | and framework of your choice. Each building block is independent and you can use one, some,
44 | or all of them in your application.
45 | """.lstrip()
46 |
47 | # Get build number from GITHUB_RUN_NUMBER environment variable
48 | build_number = os.environ.get('GITHUB_RUN_NUMBER', '0')
49 |
50 | if not is_release():
51 | name += '-dev'
52 | version = f'{__version__}{build_number}'
53 | description = 'The developmental release for Dapr FastAPI extension.'
54 | long_description = 'This is the developmental release for Dapr FastAPI extension.'
55 |
56 | print(f'package name: {name}, version: {version}', flush=True)
57 |
58 |
59 | setup(
60 | name=name,
61 | version=version,
62 | description=description,
63 | long_description=long_description,
64 | )
65 |
--------------------------------------------------------------------------------