warpzone-sdk 13.1.0__tar.gz → 14.1.0__tar.gz
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.
- warpzone_sdk-14.1.0/PKG-INFO +230 -0
- warpzone_sdk-14.1.0/README.md +195 -0
- warpzone_sdk-14.1.0/pyproject.toml +59 -0
- {warpzone_sdk-13.1.0 → warpzone_sdk-14.1.0}/warpzone/db/client.py +14 -1
- warpzone_sdk-13.1.0/PKG-INFO +0 -32
- warpzone_sdk-13.1.0/pyproject.toml +0 -55
- {warpzone_sdk-13.1.0 → warpzone_sdk-14.1.0}/warpzone/__init__.py +0 -0
- {warpzone_sdk-13.1.0 → warpzone_sdk-14.1.0}/warpzone/blobstorage/__init__.py +0 -0
- {warpzone_sdk-13.1.0 → warpzone_sdk-14.1.0}/warpzone/blobstorage/client.py +0 -0
- {warpzone_sdk-13.1.0 → warpzone_sdk-14.1.0}/warpzone/db/__init__.py +0 -0
- {warpzone_sdk-13.1.0 → warpzone_sdk-14.1.0}/warpzone/deltastorage/__init__.py +0 -0
- {warpzone_sdk-13.1.0 → warpzone_sdk-14.1.0}/warpzone/deltastorage/data_types.py +0 -0
- {warpzone_sdk-13.1.0 → warpzone_sdk-14.1.0}/warpzone/deltastorage/generated_columns.py +0 -0
- {warpzone_sdk-13.1.0 → warpzone_sdk-14.1.0}/warpzone/deltastorage/lock_client.py +0 -0
- {warpzone_sdk-13.1.0 → warpzone_sdk-14.1.0}/warpzone/deltastorage/schema.py +0 -0
- {warpzone_sdk-13.1.0 → warpzone_sdk-14.1.0}/warpzone/deltastorage/slicing.py +0 -0
- {warpzone_sdk-13.1.0 → warpzone_sdk-14.1.0}/warpzone/deltastorage/store.py +0 -0
- {warpzone_sdk-13.1.0 → warpzone_sdk-14.1.0}/warpzone/deltastorage/table.py +0 -0
- {warpzone_sdk-13.1.0 → warpzone_sdk-14.1.0}/warpzone/enums/__init__.py +0 -0
- {warpzone_sdk-13.1.0 → warpzone_sdk-14.1.0}/warpzone/enums/topicenum.py +0 -0
- {warpzone_sdk-13.1.0 → warpzone_sdk-14.1.0}/warpzone/function/__init__.py +0 -0
- {warpzone_sdk-13.1.0 → warpzone_sdk-14.1.0}/warpzone/function/checks.py +0 -0
- {warpzone_sdk-13.1.0 → warpzone_sdk-14.1.0}/warpzone/function/functionize.py +0 -0
- {warpzone_sdk-13.1.0 → warpzone_sdk-14.1.0}/warpzone/function/integrations.py +0 -0
- {warpzone_sdk-13.1.0 → warpzone_sdk-14.1.0}/warpzone/function/monitor.py +0 -0
- {warpzone_sdk-13.1.0 → warpzone_sdk-14.1.0}/warpzone/function/process.py +0 -0
- {warpzone_sdk-13.1.0 → warpzone_sdk-14.1.0}/warpzone/function/processors/__init__.py +0 -0
- {warpzone_sdk-13.1.0 → warpzone_sdk-14.1.0}/warpzone/function/processors/dependencies.py +0 -0
- {warpzone_sdk-13.1.0 → warpzone_sdk-14.1.0}/warpzone/function/processors/outputs.py +0 -0
- {warpzone_sdk-13.1.0 → warpzone_sdk-14.1.0}/warpzone/function/processors/triggers.py +0 -0
- {warpzone_sdk-13.1.0 → warpzone_sdk-14.1.0}/warpzone/function/signature.py +0 -0
- {warpzone_sdk-13.1.0 → warpzone_sdk-14.1.0}/warpzone/function/types.py +0 -0
- {warpzone_sdk-13.1.0 → warpzone_sdk-14.1.0}/warpzone/healthchecks/__init__.py +0 -0
- {warpzone_sdk-13.1.0 → warpzone_sdk-14.1.0}/warpzone/healthchecks/model.py +0 -0
- {warpzone_sdk-13.1.0 → warpzone_sdk-14.1.0}/warpzone/monitor/__init__.py +0 -0
- {warpzone_sdk-13.1.0 → warpzone_sdk-14.1.0}/warpzone/monitor/logs.py +0 -0
- {warpzone_sdk-13.1.0 → warpzone_sdk-14.1.0}/warpzone/monitor/traces.py +0 -0
- {warpzone_sdk-13.1.0 → warpzone_sdk-14.1.0}/warpzone/servicebus/data/__init__.py +0 -0
- {warpzone_sdk-13.1.0 → warpzone_sdk-14.1.0}/warpzone/servicebus/data/client.py +0 -0
- {warpzone_sdk-13.1.0 → warpzone_sdk-14.1.0}/warpzone/servicebus/events/__init__.py +0 -0
- {warpzone_sdk-13.1.0 → warpzone_sdk-14.1.0}/warpzone/servicebus/events/client.py +0 -0
- {warpzone_sdk-13.1.0 → warpzone_sdk-14.1.0}/warpzone/servicebus/events/triggers.py +0 -0
- {warpzone_sdk-13.1.0 → warpzone_sdk-14.1.0}/warpzone/tablestorage/db/__init__.py +0 -0
- {warpzone_sdk-13.1.0 → warpzone_sdk-14.1.0}/warpzone/tablestorage/db/base_client.py +0 -0
- {warpzone_sdk-13.1.0 → warpzone_sdk-14.1.0}/warpzone/tablestorage/db/client.py +0 -0
- {warpzone_sdk-13.1.0 → warpzone_sdk-14.1.0}/warpzone/tablestorage/db/table_config.py +0 -0
- {warpzone_sdk-13.1.0 → warpzone_sdk-14.1.0}/warpzone/tablestorage/tables/__init__.py +0 -0
- {warpzone_sdk-13.1.0 → warpzone_sdk-14.1.0}/warpzone/tablestorage/tables/client.py +0 -0
- {warpzone_sdk-13.1.0 → warpzone_sdk-14.1.0}/warpzone/tablestorage/tables/entities.py +0 -0
- {warpzone_sdk-13.1.0 → warpzone_sdk-14.1.0}/warpzone/tablestorage/tables/helpers.py +0 -0
- {warpzone_sdk-13.1.0 → warpzone_sdk-14.1.0}/warpzone/testing/__init__.py +0 -0
- {warpzone_sdk-13.1.0 → warpzone_sdk-14.1.0}/warpzone/testing/assertions.py +0 -0
- {warpzone_sdk-13.1.0 → warpzone_sdk-14.1.0}/warpzone/testing/data.py +0 -0
- {warpzone_sdk-13.1.0 → warpzone_sdk-14.1.0}/warpzone/testing/matchers.py +0 -0
- {warpzone_sdk-13.1.0 → warpzone_sdk-14.1.0}/warpzone/tools/__init__.py +0 -0
- {warpzone_sdk-13.1.0 → warpzone_sdk-14.1.0}/warpzone/tools/copy.py +0 -0
- {warpzone_sdk-13.1.0 → warpzone_sdk-14.1.0}/warpzone/transform/__init__.py +0 -0
- {warpzone_sdk-13.1.0 → warpzone_sdk-14.1.0}/warpzone/transform/data.py +0 -0
- {warpzone_sdk-13.1.0 → warpzone_sdk-14.1.0}/warpzone/transform/schema.py +0 -0
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: warpzone-sdk
|
|
3
|
+
Version: 14.1.0
|
|
4
|
+
Summary: The main objective of this package is to centralize logic used to interact with Azure Functions, Azure Service Bus and Azure Table Storage
|
|
5
|
+
Author: Team Enigma
|
|
6
|
+
Author-email: enigma@energinet.dk
|
|
7
|
+
Requires-Python: >=3.10
|
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
14
|
+
Requires-Dist: aiohttp (>=3.8.3)
|
|
15
|
+
Requires-Dist: azure-core (>=1.26.3)
|
|
16
|
+
Requires-Dist: azure-core-tracing-opentelemetry (>=1.0.0b12)
|
|
17
|
+
Requires-Dist: azure-data-tables (>=12.4.0)
|
|
18
|
+
Requires-Dist: azure-functions (>=1.12.0)
|
|
19
|
+
Requires-Dist: azure-identity (>=1.15.0)
|
|
20
|
+
Requires-Dist: azure-monitor-opentelemetry-exporter (>=1.0.0b36)
|
|
21
|
+
Requires-Dist: azure-servicebus (>=7.8.0,<7.9.0)
|
|
22
|
+
Requires-Dist: azure-storage-blob (>=12.14.1)
|
|
23
|
+
Requires-Dist: cryptography (==43.0.3)
|
|
24
|
+
Requires-Dist: datamazing (>=5.1.6)
|
|
25
|
+
Requires-Dist: deltalake (>=1.3.0)
|
|
26
|
+
Requires-Dist: numpy (>=1.26.4)
|
|
27
|
+
Requires-Dist: obstore (>=0.8.2)
|
|
28
|
+
Requires-Dist: opentelemetry-sdk (>=1.32.0)
|
|
29
|
+
Requires-Dist: pandas (>=2.0.3)
|
|
30
|
+
Requires-Dist: polars (>=1.33.1)
|
|
31
|
+
Requires-Dist: pyarrow (>=19.0.0)
|
|
32
|
+
Requires-Dist: typeguard (>=4.0.1)
|
|
33
|
+
Description-Content-Type: text/markdown
|
|
34
|
+
|
|
35
|
+
# WarpZone SDK
|
|
36
|
+
|
|
37
|
+
This package contains tools used in the WarpZone project.
|
|
38
|
+
These tool include:
|
|
39
|
+
|
|
40
|
+
- [Client for Storage](#client-for-storage)
|
|
41
|
+
- [Client for Servicebus](#client-for-servicebus)
|
|
42
|
+
- [Function wrapper](#function-wrapper)
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## Client for Storage
|
|
47
|
+
|
|
48
|
+
### Table storage
|
|
49
|
+
`WarpzoneTableClient` (sync) and `WarpzoneTableClientAsync` (async) clients are used for reading from and writing to Azure Storage Table Service.
|
|
50
|
+
|
|
51
|
+

|
|
52
|
+
|
|
53
|
+
--
|
|
54
|
+
|
|
55
|
+
### Blob storage
|
|
56
|
+
`WarpzoneBlobClient` client is used for uploading to and downloading from Azure Storage Blob Service.
|
|
57
|
+
|
|
58
|
+

|
|
59
|
+
|
|
60
|
+
--
|
|
61
|
+
|
|
62
|
+
### Database
|
|
63
|
+
|
|
64
|
+
`WarpzoneDatabaseClient` (sync) is an umbrella client used in warpZone, which consists of both `WarpzoneTableClient` and `WarpzoneBlobClient`
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## Client for Servicebus
|
|
70
|
+
Due to limitations on message sizes, we use different methods for sending *events* and *data* using Azure Service Bus.
|
|
71
|
+
|
|
72
|
+
### Events
|
|
73
|
+
|
|
74
|
+
We use the Service Bus for transmitting event messages. By an *event*, we mean a JSON formatted message, containing information about an event occuring in one part of the system, which needs to trigger another part of the system (such as an Azure Function trigger).
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
`WarpzoneEventClient` client is used for sending and receiving events.
|
|
78
|
+
|
|
79
|
+

|
|
80
|
+
|
|
81
|
+
--
|
|
82
|
+
|
|
83
|
+
### Data
|
|
84
|
+
|
|
85
|
+
We **do not** use the Service Bus for transmitting data directly. Instead, we use a claim-check pattern, were we store the data using Storage Blob, and transmit an event about the details of this stored data.
|
|
86
|
+
|
|
87
|
+
`WarpzoneDataClient` client is used for sending and receiving data in this way. The following diagram shows how the process works:
|
|
88
|
+
|
|
89
|
+
1. Data is uploaded
|
|
90
|
+
2. Event containing the blob location is send
|
|
91
|
+
3. Event is received
|
|
92
|
+
4. Data is downloaded using the blob location contained in the event
|
|
93
|
+
|
|
94
|
+

|
|
95
|
+
|
|
96
|
+
The transmitted event has the following format:
|
|
97
|
+
```json
|
|
98
|
+
{
|
|
99
|
+
"container_name": "<container-name>",
|
|
100
|
+
"blob_name": "<blob-name>",
|
|
101
|
+
"timestamp": "<%Y-%m-%dT%H:%M:%S%z>"
|
|
102
|
+
}
|
|
103
|
+
```
|
|
104
|
+
The data will be stored with
|
|
105
|
+
- `<container-name>` = `<topic-name>`
|
|
106
|
+
- `<blob-name>` = `<subject>/year=<%Y>/month=<%m>/day=<%d>/hour=<%H>/<message-id>.<extension>`
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
---
|
|
110
|
+
|
|
111
|
+
## Function Wrapper
|
|
112
|
+
|
|
113
|
+
For executing logic, we use a framework built on top of Azure Functions. The following diagram shows how the framework works:
|
|
114
|
+
|
|
115
|
+
1. The function is triggered by a **trigger** object (e.g. a timer or a message being received)
|
|
116
|
+
2. Possible **dependency** objects are initialized (potentially using information from the trigger). These are used to integrate with external systems (e.g. a database client).
|
|
117
|
+
3. Using the trigger and dependencies as inputs, the function outputs and an **output** object (e.g. a message being sent).
|
|
118
|
+
|
|
119
|
+

|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
The reason we have used our own framework instead of Azure Functions directly, is that we want to use our own objects as triggers, dependencies and outputs, instead of the built-in bindings. For example, as explained [above](#data), we have created our own abstraction of a message for transmitting data (`warpzone.DataMessage`); so we would like to use this, instead of the built-in binding `azure.function.ServiceBusMessage`.
|
|
123
|
+
|
|
124
|
+
Since it is not yet possible to define [custom bindings](https://github.com/Azure/azure-webjobs-sdk/wiki/Creating-custom-input-and-output-bindings) in Python, we have defined our own wrapping logic, to handle the conversion between our own objects and the built-in bindings. The following diagram shows how the wrapping logic works:
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
1. Azure trigger binding is converted to trigger object
|
|
128
|
+
2. Either
|
|
129
|
+
- (a) Output object is converted to Azure output binding.
|
|
130
|
+
- (b) Use custom output logic, when no suitable output binding exists (e.g. we use the Azure Service Bus SDK instead of the Service Bus output binding, since this is [recommended](https://learn.microsoft.com/en-us/azure/azure-functions/functions-bindings-service-bus-output?tabs=python-v1%2Cin-process%2Cextensionv5&pivots=programming-language-python#usage))
|
|
131
|
+
3. All logs and traces are sent to App Insights automatically.
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+

|
|
135
|
+
|
|
136
|
+
--
|
|
137
|
+
|
|
138
|
+
### Examples
|
|
139
|
+
|
|
140
|
+
Azure Function with data messages as trigger and output:
|
|
141
|
+
|
|
142
|
+
```json
|
|
143
|
+
# function.json
|
|
144
|
+
{
|
|
145
|
+
"scriptFile": "__init__.py",
|
|
146
|
+
"entryPoint": "main",
|
|
147
|
+
"bindings": [
|
|
148
|
+
{
|
|
149
|
+
"name": "msg",
|
|
150
|
+
"type": "serviceBusTrigger",
|
|
151
|
+
"direction": "in",
|
|
152
|
+
"connection": "...",
|
|
153
|
+
"topicName": "...",
|
|
154
|
+
"subscriptionName": "..."
|
|
155
|
+
}
|
|
156
|
+
]
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
```python
|
|
162
|
+
import warpzone as wz
|
|
163
|
+
|
|
164
|
+
def do_nothing(data_msg: wz.DataMessage) -> wz.DataMessage:
|
|
165
|
+
return data_msg
|
|
166
|
+
|
|
167
|
+
main = wz.functionize(
|
|
168
|
+
f=do_nothing,
|
|
169
|
+
trigger=wz.triggers.DataMessageTrigger(binding_name="msg"),
|
|
170
|
+
output=wz.outputs.DataMessageOutput(wz.Topic.UNIFORM)
|
|
171
|
+
)
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
Azure Function with HTTP messages as trigger and output:
|
|
175
|
+
|
|
176
|
+
```json
|
|
177
|
+
# function.json
|
|
178
|
+
{
|
|
179
|
+
"scriptFile": "__init__.py",
|
|
180
|
+
"entryPoint": "main",
|
|
181
|
+
"bindings": [
|
|
182
|
+
{
|
|
183
|
+
"authLevel": "anonymous",
|
|
184
|
+
"name": "req",
|
|
185
|
+
"type": "httpTrigger",
|
|
186
|
+
"direction": "in"
|
|
187
|
+
},
|
|
188
|
+
{
|
|
189
|
+
"type": "http",
|
|
190
|
+
"direction": "out",
|
|
191
|
+
"name": "$return"
|
|
192
|
+
}
|
|
193
|
+
]
|
|
194
|
+
}
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
```python
|
|
198
|
+
# __init__.py
|
|
199
|
+
import warpzone as wz
|
|
200
|
+
import azure.functions as func
|
|
201
|
+
|
|
202
|
+
def return_ok(req: func.HttpRequest) -> func.HttpResponse:
|
|
203
|
+
return func.HttpResponse("OK")
|
|
204
|
+
|
|
205
|
+
main = wz.functionize(
|
|
206
|
+
f=return_ok,
|
|
207
|
+
trigger=wz.triggers.HttpTrigger(binding_name="req"),
|
|
208
|
+
output=wz.outputs.HttpOutput()
|
|
209
|
+
)
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
Azure Function using dependencies:
|
|
213
|
+
|
|
214
|
+
```python
|
|
215
|
+
import warpzone as wz
|
|
216
|
+
|
|
217
|
+
def do_nothing(
|
|
218
|
+
data_msg: wz.DataMessage,
|
|
219
|
+
db: wz.WarpzoneDatabaseClient,
|
|
220
|
+
) -> wz.DataMessage:
|
|
221
|
+
return data_msg
|
|
222
|
+
|
|
223
|
+
main = wz.functionize(
|
|
224
|
+
f=do_nothing,
|
|
225
|
+
trigger=wz.triggers.DataMessageTrigger(binding_name="msg"),
|
|
226
|
+
output=wz.outputs.DataMessageOutput(wz.Topic.UNIFORM),
|
|
227
|
+
dependencies=[wz.dependencies.TableDatabaseDependency()],
|
|
228
|
+
)
|
|
229
|
+
```
|
|
230
|
+
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
# WarpZone SDK
|
|
2
|
+
|
|
3
|
+
This package contains tools used in the WarpZone project.
|
|
4
|
+
These tool include:
|
|
5
|
+
|
|
6
|
+
- [Client for Storage](#client-for-storage)
|
|
7
|
+
- [Client for Servicebus](#client-for-servicebus)
|
|
8
|
+
- [Function wrapper](#function-wrapper)
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## Client for Storage
|
|
13
|
+
|
|
14
|
+
### Table storage
|
|
15
|
+
`WarpzoneTableClient` (sync) and `WarpzoneTableClientAsync` (async) clients are used for reading from and writing to Azure Storage Table Service.
|
|
16
|
+
|
|
17
|
+

|
|
18
|
+
|
|
19
|
+
--
|
|
20
|
+
|
|
21
|
+
### Blob storage
|
|
22
|
+
`WarpzoneBlobClient` client is used for uploading to and downloading from Azure Storage Blob Service.
|
|
23
|
+
|
|
24
|
+

|
|
25
|
+
|
|
26
|
+
--
|
|
27
|
+
|
|
28
|
+
### Database
|
|
29
|
+
|
|
30
|
+
`WarpzoneDatabaseClient` (sync) is an umbrella client used in warpZone, which consists of both `WarpzoneTableClient` and `WarpzoneBlobClient`
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## Client for Servicebus
|
|
36
|
+
Due to limitations on message sizes, we use different methods for sending *events* and *data* using Azure Service Bus.
|
|
37
|
+
|
|
38
|
+
### Events
|
|
39
|
+
|
|
40
|
+
We use the Service Bus for transmitting event messages. By an *event*, we mean a JSON formatted message, containing information about an event occuring in one part of the system, which needs to trigger another part of the system (such as an Azure Function trigger).
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
`WarpzoneEventClient` client is used for sending and receiving events.
|
|
44
|
+
|
|
45
|
+

|
|
46
|
+
|
|
47
|
+
--
|
|
48
|
+
|
|
49
|
+
### Data
|
|
50
|
+
|
|
51
|
+
We **do not** use the Service Bus for transmitting data directly. Instead, we use a claim-check pattern, were we store the data using Storage Blob, and transmit an event about the details of this stored data.
|
|
52
|
+
|
|
53
|
+
`WarpzoneDataClient` client is used for sending and receiving data in this way. The following diagram shows how the process works:
|
|
54
|
+
|
|
55
|
+
1. Data is uploaded
|
|
56
|
+
2. Event containing the blob location is send
|
|
57
|
+
3. Event is received
|
|
58
|
+
4. Data is downloaded using the blob location contained in the event
|
|
59
|
+
|
|
60
|
+

|
|
61
|
+
|
|
62
|
+
The transmitted event has the following format:
|
|
63
|
+
```json
|
|
64
|
+
{
|
|
65
|
+
"container_name": "<container-name>",
|
|
66
|
+
"blob_name": "<blob-name>",
|
|
67
|
+
"timestamp": "<%Y-%m-%dT%H:%M:%S%z>"
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
The data will be stored with
|
|
71
|
+
- `<container-name>` = `<topic-name>`
|
|
72
|
+
- `<blob-name>` = `<subject>/year=<%Y>/month=<%m>/day=<%d>/hour=<%H>/<message-id>.<extension>`
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
## Function Wrapper
|
|
78
|
+
|
|
79
|
+
For executing logic, we use a framework built on top of Azure Functions. The following diagram shows how the framework works:
|
|
80
|
+
|
|
81
|
+
1. The function is triggered by a **trigger** object (e.g. a timer or a message being received)
|
|
82
|
+
2. Possible **dependency** objects are initialized (potentially using information from the trigger). These are used to integrate with external systems (e.g. a database client).
|
|
83
|
+
3. Using the trigger and dependencies as inputs, the function outputs and an **output** object (e.g. a message being sent).
|
|
84
|
+
|
|
85
|
+

|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
The reason we have used our own framework instead of Azure Functions directly, is that we want to use our own objects as triggers, dependencies and outputs, instead of the built-in bindings. For example, as explained [above](#data), we have created our own abstraction of a message for transmitting data (`warpzone.DataMessage`); so we would like to use this, instead of the built-in binding `azure.function.ServiceBusMessage`.
|
|
89
|
+
|
|
90
|
+
Since it is not yet possible to define [custom bindings](https://github.com/Azure/azure-webjobs-sdk/wiki/Creating-custom-input-and-output-bindings) in Python, we have defined our own wrapping logic, to handle the conversion between our own objects and the built-in bindings. The following diagram shows how the wrapping logic works:
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
1. Azure trigger binding is converted to trigger object
|
|
94
|
+
2. Either
|
|
95
|
+
- (a) Output object is converted to Azure output binding.
|
|
96
|
+
- (b) Use custom output logic, when no suitable output binding exists (e.g. we use the Azure Service Bus SDK instead of the Service Bus output binding, since this is [recommended](https://learn.microsoft.com/en-us/azure/azure-functions/functions-bindings-service-bus-output?tabs=python-v1%2Cin-process%2Cextensionv5&pivots=programming-language-python#usage))
|
|
97
|
+
3. All logs and traces are sent to App Insights automatically.
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+

|
|
101
|
+
|
|
102
|
+
--
|
|
103
|
+
|
|
104
|
+
### Examples
|
|
105
|
+
|
|
106
|
+
Azure Function with data messages as trigger and output:
|
|
107
|
+
|
|
108
|
+
```json
|
|
109
|
+
# function.json
|
|
110
|
+
{
|
|
111
|
+
"scriptFile": "__init__.py",
|
|
112
|
+
"entryPoint": "main",
|
|
113
|
+
"bindings": [
|
|
114
|
+
{
|
|
115
|
+
"name": "msg",
|
|
116
|
+
"type": "serviceBusTrigger",
|
|
117
|
+
"direction": "in",
|
|
118
|
+
"connection": "...",
|
|
119
|
+
"topicName": "...",
|
|
120
|
+
"subscriptionName": "..."
|
|
121
|
+
}
|
|
122
|
+
]
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
```python
|
|
128
|
+
import warpzone as wz
|
|
129
|
+
|
|
130
|
+
def do_nothing(data_msg: wz.DataMessage) -> wz.DataMessage:
|
|
131
|
+
return data_msg
|
|
132
|
+
|
|
133
|
+
main = wz.functionize(
|
|
134
|
+
f=do_nothing,
|
|
135
|
+
trigger=wz.triggers.DataMessageTrigger(binding_name="msg"),
|
|
136
|
+
output=wz.outputs.DataMessageOutput(wz.Topic.UNIFORM)
|
|
137
|
+
)
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
Azure Function with HTTP messages as trigger and output:
|
|
141
|
+
|
|
142
|
+
```json
|
|
143
|
+
# function.json
|
|
144
|
+
{
|
|
145
|
+
"scriptFile": "__init__.py",
|
|
146
|
+
"entryPoint": "main",
|
|
147
|
+
"bindings": [
|
|
148
|
+
{
|
|
149
|
+
"authLevel": "anonymous",
|
|
150
|
+
"name": "req",
|
|
151
|
+
"type": "httpTrigger",
|
|
152
|
+
"direction": "in"
|
|
153
|
+
},
|
|
154
|
+
{
|
|
155
|
+
"type": "http",
|
|
156
|
+
"direction": "out",
|
|
157
|
+
"name": "$return"
|
|
158
|
+
}
|
|
159
|
+
]
|
|
160
|
+
}
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
```python
|
|
164
|
+
# __init__.py
|
|
165
|
+
import warpzone as wz
|
|
166
|
+
import azure.functions as func
|
|
167
|
+
|
|
168
|
+
def return_ok(req: func.HttpRequest) -> func.HttpResponse:
|
|
169
|
+
return func.HttpResponse("OK")
|
|
170
|
+
|
|
171
|
+
main = wz.functionize(
|
|
172
|
+
f=return_ok,
|
|
173
|
+
trigger=wz.triggers.HttpTrigger(binding_name="req"),
|
|
174
|
+
output=wz.outputs.HttpOutput()
|
|
175
|
+
)
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
Azure Function using dependencies:
|
|
179
|
+
|
|
180
|
+
```python
|
|
181
|
+
import warpzone as wz
|
|
182
|
+
|
|
183
|
+
def do_nothing(
|
|
184
|
+
data_msg: wz.DataMessage,
|
|
185
|
+
db: wz.WarpzoneDatabaseClient,
|
|
186
|
+
) -> wz.DataMessage:
|
|
187
|
+
return data_msg
|
|
188
|
+
|
|
189
|
+
main = wz.functionize(
|
|
190
|
+
f=do_nothing,
|
|
191
|
+
trigger=wz.triggers.DataMessageTrigger(binding_name="msg"),
|
|
192
|
+
output=wz.outputs.DataMessageOutput(wz.Topic.UNIFORM),
|
|
193
|
+
dependencies=[wz.dependencies.TableDatabaseDependency()],
|
|
194
|
+
)
|
|
195
|
+
```
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "warpzone-sdk"
|
|
3
|
+
version = "14.1.0"
|
|
4
|
+
description = "The main objective of this package is to centralize logic used to interact with Azure Functions, Azure Service Bus and Azure Table Storage"
|
|
5
|
+
authors = [{ name = "Team Enigma", email = "enigma@energinet.dk" }]
|
|
6
|
+
requires-python = ">=3.10"
|
|
7
|
+
readme = "README.md"
|
|
8
|
+
|
|
9
|
+
[tool.poetry]
|
|
10
|
+
packages = [{ include = "warpzone" }]
|
|
11
|
+
requires-poetry = ">=2.2"
|
|
12
|
+
|
|
13
|
+
[tool.poetry.dependencies]
|
|
14
|
+
pandas = ">=2.0.3"
|
|
15
|
+
polars = ">=1.33.1"
|
|
16
|
+
obstore = ">=0.8.2"
|
|
17
|
+
deltalake = ">=1.3.0"
|
|
18
|
+
pyarrow = ">=19.0.0"
|
|
19
|
+
datamazing = ">=5.1.6"
|
|
20
|
+
azure-core = ">=1.26.3"
|
|
21
|
+
azure-data-tables = ">=12.4.0"
|
|
22
|
+
azure-identity = ">=1.15.0"
|
|
23
|
+
azure-servicebus = "~7.8.0" # pin to avoid breaking changes with tracing in 7.9.0
|
|
24
|
+
azure-storage-blob = ">=12.14.1"
|
|
25
|
+
aiohttp = ">=3.8.3"
|
|
26
|
+
azure-core-tracing-opentelemetry = ">=1.0.0b12"
|
|
27
|
+
azure-monitor-opentelemetry-exporter = ">=1.0.0b36"
|
|
28
|
+
opentelemetry-sdk = ">=1.32.0"
|
|
29
|
+
azure-functions = ">=1.12.0"
|
|
30
|
+
typeguard = ">=4.0.1"
|
|
31
|
+
numpy = ">=1.26.4"
|
|
32
|
+
# pin cryptography to avoid bug on azure function python worker
|
|
33
|
+
# (https://github.com/Azure/azure-functions-python-worker/issues/1651)
|
|
34
|
+
cryptography = "43.0.3"
|
|
35
|
+
|
|
36
|
+
[tool.poetry.group.dev.dependencies]
|
|
37
|
+
pre-commit = ">=2.20.0"
|
|
38
|
+
|
|
39
|
+
[tool.poetry.group.test.dependencies]
|
|
40
|
+
pytest = ">=7"
|
|
41
|
+
pytest-cov = ">=3.0.0"
|
|
42
|
+
pytest-asyncio = ">=0.19.0"
|
|
43
|
+
freezegun = ">=1.2.2"
|
|
44
|
+
mypy = ">=1.19.0"
|
|
45
|
+
|
|
46
|
+
[build-system]
|
|
47
|
+
requires = ["poetry-core>=2.0.0,<3.0.0"]
|
|
48
|
+
build-backend = "poetry.core.masonry.api"
|
|
49
|
+
|
|
50
|
+
[tool.isort]
|
|
51
|
+
multi_line_output = 3
|
|
52
|
+
line_length = 88
|
|
53
|
+
include_trailing_comma = true
|
|
54
|
+
|
|
55
|
+
[tool.black]
|
|
56
|
+
line_length = 88
|
|
57
|
+
|
|
58
|
+
[tool.mypy]
|
|
59
|
+
ignore_missing_imports = true
|
|
@@ -186,8 +186,21 @@ class WarpzoneDatabaseClient:
|
|
|
186
186
|
|
|
187
187
|
pd_df = pl_df.to_pandas()
|
|
188
188
|
|
|
189
|
-
# We
|
|
189
|
+
# We truncate to second, and change to nanosecond
|
|
190
190
|
# precision because this was used by the old solution (Azure Table Storage)
|
|
191
191
|
for col in pd_df.select_dtypes(include=["datetime", "datetimetz"]).columns:
|
|
192
192
|
pd_df[col] = pd_df[col].dt.floor("s").dt.as_unit("ns")
|
|
193
|
+
|
|
194
|
+
# We remove the valid-from and valid-to columns, as well
|
|
195
|
+
# as any generated columns, as this was not present
|
|
196
|
+
# in the old solution (Azure Table Stroage)
|
|
197
|
+
generated_cols = []
|
|
198
|
+
for field in table.schema().fields:
|
|
199
|
+
if field.generated_as is not None:
|
|
200
|
+
generated_cols.append(field.column_name)
|
|
201
|
+
|
|
202
|
+
pd_df = pd_df.drop(
|
|
203
|
+
columns=["valid_from_time_utc", "valid_to_time_utc"] + generated_cols
|
|
204
|
+
)
|
|
205
|
+
|
|
193
206
|
return pd_df
|
warpzone_sdk-13.1.0/PKG-INFO
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: warpzone-sdk
|
|
3
|
-
Version: 13.1.0
|
|
4
|
-
Summary: The main objective of this package is to centralize logic used to interact with Azure Functions, Azure Service Bus and Azure Table Storage
|
|
5
|
-
Author: Mikkel Ladekarl Folmersen Nygaard
|
|
6
|
-
Author-email: mny@energinet.dk
|
|
7
|
-
Requires-Python: >=3.10,<4.0
|
|
8
|
-
Classifier: Programming Language :: Python :: 3
|
|
9
|
-
Classifier: Programming Language :: Python :: 3.10
|
|
10
|
-
Classifier: Programming Language :: Python :: 3.11
|
|
11
|
-
Classifier: Programming Language :: Python :: 3.12
|
|
12
|
-
Classifier: Programming Language :: Python :: 3.13
|
|
13
|
-
Classifier: Programming Language :: Python :: 3.14
|
|
14
|
-
Requires-Dist: aiohttp (>=3.8.3,<4.0.0)
|
|
15
|
-
Requires-Dist: azure-core (>=1.26.3,<2.0.0)
|
|
16
|
-
Requires-Dist: azure-core-tracing-opentelemetry (==1.0.0b12)
|
|
17
|
-
Requires-Dist: azure-data-tables (>=12.4.0,<13.0.0)
|
|
18
|
-
Requires-Dist: azure-functions (>=1.12.0,<2.0.0)
|
|
19
|
-
Requires-Dist: azure-identity (>=1.15.0,<2.0.0)
|
|
20
|
-
Requires-Dist: azure-monitor-opentelemetry-exporter (==1.0.0b36)
|
|
21
|
-
Requires-Dist: azure-servicebus (>=7.8.0,<7.9.0)
|
|
22
|
-
Requires-Dist: azure-storage-blob (>=12.14.1,<13.0.0)
|
|
23
|
-
Requires-Dist: cryptography (==43.0.3)
|
|
24
|
-
Requires-Dist: datamazing (>=5.1.0,<6.0.0)
|
|
25
|
-
Requires-Dist: deltalake (>=1.1.4,<2.0.0)
|
|
26
|
-
Requires-Dist: numpy (>=1.26.4,<2.0.0)
|
|
27
|
-
Requires-Dist: obstore (>=0.8.2,<0.9.0)
|
|
28
|
-
Requires-Dist: opentelemetry-sdk (==1.32.0)
|
|
29
|
-
Requires-Dist: pandas (>=2.0.3,<3.0.0)
|
|
30
|
-
Requires-Dist: polars (>=1.33.1,<2.0.0)
|
|
31
|
-
Requires-Dist: pyarrow (>=19.0.0,<20.0.0)
|
|
32
|
-
Requires-Dist: typeguard (>=4.0.1,<5.0.0)
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
[tool.poetry]
|
|
2
|
-
name = "warpzone-sdk"
|
|
3
|
-
version = "13.1.0"
|
|
4
|
-
description = "The main objective of this package is to centralize logic used to interact with Azure Functions, Azure Service Bus and Azure Table Storage"
|
|
5
|
-
authors = ["Mikkel Ladekarl Folmersen Nygaard <mny@energinet.dk>", "Ulrik Christensen <uch@energinet.dk>"]
|
|
6
|
-
packages = [
|
|
7
|
-
{ include = "warpzone" },
|
|
8
|
-
]
|
|
9
|
-
|
|
10
|
-
[tool.poetry.dependencies]
|
|
11
|
-
python = "^3.10"
|
|
12
|
-
pandas = "^2.0.3"
|
|
13
|
-
polars = "^1.33.1"
|
|
14
|
-
obstore = "^0.8.2"
|
|
15
|
-
deltalake = "^1.1.4"
|
|
16
|
-
pyarrow = "^19.0.0"
|
|
17
|
-
datamazing = "^5.1.0"
|
|
18
|
-
azure-core = "^1.26.3"
|
|
19
|
-
azure-data-tables = "^12.4.0"
|
|
20
|
-
azure-identity = "^1.15.0"
|
|
21
|
-
azure-servicebus = "~7.8.0"
|
|
22
|
-
azure-storage-blob = "^12.14.1"
|
|
23
|
-
aiohttp = "^3.8.3"
|
|
24
|
-
azure-core-tracing-opentelemetry = "1.0.0b12"
|
|
25
|
-
azure-monitor-opentelemetry-exporter = "1.0.0b36"
|
|
26
|
-
opentelemetry-sdk = "1.32.0"
|
|
27
|
-
azure-functions = "^1.12.0"
|
|
28
|
-
typeguard = "^4.0.1"
|
|
29
|
-
numpy = "^1.26.4"
|
|
30
|
-
# pin cryptography to avoid bug on azure function python worker
|
|
31
|
-
# (https://github.com/Azure/azure-functions-python-worker/issues/1651)
|
|
32
|
-
cryptography = "43.0.3"
|
|
33
|
-
|
|
34
|
-
[tool.poetry.dev-dependencies]
|
|
35
|
-
pytest = "^7"
|
|
36
|
-
pytest-cov = "^3.0.0"
|
|
37
|
-
pre-commit = "^2.20.0"
|
|
38
|
-
pytest-asyncio = "^0.19.0"
|
|
39
|
-
freezegun = "^1.2.2"
|
|
40
|
-
mypy = "^1.19.0"
|
|
41
|
-
|
|
42
|
-
[build-system]
|
|
43
|
-
requires = ["poetry-core>=1.0.0"]
|
|
44
|
-
build-backend = "poetry.core.masonry.api"
|
|
45
|
-
|
|
46
|
-
[tool.isort]
|
|
47
|
-
multi_line_output = 3
|
|
48
|
-
line_length = 88
|
|
49
|
-
include_trailing_comma = true
|
|
50
|
-
|
|
51
|
-
[tool.black]
|
|
52
|
-
line_length = 88
|
|
53
|
-
|
|
54
|
-
[tool.mypy]
|
|
55
|
-
ignore_missing_imports = true
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|