wt-runner 0.1.3__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.
- wt_runner-0.1.3/CHANGELOG.md +17 -0
- wt_runner-0.1.3/PKG-INFO +25 -0
- wt_runner-0.1.3/README.md +435 -0
- wt_runner-0.1.3/pyproject.toml +149 -0
- wt_runner-0.1.3/setup.cfg +4 -0
- wt_runner-0.1.3/src/wt_runner/__init__.py +36 -0
- wt_runner-0.1.3/src/wt_runner/_version.py +34 -0
- wt_runner-0.1.3/src/wt_runner/app.py +758 -0
- wt_runner-0.1.3/src/wt_runner/py.typed +0 -0
- wt_runner-0.1.3/src/wt_runner/testing.py +140 -0
- wt_runner-0.1.3/src/wt_runner/tracing.py +164 -0
- wt_runner-0.1.3/src/wt_runner.egg-info/PKG-INFO +25 -0
- wt_runner-0.1.3/src/wt_runner.egg-info/SOURCES.txt +21 -0
- wt_runner-0.1.3/src/wt_runner.egg-info/dependency_links.txt +1 -0
- wt_runner-0.1.3/src/wt_runner.egg-info/requires.txt +15 -0
- wt_runner-0.1.3/src/wt_runner.egg-info/top_level.txt +1 -0
- wt_runner-0.1.3/tests/__init__.py +1 -0
- wt_runner-0.1.3/tests/conftest.py +19 -0
- wt_runner-0.1.3/tests/test_app.py +294 -0
- wt_runner-0.1.3/tests/test_gcp_imports.py +11 -0
- wt_runner-0.1.3/tests/test_testing.py +159 -0
- wt_runner-0.1.3/tests/test_tracing.py +164 -0
- wt_runner-0.1.3/uv.lock +1624 -0
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## v0.1.3 — 2026-03-13
|
|
4
|
+
|
|
5
|
+
- Remove direct git reference from `wt-runner[gcp]` extras to fix PyPI publishing ([#71](https://github.com/wildlife-dynamics/wt/pull/71))
|
|
6
|
+
|
|
7
|
+
## v0.1.2 — 2026-03-13
|
|
8
|
+
|
|
9
|
+
- Bootstrap release for prefix.dev conda channel
|
|
10
|
+
|
|
11
|
+
## v0.1.1 — 2026-03-05
|
|
12
|
+
|
|
13
|
+
- Fix incorrect license metadata
|
|
14
|
+
|
|
15
|
+
## v0.1.0 — 2026-03-05
|
|
16
|
+
|
|
17
|
+
- Initial release
|
wt_runner-0.1.3/PKG-INFO
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: wt-runner
|
|
3
|
+
Version: 0.1.3
|
|
4
|
+
Summary: FastAPI application for workflow execution using wt-invokers
|
|
5
|
+
License: BSD-3-Clause
|
|
6
|
+
Classifier: Development Status :: 3 - Alpha
|
|
7
|
+
Classifier: Intended Audience :: Developers
|
|
8
|
+
Classifier: License :: OSI Approved :: BSD License
|
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
11
|
+
Requires-Python: <3.16,>=3.13
|
|
12
|
+
Requires-Dist: wt-contracts<1.0.0,>=0.1.0
|
|
13
|
+
Requires-Dist: wt-invokers<1.0.0,>=0.1.0
|
|
14
|
+
Requires-Dist: fastapi>=0.100.0
|
|
15
|
+
Requires-Dist: uvicorn>=0.20.0
|
|
16
|
+
Requires-Dist: pydantic<3.0.0,>=2.0.0
|
|
17
|
+
Requires-Dist: py-rattler>=0.8.0
|
|
18
|
+
Requires-Dist: ruamel.yaml>=0.18.0
|
|
19
|
+
Requires-Dist: opentelemetry-api>=1.0.0
|
|
20
|
+
Requires-Dist: opentelemetry-sdk>=1.0.0
|
|
21
|
+
Requires-Dist: obstore>=0.6.0
|
|
22
|
+
Provides-Extra: gcp
|
|
23
|
+
Requires-Dist: opentelemetry-sdk<2,>=1.37.0; extra == "gcp"
|
|
24
|
+
Requires-Dist: opentelemetry-exporter-gcp-trace<2,>=1.9.0; extra == "gcp"
|
|
25
|
+
Requires-Dist: gcloud-aio-pubsub<7,>=6.1.0; extra == "gcp"
|
|
@@ -0,0 +1,435 @@
|
|
|
1
|
+
# wt-runner
|
|
2
|
+
|
|
3
|
+
FastAPI application for executing workflows using wt-invokers.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
`wt-runner` is a production-ready web service that provides HTTP endpoints for executing workflows. It integrates with `wt-invokers` to support multiple execution backends (local subprocess, cloud batch, etc.) and provides comprehensive workflow management capabilities.
|
|
8
|
+
|
|
9
|
+
## Features
|
|
10
|
+
|
|
11
|
+
- **Workflow Execution**: Run workflows with various configurations via HTTP API
|
|
12
|
+
- **Pub/Sub Integration**: Process workflow requests from Google Cloud Pub/Sub
|
|
13
|
+
- **Metadata Endpoints**: Retrieve workflow schemas and metadata
|
|
14
|
+
- **Format Conversion**: Convert between parameter formats (params ↔ formdata)
|
|
15
|
+
- **OpenTelemetry Tracing**: Built-in distributed tracing support
|
|
16
|
+
- **Multiple Invokers**: Support for different execution backends via wt-invokers
|
|
17
|
+
|
|
18
|
+
## Installation
|
|
19
|
+
|
|
20
|
+
### Basic Installation
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
pip install wt-runner
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
### With Optional Dependencies
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
# For GCP support (tracing, Pub/Sub, ecoscope-eda-core)
|
|
30
|
+
pip install wt-runner[gcp]
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### Development Installation
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
cd wt-runner
|
|
37
|
+
uv sync --dev
|
|
38
|
+
uv run pytest
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Variants
|
|
42
|
+
|
|
43
|
+
`wt-runner` ships as a base package with an optional GCP variant:
|
|
44
|
+
|
|
45
|
+
| Variant | Package | Adds |
|
|
46
|
+
|---------|---------|------|
|
|
47
|
+
| **Base** | `wt-runner` | Workflow execution, result retrieval (obstore), all endpoints except Pub/Sub |
|
|
48
|
+
| **GCP** | `wt-runner-gcp` | Pub/Sub endpoint, GCP tracing, Cloud Batch deps (`wt-invokers-gcp`) |
|
|
49
|
+
|
|
50
|
+
### Installing variants
|
|
51
|
+
|
|
52
|
+
- **pip**: `pip install wt-runner[gcp]`
|
|
53
|
+
- **conda**: `pixi add wt-runner-gcp` (metapackage that pulls in `wt-runner` + all GCP deps)
|
|
54
|
+
- **Compiled workflows**: `wt-compiler compile --spec spec.yaml --variant gcp`
|
|
55
|
+
|
|
56
|
+
## Usage
|
|
57
|
+
|
|
58
|
+
### Starting the Server
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
# Basic usage
|
|
62
|
+
uvicorn wt_runner.app:app
|
|
63
|
+
|
|
64
|
+
# With custom host and port
|
|
65
|
+
uvicorn wt_runner.app:app --host 0.0.0.0 --port 8000
|
|
66
|
+
|
|
67
|
+
# With auto-reload for development
|
|
68
|
+
uvicorn wt_runner.app:app --reload
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### Using the FastAPI App in Code
|
|
72
|
+
|
|
73
|
+
```python
|
|
74
|
+
from wt_runner import app
|
|
75
|
+
|
|
76
|
+
# The app can be imported and used with any ASGI server
|
|
77
|
+
import uvicorn
|
|
78
|
+
uvicorn.run(app, host="0.0.0.0", port=8000)
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## API Endpoints
|
|
82
|
+
|
|
83
|
+
### Health Check
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
GET /
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Returns server health status.
|
|
90
|
+
|
|
91
|
+
**Response:**
|
|
92
|
+
```json
|
|
93
|
+
{
|
|
94
|
+
"status": "ok"
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### Run Workflow
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
POST /
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Execute a workflow with specified parameters.
|
|
105
|
+
|
|
106
|
+
**Query Parameters:**
|
|
107
|
+
- `matchspec` (required): Rattler matchspec for the workflow package
|
|
108
|
+
- `invoker_type` (optional): Type of invoker to use (default: `BlockingLocalSubprocessInvoker`)
|
|
109
|
+
- `results_url` (required): URL or path for storing results
|
|
110
|
+
- `workflow_run_id` (optional): Unique identifier for the workflow run
|
|
111
|
+
- `timeout` (optional): Timeout in seconds
|
|
112
|
+
- `docker_image_uri` (optional): Docker image URI for the workflow
|
|
113
|
+
|
|
114
|
+
**Request Body:**
|
|
115
|
+
```json
|
|
116
|
+
{
|
|
117
|
+
"params": {
|
|
118
|
+
"key": "value"
|
|
119
|
+
},
|
|
120
|
+
"execution_mode": "sequential",
|
|
121
|
+
"mock_io": false,
|
|
122
|
+
"data_connections_env_vars": {
|
|
123
|
+
"SECRET_KEY": "secret_value"
|
|
124
|
+
},
|
|
125
|
+
"lithops_config": {
|
|
126
|
+
"lithops": {
|
|
127
|
+
"backend": "localhost",
|
|
128
|
+
"storage": "localhost"
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
**Response:**
|
|
135
|
+
```json
|
|
136
|
+
{
|
|
137
|
+
"result": {...},
|
|
138
|
+
"error": null,
|
|
139
|
+
"trace": null
|
|
140
|
+
}
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### Run from Pub/Sub
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
POST /run-from-pubsub
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
Process workflow execution requests from Google Cloud Pub/Sub messages.
|
|
150
|
+
|
|
151
|
+
**Request Body:** (Pub/Sub message format)
|
|
152
|
+
```json
|
|
153
|
+
{
|
|
154
|
+
"message": {
|
|
155
|
+
"data": "base64-encoded-workflow-params"
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
**Response:**
|
|
161
|
+
```json
|
|
162
|
+
{
|
|
163
|
+
"status": "processed"
|
|
164
|
+
}
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
### Get RJSF Schema
|
|
168
|
+
|
|
169
|
+
```bash
|
|
170
|
+
GET /rjsf?matchspec=<workflow-matchspec>
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
Retrieve the React JSON Schema Form schema for a workflow.
|
|
174
|
+
|
|
175
|
+
**Response:**
|
|
176
|
+
```json
|
|
177
|
+
{
|
|
178
|
+
"schema": {...},
|
|
179
|
+
"uiSchema": {...}
|
|
180
|
+
}
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
### Get Data Connection Property Names
|
|
184
|
+
|
|
185
|
+
```bash
|
|
186
|
+
GET /data-connection-property-names?matchspec=<workflow-matchspec>
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
Retrieve data connection property names for a workflow.
|
|
190
|
+
|
|
191
|
+
### Convert Form Data to Params
|
|
192
|
+
|
|
193
|
+
```bash
|
|
194
|
+
POST /formdata-to-params?matchspec=<workflow-matchspec>
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
Convert form data format to workflow parameters.
|
|
198
|
+
|
|
199
|
+
**Request Body:**
|
|
200
|
+
```json
|
|
201
|
+
{
|
|
202
|
+
"field1": "value1",
|
|
203
|
+
"field2": "value2"
|
|
204
|
+
}
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
### Convert Params to Form Data
|
|
208
|
+
|
|
209
|
+
```bash
|
|
210
|
+
POST /params-to-formdata?matchspec=<workflow-matchspec>
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
Convert workflow parameters to form data format.
|
|
214
|
+
|
|
215
|
+
**Request Body:**
|
|
216
|
+
```json
|
|
217
|
+
{
|
|
218
|
+
"param1": "value1",
|
|
219
|
+
"param2": "value2"
|
|
220
|
+
}
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
## Configuration
|
|
224
|
+
|
|
225
|
+
### Environment Variables
|
|
226
|
+
|
|
227
|
+
- `ECOSCOPE_WORKFLOWS_MATCHSPEC_OVERRIDE`: Override matchspec for all requests
|
|
228
|
+
- `ECOSCOPE_WORKFLOWS_OTEL_EXPORTER`: OpenTelemetry exporter type (`console` or `gcp`)
|
|
229
|
+
- `ECOSCOPE_WORKFLOWS_OTEL_CONSOLE_EXPORTER_DST`: Console exporter destination (`stdout` or `file`)
|
|
230
|
+
- `ECOSCOPE_WORKFLOWS_OTEL_CONSOLE_EXPORTER_FILE_DST_TARGET_DIR`: Directory for trace files
|
|
231
|
+
|
|
232
|
+
### OpenTelemetry Tracing
|
|
233
|
+
|
|
234
|
+
Enable tracing by setting environment variables:
|
|
235
|
+
|
|
236
|
+
```bash
|
|
237
|
+
# Console exporter (stdout)
|
|
238
|
+
export ECOSCOPE_WORKFLOWS_OTEL_EXPORTER=console
|
|
239
|
+
export ECOSCOPE_WORKFLOWS_OTEL_CONSOLE_EXPORTER_DST=stdout
|
|
240
|
+
|
|
241
|
+
# Console exporter (file)
|
|
242
|
+
export ECOSCOPE_WORKFLOWS_OTEL_EXPORTER=console
|
|
243
|
+
export ECOSCOPE_WORKFLOWS_OTEL_CONSOLE_EXPORTER_DST=file
|
|
244
|
+
export ECOSCOPE_WORKFLOWS_OTEL_CONSOLE_EXPORTER_FILE_DST_TARGET_DIR=/path/to/traces
|
|
245
|
+
|
|
246
|
+
# GCP Cloud Trace
|
|
247
|
+
export ECOSCOPE_WORKFLOWS_OTEL_EXPORTER=gcp
|
|
248
|
+
export GOOGLE_APPLICATION_CREDENTIALS=/path/to/credentials.json
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
### Programmatic Tracing Configuration
|
|
252
|
+
|
|
253
|
+
```python
|
|
254
|
+
from wt_runner import configure_tracer
|
|
255
|
+
|
|
256
|
+
configure_tracer(
|
|
257
|
+
name="my-service",
|
|
258
|
+
version="1.0.0",
|
|
259
|
+
exporter="console",
|
|
260
|
+
exporter_kws={}
|
|
261
|
+
)
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
## Development
|
|
265
|
+
|
|
266
|
+
### Running Tests
|
|
267
|
+
|
|
268
|
+
```bash
|
|
269
|
+
# Core tests (GCP tests skipped)
|
|
270
|
+
uv sync --dev
|
|
271
|
+
uv run pytest
|
|
272
|
+
|
|
273
|
+
# Full tests including GCP (Pub/Sub, tracing)
|
|
274
|
+
uv sync --extra gcp --dev
|
|
275
|
+
uv run pytest
|
|
276
|
+
|
|
277
|
+
# Run with coverage
|
|
278
|
+
uv run pytest --cov=wt_runner --cov-report=term-missing
|
|
279
|
+
|
|
280
|
+
# Run specific test file
|
|
281
|
+
uv run pytest tests/test_app.py
|
|
282
|
+
|
|
283
|
+
# Run with verbose output
|
|
284
|
+
uv run pytest -v
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
### Type Checking
|
|
288
|
+
|
|
289
|
+
```bash
|
|
290
|
+
uv run mypy src/wt_runner
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
### Linting and Formatting
|
|
294
|
+
|
|
295
|
+
```bash
|
|
296
|
+
# Check code
|
|
297
|
+
uv run ruff check src/wt_runner
|
|
298
|
+
|
|
299
|
+
# Format code
|
|
300
|
+
uv run ruff format src/wt_runner
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
## Architecture
|
|
304
|
+
|
|
305
|
+
### Dependencies
|
|
306
|
+
|
|
307
|
+
- **wt-invokers**: Provides workflow execution backends (required)
|
|
308
|
+
- **wt-contracts**: Shared interface contracts (required)
|
|
309
|
+
- **FastAPI**: Web framework for API endpoints
|
|
310
|
+
- **Uvicorn**: ASGI server for running the application
|
|
311
|
+
- **Rattler**: Conda package management
|
|
312
|
+
- **OpenTelemetry**: Distributed tracing (optional)
|
|
313
|
+
- **obstore**: Object storage for result retrieval (required)
|
|
314
|
+
|
|
315
|
+
### Package Structure
|
|
316
|
+
|
|
317
|
+
```
|
|
318
|
+
wt-runner/
|
|
319
|
+
├── src/wt_runner/
|
|
320
|
+
│ ├── __init__.py # Package exports
|
|
321
|
+
│ ├── app.py # FastAPI application
|
|
322
|
+
│ ├── tracing.py # OpenTelemetry tracing
|
|
323
|
+
│ └── _version.py # Version info (auto-generated)
|
|
324
|
+
├── tests/
|
|
325
|
+
│ ├── test_app.py # Endpoint tests
|
|
326
|
+
│ ├── test_tracing.py # Tracing tests
|
|
327
|
+
│ └── conftest.py # Pytest configuration
|
|
328
|
+
├── pyproject.toml # Package metadata
|
|
329
|
+
└── README.md
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
## Invoker Support
|
|
333
|
+
|
|
334
|
+
The runner supports all invokers provided by `wt-invokers`:
|
|
335
|
+
|
|
336
|
+
- `BlockingLocalSubprocessInvoker`: Synchronous local subprocess execution
|
|
337
|
+
- `AsyncLocalSubprocessInvoker`: Asynchronous local subprocess execution
|
|
338
|
+
- `CloudBatchInvoker`: Google Cloud Batch execution (requires GCP dependencies)
|
|
339
|
+
|
|
340
|
+
See [wt-invokers documentation](../wt-invokers/README.md) for more details.
|
|
341
|
+
|
|
342
|
+
## Error Handling
|
|
343
|
+
|
|
344
|
+
The runner provides comprehensive error handling:
|
|
345
|
+
|
|
346
|
+
- **400 Bad Request**: Invalid request parameters
|
|
347
|
+
- **422 Unprocessable Entity**: Validation errors
|
|
348
|
+
- **500 Internal Server Error**: Workflow execution failures
|
|
349
|
+
- **503 Service Unavailable**: Timeout errors
|
|
350
|
+
|
|
351
|
+
All errors include detailed trace information in the response.
|
|
352
|
+
|
|
353
|
+
## Examples
|
|
354
|
+
|
|
355
|
+
### Basic Workflow Execution
|
|
356
|
+
|
|
357
|
+
```python
|
|
358
|
+
import httpx
|
|
359
|
+
|
|
360
|
+
response = httpx.post(
|
|
361
|
+
"http://localhost:8000/",
|
|
362
|
+
params={
|
|
363
|
+
"matchspec": "my-workflow>=1.0",
|
|
364
|
+
"results_url": "gs://bucket/results",
|
|
365
|
+
},
|
|
366
|
+
json={
|
|
367
|
+
"params": {"input": "data"},
|
|
368
|
+
"execution_mode": "sequential",
|
|
369
|
+
"mock_io": False,
|
|
370
|
+
},
|
|
371
|
+
)
|
|
372
|
+
|
|
373
|
+
result = response.json()
|
|
374
|
+
print(result["result"])
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
### With Custom Invoker
|
|
378
|
+
|
|
379
|
+
```python
|
|
380
|
+
response = httpx.post(
|
|
381
|
+
"http://localhost:8000/",
|
|
382
|
+
params={
|
|
383
|
+
"matchspec": "my-workflow>=1.0",
|
|
384
|
+
"invoker_type": "AsyncLocalSubprocessInvoker",
|
|
385
|
+
"results_url": "gs://bucket/results",
|
|
386
|
+
},
|
|
387
|
+
json={
|
|
388
|
+
"params": {"input": "data"},
|
|
389
|
+
"execution_mode": "async",
|
|
390
|
+
"mock_io": False,
|
|
391
|
+
},
|
|
392
|
+
)
|
|
393
|
+
```
|
|
394
|
+
|
|
395
|
+
### With Tracing
|
|
396
|
+
|
|
397
|
+
```python
|
|
398
|
+
response = httpx.post(
|
|
399
|
+
"http://localhost:8000/",
|
|
400
|
+
params={
|
|
401
|
+
"matchspec": "my-workflow>=1.0",
|
|
402
|
+
"results_url": "gs://bucket/results",
|
|
403
|
+
},
|
|
404
|
+
headers={
|
|
405
|
+
"traceparent": "00-trace-id-span-id-01",
|
|
406
|
+
},
|
|
407
|
+
json={
|
|
408
|
+
"params": {"input": "data"},
|
|
409
|
+
"execution_mode": "sequential",
|
|
410
|
+
"mock_io": False,
|
|
411
|
+
},
|
|
412
|
+
)
|
|
413
|
+
```
|
|
414
|
+
|
|
415
|
+
## Contributing
|
|
416
|
+
|
|
417
|
+
Contributions are welcome! Please ensure:
|
|
418
|
+
|
|
419
|
+
1. All tests pass: `uv run pytest`
|
|
420
|
+
2. Type checking passes: `uv run mypy src/wt_runner`
|
|
421
|
+
3. Code is formatted: `uv run ruff format src/wt_runner`
|
|
422
|
+
4. Test coverage remains >90%
|
|
423
|
+
5. All public functions have docstrings
|
|
424
|
+
|
|
425
|
+
## License
|
|
426
|
+
|
|
427
|
+
BSD-3-Clause
|
|
428
|
+
|
|
429
|
+
## Related Packages
|
|
430
|
+
|
|
431
|
+
- [wt-contracts](../wt-contracts/README.md): Shared interface contracts
|
|
432
|
+
- [wt-invokers](../wt-invokers/README.md): Workflow execution backends
|
|
433
|
+
- [wt-task](../wt-task/README.md): Task decorator and execution
|
|
434
|
+
- [wt-compiler](../wt-compiler/README.md): Workflow compilation
|
|
435
|
+
- [wt-registry](../wt-registry/README.md): Function registration
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=64", "setuptools-scm>=8"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "wt-runner"
|
|
7
|
+
dynamic = ["version"]
|
|
8
|
+
description = "FastAPI application for workflow execution using wt-invokers"
|
|
9
|
+
requires-python = ">=3.13,<3.16"
|
|
10
|
+
license = { text = "BSD-3-Clause" }
|
|
11
|
+
classifiers = [
|
|
12
|
+
"Development Status :: 3 - Alpha",
|
|
13
|
+
"Intended Audience :: Developers",
|
|
14
|
+
"License :: OSI Approved :: BSD License",
|
|
15
|
+
"Programming Language :: Python :: 3",
|
|
16
|
+
"Programming Language :: Python :: 3.13",
|
|
17
|
+
]
|
|
18
|
+
dependencies = [
|
|
19
|
+
"wt-contracts>=0.1.0,<1.0.0",
|
|
20
|
+
"wt-invokers>=0.1.0,<1.0.0",
|
|
21
|
+
"fastapi>=0.100.0",
|
|
22
|
+
"uvicorn>=0.20.0",
|
|
23
|
+
"pydantic>=2.0.0,<3.0.0",
|
|
24
|
+
"py-rattler>=0.8.0",
|
|
25
|
+
"ruamel.yaml>=0.18.0",
|
|
26
|
+
"opentelemetry-api>=1.0.0",
|
|
27
|
+
"opentelemetry-sdk>=1.0.0",
|
|
28
|
+
"obstore>=0.6.0",
|
|
29
|
+
]
|
|
30
|
+
|
|
31
|
+
[project.optional-dependencies]
|
|
32
|
+
# Google Cloud Platform dependencies (tracing, Pub/Sub)
|
|
33
|
+
# Note: ecoscope-eda-core is excluded here because PyPI forbids direct git
|
|
34
|
+
# references in extras. Install it separately or use the wt-runner-gcp conda
|
|
35
|
+
# metapackage which includes it.
|
|
36
|
+
gcp = [
|
|
37
|
+
"opentelemetry-sdk>=1.37.0,<2",
|
|
38
|
+
"opentelemetry-exporter-gcp-trace>=1.9.0,<2",
|
|
39
|
+
"gcloud-aio-pubsub>=6.1.0,<7",
|
|
40
|
+
]
|
|
41
|
+
|
|
42
|
+
[dependency-groups]
|
|
43
|
+
dev = [
|
|
44
|
+
"pytest>=7.0.0",
|
|
45
|
+
"pytest-asyncio>=0.21.0",
|
|
46
|
+
"pytest-cov>=4.0.0",
|
|
47
|
+
"httpx>=0.24.0", # For FastAPI testing
|
|
48
|
+
"mypy>=1.0.0",
|
|
49
|
+
"ruff>=0.1.0",
|
|
50
|
+
]
|
|
51
|
+
|
|
52
|
+
[tool.uv.sources]
|
|
53
|
+
# Development override - uses local editable packages
|
|
54
|
+
# Published packages will reference PyPI version normally
|
|
55
|
+
wt-contracts = { path = "../wt-contracts", editable = true }
|
|
56
|
+
wt-invokers = { path = "../wt-invokers", editable = true }
|
|
57
|
+
|
|
58
|
+
[tool.setuptools.packages.find]
|
|
59
|
+
where = ["src"]
|
|
60
|
+
|
|
61
|
+
[tool.setuptools_scm]
|
|
62
|
+
# Version comes from git tags matching this pattern
|
|
63
|
+
tag_regex = "^wt-runner/v(?P<version>[0-9.]+)$"
|
|
64
|
+
# Root is the git repository root
|
|
65
|
+
root = ".."
|
|
66
|
+
# Generate version file
|
|
67
|
+
version_file = "src/wt_runner/_version.py"
|
|
68
|
+
git_describe_command = ["git", "describe", "--dirty", "--tags", "--long", "--match", "wt-runner/v*"]
|
|
69
|
+
|
|
70
|
+
[tool.pytest.ini_options]
|
|
71
|
+
testpaths = ["tests"]
|
|
72
|
+
asyncio_mode = "auto"
|
|
73
|
+
addopts = "--cov=wt_runner --cov-report=term-missing"
|
|
74
|
+
|
|
75
|
+
[tool.mypy]
|
|
76
|
+
python_version = "3.13"
|
|
77
|
+
strict = true
|
|
78
|
+
warn_return_any = true
|
|
79
|
+
warn_unused_configs = true
|
|
80
|
+
plugins = ["pydantic.mypy"]
|
|
81
|
+
|
|
82
|
+
[[tool.mypy.overrides]]
|
|
83
|
+
module = [
|
|
84
|
+
"opentelemetry",
|
|
85
|
+
"opentelemetry.*",
|
|
86
|
+
]
|
|
87
|
+
ignore_missing_imports = true
|
|
88
|
+
|
|
89
|
+
[[tool.mypy.overrides]]
|
|
90
|
+
module = ["wt_runner.tracing"]
|
|
91
|
+
warn_unused_ignores = false
|
|
92
|
+
|
|
93
|
+
[tool.ruff]
|
|
94
|
+
target-version = "py313"
|
|
95
|
+
line-length = 100
|
|
96
|
+
|
|
97
|
+
[tool.ruff.lint]
|
|
98
|
+
select = [
|
|
99
|
+
"E", # pycodestyle errors
|
|
100
|
+
"W", # pycodestyle warnings
|
|
101
|
+
"F", # pyflakes
|
|
102
|
+
"I", # isort
|
|
103
|
+
"B", # flake8-bugbear
|
|
104
|
+
"C4", # flake8-comprehensions
|
|
105
|
+
"UP", # pyupgrade
|
|
106
|
+
]
|
|
107
|
+
ignore = []
|
|
108
|
+
|
|
109
|
+
[tool.ruff.lint.per-file-ignores]
|
|
110
|
+
"__init__.py" = ["F401"] # Allow unused imports in __init__.py
|
|
111
|
+
|
|
112
|
+
[tool.ruff.lint.flake8-bugbear]
|
|
113
|
+
extend-immutable-calls = [
|
|
114
|
+
"fastapi.Query",
|
|
115
|
+
"fastapi.Depends",
|
|
116
|
+
]
|
|
117
|
+
|
|
118
|
+
# ============================================================================
|
|
119
|
+
# Pixi Build Configuration (conda package building)
|
|
120
|
+
# ============================================================================
|
|
121
|
+
|
|
122
|
+
[tool.pixi.package]
|
|
123
|
+
name = "wt-runner"
|
|
124
|
+
version = "0.1.3"
|
|
125
|
+
|
|
126
|
+
[tool.pixi.package.build]
|
|
127
|
+
backend = { name = "pixi-build-python", version = "*", channels = ["conda-forge", "https://prefix.dev/pixi-build-backends"] }
|
|
128
|
+
|
|
129
|
+
[tool.pixi.package.build.config]
|
|
130
|
+
noarch = true
|
|
131
|
+
|
|
132
|
+
[tool.pixi.package.host-dependencies]
|
|
133
|
+
python = ">=3.13,<3.16"
|
|
134
|
+
setuptools = ">=64"
|
|
135
|
+
setuptools-scm = ">=8"
|
|
136
|
+
pip = "*"
|
|
137
|
+
|
|
138
|
+
[tool.pixi.package.run-dependencies]
|
|
139
|
+
python = ">=3.13,<3.16"
|
|
140
|
+
fastapi = ">=0.100.0"
|
|
141
|
+
uvicorn = ">=0.20.0"
|
|
142
|
+
pydantic = ">=2.0.0,<3.0.0"
|
|
143
|
+
py-rattler = ">=0.8.0"
|
|
144
|
+
"ruamel.yaml" = ">=0.18.0"
|
|
145
|
+
opentelemetry-api = ">=1.0.0"
|
|
146
|
+
opentelemetry-sdk = ">=1.0.0"
|
|
147
|
+
obstore = ">=0.6.0"
|
|
148
|
+
wt-contracts = ">=0.1.0,<1.0.0"
|
|
149
|
+
wt-invokers = ">=0.1.0,<1.0.0"
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"""wt-runner: FastAPI application for workflow execution.
|
|
2
|
+
|
|
3
|
+
This package provides a FastAPI web service for executing workflows using
|
|
4
|
+
wt-invokers. It includes endpoints for:
|
|
5
|
+
- Running workflows with various configurations
|
|
6
|
+
- Processing Pub/Sub messages
|
|
7
|
+
- Retrieving workflow metadata and schemas
|
|
8
|
+
- Converting between parameter formats
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from wt_runner.app import app
|
|
12
|
+
from wt_runner.testing import Case, CaseRunner
|
|
13
|
+
from wt_runner.tracing import (
|
|
14
|
+
TraceContextHeaders,
|
|
15
|
+
attach_context,
|
|
16
|
+
build_context_headers,
|
|
17
|
+
configure_tracer,
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
try:
|
|
21
|
+
from wt_runner._version import __version__, __version_tuple__
|
|
22
|
+
except ImportError:
|
|
23
|
+
__version__ = "unknown"
|
|
24
|
+
__version_tuple__ = (0, 0, 0)
|
|
25
|
+
|
|
26
|
+
__all__ = [
|
|
27
|
+
"app",
|
|
28
|
+
"Case",
|
|
29
|
+
"CaseRunner",
|
|
30
|
+
"configure_tracer",
|
|
31
|
+
"attach_context",
|
|
32
|
+
"build_context_headers",
|
|
33
|
+
"TraceContextHeaders",
|
|
34
|
+
"__version__",
|
|
35
|
+
"__version_tuple__",
|
|
36
|
+
]
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# file generated by setuptools-scm
|
|
2
|
+
# don't change, don't track in version control
|
|
3
|
+
|
|
4
|
+
__all__ = [
|
|
5
|
+
"__version__",
|
|
6
|
+
"__version_tuple__",
|
|
7
|
+
"version",
|
|
8
|
+
"version_tuple",
|
|
9
|
+
"__commit_id__",
|
|
10
|
+
"commit_id",
|
|
11
|
+
]
|
|
12
|
+
|
|
13
|
+
TYPE_CHECKING = False
|
|
14
|
+
if TYPE_CHECKING:
|
|
15
|
+
from typing import Tuple
|
|
16
|
+
from typing import Union
|
|
17
|
+
|
|
18
|
+
VERSION_TUPLE = Tuple[Union[int, str], ...]
|
|
19
|
+
COMMIT_ID = Union[str, None]
|
|
20
|
+
else:
|
|
21
|
+
VERSION_TUPLE = object
|
|
22
|
+
COMMIT_ID = object
|
|
23
|
+
|
|
24
|
+
version: str
|
|
25
|
+
__version__: str
|
|
26
|
+
__version_tuple__: VERSION_TUPLE
|
|
27
|
+
version_tuple: VERSION_TUPLE
|
|
28
|
+
commit_id: COMMIT_ID
|
|
29
|
+
__commit_id__: COMMIT_ID
|
|
30
|
+
|
|
31
|
+
__version__ = version = '0.1.3'
|
|
32
|
+
__version_tuple__ = version_tuple = (0, 1, 3)
|
|
33
|
+
|
|
34
|
+
__commit_id__ = commit_id = 'g9ca3e09'
|