azure-functions-durable 1.2.9__py3-none-any.whl → 1.3.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (104) hide show
  1. azure/durable_functions/__init__.py +81 -81
  2. azure/durable_functions/constants.py +9 -9
  3. azure/durable_functions/decorators/__init__.py +3 -3
  4. azure/durable_functions/decorators/durable_app.py +260 -249
  5. azure/durable_functions/decorators/metadata.py +109 -109
  6. azure/durable_functions/entity.py +129 -125
  7. azure/durable_functions/models/DurableEntityContext.py +201 -201
  8. azure/durable_functions/models/DurableHttpRequest.py +58 -58
  9. azure/durable_functions/models/DurableOrchestrationBindings.py +66 -66
  10. azure/durable_functions/models/DurableOrchestrationClient.py +812 -781
  11. azure/durable_functions/models/DurableOrchestrationContext.py +761 -707
  12. azure/durable_functions/models/DurableOrchestrationStatus.py +156 -156
  13. azure/durable_functions/models/EntityStateResponse.py +23 -23
  14. azure/durable_functions/models/FunctionContext.py +7 -7
  15. azure/durable_functions/models/OrchestrationRuntimeStatus.py +32 -32
  16. azure/durable_functions/models/OrchestratorState.py +117 -116
  17. azure/durable_functions/models/PurgeHistoryResult.py +33 -33
  18. azure/durable_functions/models/ReplaySchema.py +9 -8
  19. azure/durable_functions/models/RetryOptions.py +69 -69
  20. azure/durable_functions/models/RpcManagementOptions.py +86 -86
  21. azure/durable_functions/models/Task.py +540 -426
  22. azure/durable_functions/models/TaskOrchestrationExecutor.py +352 -336
  23. azure/durable_functions/models/TokenSource.py +56 -56
  24. azure/durable_functions/models/__init__.py +26 -24
  25. azure/durable_functions/models/actions/Action.py +23 -23
  26. azure/durable_functions/models/actions/ActionType.py +18 -18
  27. azure/durable_functions/models/actions/CallActivityAction.py +41 -41
  28. azure/durable_functions/models/actions/CallActivityWithRetryAction.py +45 -45
  29. azure/durable_functions/models/actions/CallEntityAction.py +46 -46
  30. azure/durable_functions/models/actions/CallHttpAction.py +35 -35
  31. azure/durable_functions/models/actions/CallSubOrchestratorAction.py +40 -40
  32. azure/durable_functions/models/actions/CallSubOrchestratorWithRetryAction.py +44 -44
  33. azure/durable_functions/models/actions/CompoundAction.py +35 -35
  34. azure/durable_functions/models/actions/ContinueAsNewAction.py +36 -36
  35. azure/durable_functions/models/actions/CreateTimerAction.py +48 -48
  36. azure/durable_functions/models/actions/NoOpAction.py +35 -35
  37. azure/durable_functions/models/actions/SignalEntityAction.py +47 -47
  38. azure/durable_functions/models/actions/WaitForExternalEventAction.py +63 -63
  39. azure/durable_functions/models/actions/WhenAllAction.py +14 -14
  40. azure/durable_functions/models/actions/WhenAnyAction.py +14 -14
  41. azure/durable_functions/models/actions/__init__.py +24 -24
  42. azure/durable_functions/models/entities/EntityState.py +74 -74
  43. azure/durable_functions/models/entities/OperationResult.py +94 -76
  44. azure/durable_functions/models/entities/RequestMessage.py +53 -53
  45. azure/durable_functions/models/entities/ResponseMessage.py +48 -48
  46. azure/durable_functions/models/entities/Signal.py +62 -62
  47. azure/durable_functions/models/entities/__init__.py +17 -17
  48. azure/durable_functions/models/history/HistoryEvent.py +92 -92
  49. azure/durable_functions/models/history/HistoryEventType.py +27 -27
  50. azure/durable_functions/models/history/__init__.py +8 -8
  51. azure/durable_functions/models/utils/__init__.py +7 -7
  52. azure/durable_functions/models/utils/entity_utils.py +103 -91
  53. azure/durable_functions/models/utils/http_utils.py +80 -69
  54. azure/durable_functions/models/utils/json_utils.py +96 -56
  55. azure/durable_functions/orchestrator.py +73 -71
  56. azure/durable_functions/testing/OrchestratorGeneratorWrapper.py +42 -0
  57. azure/durable_functions/testing/__init__.py +6 -0
  58. {azure_functions_durable-1.2.9.dist-info → azure_functions_durable-1.3.0.dist-info}/LICENSE +21 -21
  59. {azure_functions_durable-1.2.9.dist-info → azure_functions_durable-1.3.0.dist-info}/METADATA +59 -58
  60. azure_functions_durable-1.3.0.dist-info/RECORD +103 -0
  61. {azure_functions_durable-1.2.9.dist-info → azure_functions_durable-1.3.0.dist-info}/WHEEL +1 -1
  62. tests/models/test_DecoratorMetadata.py +135 -135
  63. tests/models/test_Decorators.py +107 -107
  64. tests/models/test_DurableOrchestrationBindings.py +68 -68
  65. tests/models/test_DurableOrchestrationClient.py +730 -730
  66. tests/models/test_DurableOrchestrationContext.py +102 -102
  67. tests/models/test_DurableOrchestrationStatus.py +59 -59
  68. tests/models/test_OrchestrationState.py +28 -28
  69. tests/models/test_RpcManagementOptions.py +79 -79
  70. tests/models/test_TokenSource.py +10 -10
  71. tests/orchestrator/models/OrchestrationInstance.py +18 -18
  72. tests/orchestrator/orchestrator_test_utils.py +130 -130
  73. tests/orchestrator/schemas/OrchetrationStateSchema.py +66 -66
  74. tests/orchestrator/test_call_http.py +235 -176
  75. tests/orchestrator/test_continue_as_new.py +67 -67
  76. tests/orchestrator/test_create_timer.py +126 -126
  77. tests/orchestrator/test_entity.py +397 -395
  78. tests/orchestrator/test_external_event.py +53 -53
  79. tests/orchestrator/test_fan_out_fan_in.py +175 -175
  80. tests/orchestrator/test_is_replaying_flag.py +101 -101
  81. tests/orchestrator/test_retries.py +308 -308
  82. tests/orchestrator/test_sequential_orchestrator.py +841 -841
  83. tests/orchestrator/test_sequential_orchestrator_custom_status.py +119 -119
  84. tests/orchestrator/test_sequential_orchestrator_with_retry.py +465 -465
  85. tests/orchestrator/test_serialization.py +30 -30
  86. tests/orchestrator/test_sub_orchestrator.py +95 -95
  87. tests/orchestrator/test_sub_orchestrator_with_retry.py +129 -129
  88. tests/orchestrator/test_task_any.py +60 -60
  89. tests/tasks/tasks_test_utils.py +17 -17
  90. tests/tasks/test_long_timers.py +70 -0
  91. tests/tasks/test_new_uuid.py +34 -34
  92. tests/test_utils/ContextBuilder.py +174 -174
  93. tests/test_utils/EntityContextBuilder.py +56 -56
  94. tests/test_utils/constants.py +1 -1
  95. tests/test_utils/json_utils.py +30 -30
  96. tests/test_utils/testClasses.py +56 -56
  97. tests/utils/__init__.py +1 -0
  98. tests/utils/test_entity_utils.py +24 -0
  99. azure_functions_durable-1.2.9.data/data/_manifest/bsi.json +0 -1
  100. azure_functions_durable-1.2.9.data/data/_manifest/manifest.cat +0 -0
  101. azure_functions_durable-1.2.9.data/data/_manifest/manifest.spdx.json +0 -11985
  102. azure_functions_durable-1.2.9.data/data/_manifest/manifest.spdx.json.sha256 +0 -1
  103. azure_functions_durable-1.2.9.dist-info/RECORD +0 -102
  104. {azure_functions_durable-1.2.9.dist-info → azure_functions_durable-1.3.0.dist-info}/top_level.txt +0 -0
@@ -1,249 +1,260 @@
1
- # Copyright (c) Microsoft Corporation. All rights reserved.
2
- # Licensed under the MIT License.
3
- from .metadata import OrchestrationTrigger, ActivityTrigger, EntityTrigger,\
4
- DurableClient
5
- from typing import Callable, Optional
6
- from azure.durable_functions.entity import Entity
7
- from azure.durable_functions.orchestrator import Orchestrator
8
- from azure.durable_functions import DurableOrchestrationClient
9
- from typing import Union
10
- from azure.functions import FunctionRegister, TriggerApi, BindingApi, AuthLevel
11
- from functools import wraps
12
-
13
- try:
14
- from azure.functions import SettingsApi
15
- except ImportError: # backwards compatibility path
16
- class SettingsApi:
17
- """Backwards compatibility mock of SettingsApi."""
18
-
19
- pass
20
-
21
-
22
- class Blueprint(TriggerApi, BindingApi, SettingsApi):
23
- """Durable Functions (DF) Blueprint container.
24
-
25
- It allows functions to be declared via trigger and binding decorators,
26
- but does not automatically index/register these functions.
27
-
28
- To register these functions, utilize the `register_functions` method from any
29
- :class:`FunctionRegister` subclass, such as `DFApp`.
30
- """
31
-
32
- def __init__(self,
33
- http_auth_level: Union[AuthLevel, str] = AuthLevel.FUNCTION):
34
- """Instantiate a Durable Functions app with which to register Functions.
35
-
36
- Parameters
37
- ----------
38
- http_auth_level: Union[AuthLevel, str]
39
- Authorization level required for Function invocation.
40
- Defaults to AuthLevel.Function.
41
-
42
- Returns
43
- -------
44
- DFApp
45
- New instance of a Durable Functions app
46
- """
47
- super().__init__(auth_level=http_auth_level)
48
-
49
- def _configure_entity_callable(self, wrap) -> Callable:
50
- """Obtain decorator to construct an Entity class from a user-defined Function.
51
-
52
- In the old programming model, this decorator's logic was unavoidable boilerplate
53
- in user-code. Now, this is handled internally by the framework.
54
-
55
- Parameters
56
- ----------
57
- wrap: Callable
58
- The next decorator to be applied.
59
-
60
- Returns
61
- -------
62
- Callable
63
- The function to construct an Entity class from the user-defined Function,
64
- wrapped by the next decorator in the sequence.
65
- """
66
- def decorator(entity_func):
67
- # Construct an entity based on the end-user code
68
- handle = Entity.create(entity_func)
69
-
70
- # invoke next decorator, with the Entity as input
71
- handle.__name__ = entity_func.__name__
72
- return wrap(handle)
73
-
74
- return decorator
75
-
76
- def _configure_orchestrator_callable(self, wrap) -> Callable:
77
- """Obtain decorator to construct an Orchestrator class from a user-defined Function.
78
-
79
- In the old programming model, this decorator's logic was unavoidable boilerplate
80
- in user-code. Now, this is handled internally by the framework.
81
-
82
- Parameters
83
- ----------
84
- wrap: Callable
85
- The next decorator to be applied.
86
-
87
- Returns
88
- -------
89
- Callable
90
- The function to construct an Orchestrator class from the user-defined Function,
91
- wrapped by the next decorator in the sequence.
92
- """
93
- def decorator(orchestrator_func):
94
- # Construct an orchestrator based on the end-user code
95
- handle = Orchestrator.create(orchestrator_func)
96
-
97
- # invoke next decorator, with the Orchestrator as input
98
- handle.__name__ = orchestrator_func.__name__
99
- return wrap(handle)
100
-
101
- return decorator
102
-
103
- def orchestration_trigger(self, context_name: str,
104
- orchestration: Optional[str] = None):
105
- """Register an Orchestrator Function.
106
-
107
- Parameters
108
- ----------
109
- context_name: str
110
- Parameter name of the DurableOrchestrationContext object.
111
- orchestration: Optional[str]
112
- Name of Orchestrator Function.
113
- The value is None by default, in which case the name of the method is used.
114
- """
115
- @self._configure_orchestrator_callable
116
- @self._configure_function_builder
117
- def wrap(fb):
118
-
119
- def decorator():
120
- fb.add_trigger(
121
- trigger=OrchestrationTrigger(name=context_name,
122
- orchestration=orchestration))
123
- return fb
124
-
125
- return decorator()
126
-
127
- return wrap
128
-
129
- def activity_trigger(self, input_name: str,
130
- activity: Optional[str] = None):
131
- """Register an Activity Function.
132
-
133
- Parameters
134
- ----------
135
- input_name: str
136
- Parameter name of the Activity input.
137
- activity: Optional[str]
138
- Name of Activity Function.
139
- The value is None by default, in which case the name of the method is used.
140
- """
141
- @self._configure_function_builder
142
- def wrap(fb):
143
- def decorator():
144
- fb.add_trigger(
145
- trigger=ActivityTrigger(name=input_name,
146
- activity=activity))
147
- return fb
148
-
149
- return decorator()
150
-
151
- return wrap
152
-
153
- def entity_trigger(self, context_name: str,
154
- entity_name: Optional[str] = None):
155
- """Register an Entity Function.
156
-
157
- Parameters
158
- ----------
159
- context_name: str
160
- Parameter name of the Entity input.
161
- entity_name: Optional[str]
162
- Name of Entity Function.
163
- The value is None by default, in which case the name of the method is used.
164
- """
165
- @self._configure_entity_callable
166
- @self._configure_function_builder
167
- def wrap(fb):
168
- def decorator():
169
- fb.add_trigger(
170
- trigger=EntityTrigger(name=context_name,
171
- entity_name=entity_name))
172
- return fb
173
-
174
- return decorator()
175
-
176
- return wrap
177
-
178
- def _add_rich_client(self, fb, parameter_name,
179
- client_constructor):
180
- # Obtain user-code and force type annotation on the client-binding parameter to be `str`.
181
- # This ensures a passing type-check of that specific parameter,
182
- # circumventing a limitation of the worker in type-checking rich DF Client objects.
183
- # TODO: Once rich-binding type checking is possible, remove the annotation change.
184
- user_code = fb._function._func
185
- user_code.__annotations__[parameter_name] = str
186
-
187
- # `wraps` This ensures we re-export the same method-signature as the decorated method
188
- @wraps(user_code)
189
- async def df_client_middleware(*args, **kwargs):
190
-
191
- # Obtain JSON-string currently passed as DF Client,
192
- # construct rich object from it,
193
- # and assign parameter to that rich object
194
- starter = kwargs[parameter_name]
195
- client = client_constructor(starter)
196
- kwargs[parameter_name] = client
197
-
198
- # Invoke user code with rich DF Client binding
199
- return await user_code(*args, **kwargs)
200
-
201
- user_code_with_rich_client = df_client_middleware
202
- fb._function._func = user_code_with_rich_client
203
-
204
- def durable_client_input(self,
205
- client_name: str,
206
- task_hub: Optional[str] = None,
207
- connection_name: Optional[str] = None
208
- ):
209
- """Register a Durable-client Function.
210
-
211
- Parameters
212
- ----------
213
- client_name: str
214
- Parameter name of durable client.
215
- task_hub: Optional[str]
216
- Used in scenarios where multiple function apps share the same storage account
217
- but need to be isolated from each other. If not specified, the default value
218
- from host.json is used.
219
- This value must match the value used by the target orchestrator functions.
220
- connection_name: Optional[str]
221
- The name of an app setting that contains a storage account connection string.
222
- The storage account represented by this connection string must be the same one
223
- used by the target orchestrator functions. If not specified, the default storage
224
- account connection string for the function app is used.
225
- """
226
-
227
- @self._configure_function_builder
228
- def wrap(fb):
229
- def decorator():
230
- self._add_rich_client(fb, client_name, DurableOrchestrationClient)
231
-
232
- fb.add_binding(
233
- binding=DurableClient(name=client_name,
234
- task_hub=task_hub,
235
- connection_name=connection_name))
236
- return fb
237
-
238
- return decorator()
239
-
240
- return wrap
241
-
242
-
243
- class DFApp(Blueprint, FunctionRegister):
244
- """Durable Functions (DF) app.
245
-
246
- Exports the decorators required to declare and index DF Function-types.
247
- """
248
-
249
- pass
1
+ # Copyright (c) Microsoft Corporation. All rights reserved.
2
+ # Licensed under the MIT License.
3
+ from .metadata import OrchestrationTrigger, ActivityTrigger, EntityTrigger,\
4
+ DurableClient
5
+ from typing import Callable, Optional
6
+ from azure.durable_functions.entity import Entity
7
+ from azure.durable_functions.orchestrator import Orchestrator
8
+ from azure.durable_functions import DurableOrchestrationClient
9
+ from typing import Union
10
+ from azure.functions import FunctionRegister, TriggerApi, BindingApi, AuthLevel
11
+ from functools import wraps
12
+
13
+ try:
14
+ from azure.functions import SettingsApi
15
+ except ImportError: # backwards compatibility path
16
+ class SettingsApi:
17
+ """Backwards compatibility mock of SettingsApi."""
18
+
19
+ pass
20
+
21
+
22
+ class Blueprint(TriggerApi, BindingApi, SettingsApi):
23
+ """Durable Functions (DF) Blueprint container.
24
+
25
+ It allows functions to be declared via trigger and binding decorators,
26
+ but does not automatically index/register these functions.
27
+
28
+ To register these functions, utilize the `register_functions` method from any
29
+ :class:`FunctionRegister` subclass, such as `DFApp`.
30
+ """
31
+
32
+ def __init__(self,
33
+ http_auth_level: Union[AuthLevel, str] = AuthLevel.FUNCTION):
34
+ """Instantiate a Durable Functions app with which to register Functions.
35
+
36
+ Parameters
37
+ ----------
38
+ http_auth_level: Union[AuthLevel, str]
39
+ Authorization level required for Function invocation.
40
+ Defaults to AuthLevel.Function.
41
+
42
+ Returns
43
+ -------
44
+ DFApp
45
+ New instance of a Durable Functions app
46
+ """
47
+ super().__init__(auth_level=http_auth_level)
48
+
49
+ def _configure_entity_callable(self, wrap) -> Callable:
50
+ """Obtain decorator to construct an Entity class from a user-defined Function.
51
+
52
+ In the old programming model, this decorator's logic was unavoidable boilerplate
53
+ in user-code. Now, this is handled internally by the framework.
54
+
55
+ Parameters
56
+ ----------
57
+ wrap: Callable
58
+ The next decorator to be applied.
59
+
60
+ Returns
61
+ -------
62
+ Callable
63
+ The function to construct an Entity class from the user-defined Function,
64
+ wrapped by the next decorator in the sequence.
65
+ """
66
+ def decorator(entity_func):
67
+ # Construct an entity based on the end-user code
68
+ handle = Entity.create(entity_func)
69
+
70
+ # invoke next decorator, with the Entity as input
71
+ handle.__name__ = entity_func.__name__
72
+ return wrap(handle)
73
+
74
+ return decorator
75
+
76
+ def _configure_orchestrator_callable(self, wrap) -> Callable:
77
+ """Obtain decorator to construct an Orchestrator class from a user-defined Function.
78
+
79
+ In the old programming model, this decorator's logic was unavoidable boilerplate
80
+ in user-code. Now, this is handled internally by the framework.
81
+
82
+ Parameters
83
+ ----------
84
+ wrap: Callable
85
+ The next decorator to be applied.
86
+
87
+ Returns
88
+ -------
89
+ Callable
90
+ The function to construct an Orchestrator class from the user-defined Function,
91
+ wrapped by the next decorator in the sequence.
92
+ """
93
+ def decorator(orchestrator_func):
94
+ # Construct an orchestrator based on the end-user code
95
+ handle = Orchestrator.create(orchestrator_func)
96
+
97
+ # invoke next decorator, with the Orchestrator as input
98
+ handle.__name__ = orchestrator_func.__name__
99
+ return wrap(handle)
100
+
101
+ return decorator
102
+
103
+ def orchestration_trigger(self, context_name: str,
104
+ orchestration: Optional[str] = None):
105
+ """Register an Orchestrator Function.
106
+
107
+ Parameters
108
+ ----------
109
+ context_name: str
110
+ Parameter name of the DurableOrchestrationContext object.
111
+ orchestration: Optional[str]
112
+ Name of Orchestrator Function.
113
+ The value is None by default, in which case the name of the method is used.
114
+ """
115
+ @self._configure_orchestrator_callable
116
+ @self._configure_function_builder
117
+ def wrap(fb):
118
+
119
+ def decorator():
120
+ fb.add_trigger(
121
+ trigger=OrchestrationTrigger(name=context_name,
122
+ orchestration=orchestration))
123
+ return fb
124
+
125
+ return decorator()
126
+
127
+ return wrap
128
+
129
+ def activity_trigger(self, input_name: str,
130
+ activity: Optional[str] = None):
131
+ """Register an Activity Function.
132
+
133
+ Parameters
134
+ ----------
135
+ input_name: str
136
+ Parameter name of the Activity input.
137
+ activity: Optional[str]
138
+ Name of Activity Function.
139
+ The value is None by default, in which case the name of the method is used.
140
+ """
141
+ @self._configure_function_builder
142
+ def wrap(fb):
143
+ def decorator():
144
+ fb.add_trigger(
145
+ trigger=ActivityTrigger(name=input_name,
146
+ activity=activity))
147
+ return fb
148
+
149
+ return decorator()
150
+
151
+ return wrap
152
+
153
+ def entity_trigger(self, context_name: str,
154
+ entity_name: Optional[str] = None):
155
+ """Register an Entity Function.
156
+
157
+ Parameters
158
+ ----------
159
+ context_name: str
160
+ Parameter name of the Entity input.
161
+ entity_name: Optional[str]
162
+ Name of Entity Function.
163
+ The value is None by default, in which case the name of the method is used.
164
+ """
165
+ @self._configure_entity_callable
166
+ @self._configure_function_builder
167
+ def wrap(fb):
168
+ def decorator():
169
+ fb.add_trigger(
170
+ trigger=EntityTrigger(name=context_name,
171
+ entity_name=entity_name))
172
+ return fb
173
+
174
+ return decorator()
175
+
176
+ return wrap
177
+
178
+ def _add_rich_client(self, fb, parameter_name,
179
+ client_constructor):
180
+ # Obtain user-code and force type annotation on the client-binding parameter to be `str`.
181
+ # This ensures a passing type-check of that specific parameter,
182
+ # circumventing a limitation of the worker in type-checking rich DF Client objects.
183
+ # TODO: Once rich-binding type checking is possible, remove the annotation change.
184
+ user_code = fb._function._func
185
+ user_code.__annotations__[parameter_name] = str
186
+
187
+ # `wraps` This ensures we re-export the same method-signature as the decorated method
188
+ @wraps(user_code)
189
+ async def df_client_middleware(*args, **kwargs):
190
+
191
+ # Obtain JSON-string currently passed as DF Client,
192
+ # construct rich object from it,
193
+ # and assign parameter to that rich object
194
+ starter = kwargs[parameter_name]
195
+ client = client_constructor(starter)
196
+ kwargs[parameter_name] = client
197
+
198
+ # Invoke user code with rich DF Client binding
199
+ return await user_code(*args, **kwargs)
200
+
201
+ # Todo: This feels awkward - however, there are two reasons that I can't naively implement
202
+ # this in the same way as entities and orchestrators:
203
+ # 1. We intentionally wrap this exported signature with @wraps, to preserve the original
204
+ # signature of the user code. This means that we can't just assign a new object to the
205
+ # fb._function._func, as that would overwrite the original signature.
206
+ # 2. I have not yet fully tested the behavior of overriding __call__ on an object with an
207
+ # async method.
208
+ # Here we lose type hinting and auto-documentation - not great. Need to find a better way
209
+ # to do this.
210
+ df_client_middleware.client_function = fb._function._func
211
+
212
+ user_code_with_rich_client = df_client_middleware
213
+ fb._function._func = user_code_with_rich_client
214
+
215
+ def durable_client_input(self,
216
+ client_name: str,
217
+ task_hub: Optional[str] = None,
218
+ connection_name: Optional[str] = None
219
+ ):
220
+ """Register a Durable-client Function.
221
+
222
+ Parameters
223
+ ----------
224
+ client_name: str
225
+ Parameter name of durable client.
226
+ task_hub: Optional[str]
227
+ Used in scenarios where multiple function apps share the same storage account
228
+ but need to be isolated from each other. If not specified, the default value
229
+ from host.json is used.
230
+ This value must match the value used by the target orchestrator functions.
231
+ connection_name: Optional[str]
232
+ The name of an app setting that contains a storage account connection string.
233
+ The storage account represented by this connection string must be the same one
234
+ used by the target orchestrator functions. If not specified, the default storage
235
+ account connection string for the function app is used.
236
+ """
237
+
238
+ @self._configure_function_builder
239
+ def wrap(fb):
240
+ def decorator():
241
+ self._add_rich_client(fb, client_name, DurableOrchestrationClient)
242
+
243
+ fb.add_binding(
244
+ binding=DurableClient(name=client_name,
245
+ task_hub=task_hub,
246
+ connection_name=connection_name))
247
+ return fb
248
+
249
+ return decorator()
250
+
251
+ return wrap
252
+
253
+
254
+ class DFApp(Blueprint, FunctionRegister):
255
+ """Durable Functions (DF) app.
256
+
257
+ Exports the decorators required to declare and index DF Function-types.
258
+ """
259
+
260
+ pass