fastprocesses 0.7.4__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.
- fastprocesses/__init__.py +8 -0
- fastprocesses/api/__init__.py +0 -0
- fastprocesses/api/manager.py +377 -0
- fastprocesses/api/router.py +177 -0
- fastprocesses/api/server.py +24 -0
- fastprocesses/celery_worker.py +45 -0
- fastprocesses/common.py +59 -0
- fastprocesses/core/__init__.py +0 -0
- fastprocesses/core/base_process.py +137 -0
- fastprocesses/core/cache.py +55 -0
- fastprocesses/core/config.py +17 -0
- fastprocesses/core/logging.py +75 -0
- fastprocesses/core/models.py +188 -0
- fastprocesses/processes/__init__.py +0 -0
- fastprocesses/processes/process_registry.py +114 -0
- fastprocesses/py.typed +0 -0
- fastprocesses/worker/__init__.py +0 -0
- fastprocesses/worker/celery_app.py +154 -0
- fastprocesses-0.7.4.dist-info/AUTHORS.md +1 -0
- fastprocesses-0.7.4.dist-info/METADATA +274 -0
- fastprocesses-0.7.4.dist-info/RECORD +23 -0
- fastprocesses-0.7.4.dist-info/WHEEL +4 -0
- fastprocesses-0.7.4.dist-info/entry_points.txt +3 -0
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
# worker/celery_app.py
|
|
2
|
+
import asyncio
|
|
3
|
+
from datetime import datetime, timezone
|
|
4
|
+
import json
|
|
5
|
+
from typing import Any, Dict
|
|
6
|
+
|
|
7
|
+
from celery import Task
|
|
8
|
+
from pydantic import BaseModel
|
|
9
|
+
|
|
10
|
+
from fastprocesses.common import celery_app, redis_cache
|
|
11
|
+
from fastprocesses.core.logging import logger
|
|
12
|
+
from fastprocesses.core.models import CalculationTask
|
|
13
|
+
from fastprocesses.processes.process_registry import get_process_registry
|
|
14
|
+
|
|
15
|
+
from celery.exceptions import SoftTimeLimitExceeded
|
|
16
|
+
|
|
17
|
+
# NOTE: Cache hash key is based on original unprocessed inputs always
|
|
18
|
+
# this ensures consistent caching and cache retrieval
|
|
19
|
+
# which does not depend on arbitrary processed data, which can change
|
|
20
|
+
# when the process is updated or changed!
|
|
21
|
+
|
|
22
|
+
class CacheResultTask(Task):
|
|
23
|
+
def on_success(
|
|
24
|
+
self, retval: dict | BaseModel,
|
|
25
|
+
task_id, args, kwargs
|
|
26
|
+
):
|
|
27
|
+
try:
|
|
28
|
+
# Deserialize the original data
|
|
29
|
+
original_data = json.loads(args[1])
|
|
30
|
+
calculation_task = CalculationTask(**original_data)
|
|
31
|
+
|
|
32
|
+
# Get the the hash key for the task
|
|
33
|
+
key = calculation_task.celery_key
|
|
34
|
+
|
|
35
|
+
# Store the result in cache
|
|
36
|
+
# Use the task ID as the key
|
|
37
|
+
redis_cache.put(key=key, value=retval)
|
|
38
|
+
|
|
39
|
+
logger.info(f"Saved result with key {key} to cache: {retval}")
|
|
40
|
+
except Exception as e:
|
|
41
|
+
logger.error(f"Error caching results: {e}")
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
@celery_app.task(bind=True, name="execute_process", base=CacheResultTask)
|
|
45
|
+
def execute_process(self, process_id: str, serialized_data: Dict[str, Any]):
|
|
46
|
+
|
|
47
|
+
data = json.loads(serialized_data)
|
|
48
|
+
|
|
49
|
+
logger.info(f"Executing process {process_id} with data {data}")
|
|
50
|
+
job_id = self.request.id # Get the task/job ID
|
|
51
|
+
|
|
52
|
+
# Create a progress update function that captures the job_id
|
|
53
|
+
def update_progress(progress: int, message: str = None):
|
|
54
|
+
job_key = f"job:{job_id}"
|
|
55
|
+
job_info = redis_cache.get(job_key) or {}
|
|
56
|
+
|
|
57
|
+
job_info.update(
|
|
58
|
+
{
|
|
59
|
+
"status": "running",
|
|
60
|
+
"progress": progress,
|
|
61
|
+
"updated": datetime.now(timezone.utc),
|
|
62
|
+
"process_id": process_id,
|
|
63
|
+
}
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
if message:
|
|
67
|
+
job_info["message"] = message
|
|
68
|
+
|
|
69
|
+
redis_cache.put(job_key, job_info)
|
|
70
|
+
logger.debug(f"Updated progress for job {job_id}: {progress}%, {message}")
|
|
71
|
+
|
|
72
|
+
try:
|
|
73
|
+
# Initialize progress
|
|
74
|
+
update_progress(0, "Starting process")
|
|
75
|
+
|
|
76
|
+
service = get_process_registry().get_service(process_id)
|
|
77
|
+
|
|
78
|
+
if asyncio.iscoroutinefunction(service.execute):
|
|
79
|
+
result = asyncio.run(
|
|
80
|
+
service.execute(
|
|
81
|
+
data,
|
|
82
|
+
progress_callback=update_progress,
|
|
83
|
+
)
|
|
84
|
+
)
|
|
85
|
+
else:
|
|
86
|
+
result = service.execute(data)
|
|
87
|
+
|
|
88
|
+
logger.info(f"Process {process_id} executed successfully with result {result}")
|
|
89
|
+
|
|
90
|
+
# Mark job as complete
|
|
91
|
+
update_progress(100, "Process completed")
|
|
92
|
+
|
|
93
|
+
return result
|
|
94
|
+
except SoftTimeLimitExceeded as e:
|
|
95
|
+
logger.warning(f"Task {job_id} hit the soft time limit: {e}")
|
|
96
|
+
# Attempt to resume the process
|
|
97
|
+
try:
|
|
98
|
+
if asyncio.iscoroutinefunction(service.execute):
|
|
99
|
+
result = asyncio.run(service.execute(data))
|
|
100
|
+
else:
|
|
101
|
+
result = service.execute(data)
|
|
102
|
+
|
|
103
|
+
logger.info(f"Process {process_id} completed after soft time limit")
|
|
104
|
+
update_progress(100, "Process completed after soft time limit")
|
|
105
|
+
return result
|
|
106
|
+
except Exception as inner_exception:
|
|
107
|
+
logger.error(
|
|
108
|
+
f"Error while completing task after soft time limit: {inner_exception}"
|
|
109
|
+
)
|
|
110
|
+
raise inner_exception
|
|
111
|
+
|
|
112
|
+
except Exception as e:
|
|
113
|
+
# Update job with error status
|
|
114
|
+
job_key = f"job:{job_id}"
|
|
115
|
+
job_info = redis_cache.get(job_key) or {}
|
|
116
|
+
job_info.update(
|
|
117
|
+
{
|
|
118
|
+
"status": "failed",
|
|
119
|
+
"message": str(e),
|
|
120
|
+
"updated": datetime.now(timezone.utc),
|
|
121
|
+
"process_id": process_id,
|
|
122
|
+
}
|
|
123
|
+
)
|
|
124
|
+
redis_cache.put(job_key, job_info)
|
|
125
|
+
|
|
126
|
+
logger.error(f"Error executing process {process_id}: {e}")
|
|
127
|
+
raise
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
@celery_app.task(name="check_cache")
|
|
131
|
+
def check_cache(calculation_task: Dict[str, Any]) -> Dict[str, Any]:
|
|
132
|
+
"""
|
|
133
|
+
Check if results exist in cache and return status
|
|
134
|
+
"""
|
|
135
|
+
task = CalculationTask(**calculation_task)
|
|
136
|
+
cached_result = redis_cache.get(key=task.celery_key)
|
|
137
|
+
|
|
138
|
+
if cached_result:
|
|
139
|
+
logger.info(f"Cache hit for key {task.celery_key}")
|
|
140
|
+
return {"status": "HIT", "result": cached_result}
|
|
141
|
+
|
|
142
|
+
logger.info(f"Cache miss for key {task.celery_key}")
|
|
143
|
+
return {"status": "MISS"}
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
@celery_app.task(name="find_result_in_cache")
|
|
147
|
+
def find_result_in_cache(celery_key: str) -> dict | None:
|
|
148
|
+
"""
|
|
149
|
+
Retrieve result from cache
|
|
150
|
+
"""
|
|
151
|
+
result = redis_cache.get(key=celery_key)
|
|
152
|
+
if result:
|
|
153
|
+
logger.info(f"Retrieved result from cache for key {celery_key}")
|
|
154
|
+
return result
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# Authors
|
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
|
+
Name: fastprocesses
|
|
3
|
+
Version: 0.7.4
|
|
4
|
+
Summary: A library to create a FastAPI-based OGC API Processes wrapper around existing projects.
|
|
5
|
+
Author: Stefan Schuhart
|
|
6
|
+
Author-email: stefan.schuhart@gv.hamburg.de
|
|
7
|
+
Requires-Python: >=3.10
|
|
8
|
+
Classifier: Development Status :: 3 - Alpha
|
|
9
|
+
Classifier: Intended Audience :: Developers
|
|
10
|
+
Classifier: Programming Language :: Python
|
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
|
12
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Classifier: Topic :: Software Development
|
|
17
|
+
Classifier: Topic :: Utilities
|
|
18
|
+
Classifier: Typing :: Typed
|
|
19
|
+
Requires-Dist: celery (>=5.4.0,<6.0.0)
|
|
20
|
+
Requires-Dist: fastapi (>=0.115.8,<0.116.0)
|
|
21
|
+
Requires-Dist: loguru (>=0.7.3,<0.8.0)
|
|
22
|
+
Requires-Dist: pydantic (>=2.10.6,<3.0.0)
|
|
23
|
+
Requires-Dist: pydantic-settings (>=2.7.1,<3.0.0)
|
|
24
|
+
Requires-Dist: redis (>=5.2.1,<6.0.0)
|
|
25
|
+
Requires-Dist: uvicorn (>=0.34.0,<0.35.0)
|
|
26
|
+
Project-URL: Changelog, https://github.com/geowerkstatt-hamburg/fastProcesses/CHANGELOG.md
|
|
27
|
+
Project-URL: Documentation, https://github.com/geowerkstatt-hamburg/fastProcesses/README.md
|
|
28
|
+
Project-URL: Homepage, https://geowerkstatt-hamburg.github.io/fastProcesses
|
|
29
|
+
Project-URL: Repository, https://github.com/geowerkstatt-hamburg/fastProcesses
|
|
30
|
+
Description-Content-Type: text/markdown
|
|
31
|
+
|
|
32
|
+
# fastprocesses
|
|
33
|
+
|
|
34
|
+
A library to create a FastAPI-based OGC API Processes wrapper around existing projects. This library simplifies the process of defining and registering processes, making it easy to build and deploy OGC API Processes.
|
|
35
|
+
|
|
36
|
+
AI was used to create this code.
|
|
37
|
+
|
|
38
|
+
## Version: 0.7.4
|
|
39
|
+
|
|
40
|
+
### Description
|
|
41
|
+
|
|
42
|
+
fastprocesses is a Python library that provides a simple and efficient way to create OGC API Processes using FastAPI. It allows you to define processes, register them, and expose them through a FastAPI application with minimal effort, following the OGC API Processes 1.0.0 specification.
|
|
43
|
+
|
|
44
|
+
### Features
|
|
45
|
+
|
|
46
|
+
- **OGC API Processes Compliance**: Fully implements the OGC API Processes 1.0.0 Core specification
|
|
47
|
+
- **FastAPI Integration**: Leverages FastAPI for building high-performance APIs
|
|
48
|
+
- **Process Management**: Supports both synchronous and asynchronous process execution
|
|
49
|
+
- **Job Control**: Implements job control options (sync-execute, async-execute)
|
|
50
|
+
- **Output Handling**: Supports various output transmission modes (value, reference)
|
|
51
|
+
- **Result Caching**: Built-in Redis-based caching for process results
|
|
52
|
+
- **Celery Integration**: Asynchronous task processing using Celery
|
|
53
|
+
- **Pydantic Models**: Strong type validation for process inputs and outputs
|
|
54
|
+
- **Logging**: Uses `loguru` for modern logging with rotation support
|
|
55
|
+
|
|
56
|
+
### Architecture
|
|
57
|
+
|
|
58
|
+
```mermaid
|
|
59
|
+
graph TB
|
|
60
|
+
subgraph Client
|
|
61
|
+
CLI[Client Request]
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
subgraph FastAPI Application
|
|
65
|
+
API[OGCProcessesAPI]
|
|
66
|
+
Router[API Router]
|
|
67
|
+
PM[ProcessManager]
|
|
68
|
+
PR[ProcessRegistry]
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
subgraph Redis
|
|
72
|
+
RC[Redis Cache]
|
|
73
|
+
RR[Redis Registry]
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
subgraph Process
|
|
77
|
+
BP[BaseProcess]
|
|
78
|
+
SP[SimpleProcess]
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
subgraph Worker
|
|
82
|
+
CW[Celery Worker]
|
|
83
|
+
CT[CacheResultTask]
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
%% Client interactions
|
|
87
|
+
CLI -->|HTTP Request| API
|
|
88
|
+
API -->|Route Request| Router
|
|
89
|
+
Router -->|Execute Process| PM
|
|
90
|
+
|
|
91
|
+
%% Process Manager flow
|
|
92
|
+
PM -->|Get Process| PR
|
|
93
|
+
PM -->|Check Cache| RC
|
|
94
|
+
PM -->|Submit Task| CW
|
|
95
|
+
PM -->|Get Result| RC
|
|
96
|
+
|
|
97
|
+
%% Process Registry
|
|
98
|
+
PR -->|Store/Retrieve| RR
|
|
99
|
+
PR -.->|Registers| SP
|
|
100
|
+
SP -->|Inherits| BP
|
|
101
|
+
|
|
102
|
+
%% Worker flow
|
|
103
|
+
CW -->|Execute| SP
|
|
104
|
+
CW -->|Cache Result| CT
|
|
105
|
+
CT -->|Store| RC
|
|
106
|
+
|
|
107
|
+
%% Styling
|
|
108
|
+
classDef api fill:#f9f,stroke:#333,stroke-width:2px
|
|
109
|
+
classDef cache fill:#bbf,stroke:#333,stroke-width:2px
|
|
110
|
+
classDef process fill:#bfb,stroke:#333,stroke-width:2px
|
|
111
|
+
classDef worker fill:#fbb,stroke:#333,stroke-width:2px
|
|
112
|
+
|
|
113
|
+
class API,Router api
|
|
114
|
+
class RC,RR cache
|
|
115
|
+
class BP,SP process
|
|
116
|
+
class CW,CT worker
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### Usage
|
|
120
|
+
|
|
121
|
+
1. **Define a Process**: Create a new process by subclassing `BaseProcess` and using the `@register_process` decorator.
|
|
122
|
+
|
|
123
|
+
```python
|
|
124
|
+
from fastprocesses.core.base_process import BaseProcess
|
|
125
|
+
from fastprocesses.core.models import (
|
|
126
|
+
ProcessDescription,
|
|
127
|
+
ProcessInput,
|
|
128
|
+
ProcessJobControlOptions,
|
|
129
|
+
ProcessOutput,
|
|
130
|
+
ProcessOutputTransmission,
|
|
131
|
+
Schema,
|
|
132
|
+
)
|
|
133
|
+
from fastprocesses.processes.process_registry import register_process
|
|
134
|
+
|
|
135
|
+
@register_process("simple_process")
|
|
136
|
+
class SimpleProcess(BaseProcess):
|
|
137
|
+
# Define process description as a class variable
|
|
138
|
+
process_description = ProcessDescription(
|
|
139
|
+
id="simple_process",
|
|
140
|
+
title="Simple Process",
|
|
141
|
+
version="1.0.0",
|
|
142
|
+
description="A simple example process",
|
|
143
|
+
jobControlOptions=[
|
|
144
|
+
ProcessJobControlOptions.SYNC_EXECUTE,
|
|
145
|
+
ProcessJobControlOptions.ASYNC_EXECUTE
|
|
146
|
+
],
|
|
147
|
+
outputTransmission=[
|
|
148
|
+
ProcessOutputTransmission.VALUE
|
|
149
|
+
],
|
|
150
|
+
inputs={
|
|
151
|
+
"input_text": ProcessInput(
|
|
152
|
+
title="Input Text",
|
|
153
|
+
description="Text to process",
|
|
154
|
+
schema=Schema(
|
|
155
|
+
type="string",
|
|
156
|
+
minLength=1,
|
|
157
|
+
maxLength=1000
|
|
158
|
+
)
|
|
159
|
+
)
|
|
160
|
+
},
|
|
161
|
+
outputs={
|
|
162
|
+
"output_text": ProcessOutput(
|
|
163
|
+
title="Output Text",
|
|
164
|
+
description="Processed text",
|
|
165
|
+
schema=Schema(
|
|
166
|
+
type="string"
|
|
167
|
+
)
|
|
168
|
+
)
|
|
169
|
+
},
|
|
170
|
+
keywords=["text", "processing"],
|
|
171
|
+
metadata={
|
|
172
|
+
"created": "2024-02-19",
|
|
173
|
+
"provider": "Example Organization"
|
|
174
|
+
}
|
|
175
|
+
)
|
|
176
|
+
|
|
177
|
+
async def execute(self, inputs: Dict[str, Any]) -> Dict[str, Any]:
|
|
178
|
+
input_text = inputs["inputs"]["input_text"]
|
|
179
|
+
output_text = input_text.upper()
|
|
180
|
+
return {"output_text": output_text}
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
2. **Create the FastAPI Application**:
|
|
184
|
+
|
|
185
|
+
```python
|
|
186
|
+
import uvicorn
|
|
187
|
+
from fastprocesses.api.server import OGCProcessesAPI
|
|
188
|
+
|
|
189
|
+
app = OGCProcessesAPI(
|
|
190
|
+
title="Simple Process API",
|
|
191
|
+
version="1.0.0",
|
|
192
|
+
description="A simple API for running processes"
|
|
193
|
+
).get_app()
|
|
194
|
+
|
|
195
|
+
if __name__ == "__main__":
|
|
196
|
+
uvicorn.run(app, host="0.0.0.0", port=8000)
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
3. **Start the Services**:
|
|
200
|
+
|
|
201
|
+
Start Redis (required for caching and Celery):
|
|
202
|
+
```bash
|
|
203
|
+
docker run -d -p 6379:6379 redis
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
Start the Celery worker:
|
|
207
|
+
```bash
|
|
208
|
+
celery -A fastprocesses.worker.celery_app worker
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
Start the FastAPI application:
|
|
212
|
+
```bash
|
|
213
|
+
poetry run python examples/run_example.py
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
4. **Use the API**:
|
|
217
|
+
|
|
218
|
+
Execute a process (async):
|
|
219
|
+
```bash
|
|
220
|
+
curl -X POST "http://localhost:8000/processes/simple_process/execution" \
|
|
221
|
+
-H "Content-Type: application/json" \
|
|
222
|
+
-d '{
|
|
223
|
+
"inputs": {
|
|
224
|
+
"input_text": "hello world"
|
|
225
|
+
},
|
|
226
|
+
"mode": "async"
|
|
227
|
+
}'
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
Execute a process (sync):
|
|
231
|
+
```bash
|
|
232
|
+
curl -X POST "http://localhost:8000/processes/simple_process/execution" \
|
|
233
|
+
-H "Content-Type: application/json" \
|
|
234
|
+
-d '{
|
|
235
|
+
"inputs": {
|
|
236
|
+
"input_text": "hello world"
|
|
237
|
+
},
|
|
238
|
+
"mode": "sync"
|
|
239
|
+
}'
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
### API Endpoints
|
|
243
|
+
|
|
244
|
+
- `GET /`: Landing page
|
|
245
|
+
- `GET /conformance`: OGC API conformance declaration
|
|
246
|
+
- `GET /processes`: List available processes
|
|
247
|
+
- `GET /processes/{process_id}`: Get process description
|
|
248
|
+
- `POST /processes/{process_id}/execution`: Execute a process
|
|
249
|
+
- `GET /jobs`: List all jobs
|
|
250
|
+
- `GET /jobs/{job_id}`: Get job status
|
|
251
|
+
- `GET /jobs/{job_id}/results`: Get job results
|
|
252
|
+
|
|
253
|
+
### Configuration
|
|
254
|
+
|
|
255
|
+
The library can be configured using environment variables:
|
|
256
|
+
|
|
257
|
+
```bash
|
|
258
|
+
REDIS_CACHE_URL=redis://localhost:6379/0
|
|
259
|
+
CELERY_BROKER_URL=redis://localhost:6379/1
|
|
260
|
+
CELERY_RESULT_BACKEND=redis://localhost:6379/2
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
### Notes:
|
|
264
|
+
How to serialize pydantic models within celery? -> https://benninger.ca/posts/celery-serializer-pydantic/
|
|
265
|
+
|
|
266
|
+
!IMPORTANT!: Cache hash key is based on original unprocessed inputs always this ensures consistent caching and cache retrieval which does not depend on arbitrary processed data, which can change when the process is updated or changed!
|
|
267
|
+
|
|
268
|
+
### Version Notes
|
|
269
|
+
- **Version: 0.7.4**: added paging to processes and jobs, including limit and offset query params
|
|
270
|
+
- **0.5.0**: Extended Schema model
|
|
271
|
+
- **0.4.0**: Added full OGC API Processes 1.0.0 Core compliance
|
|
272
|
+
- **0.3.0**: Added job control and output transmission options
|
|
273
|
+
- **0.2.0**: Added Redis caching and Celery integration
|
|
274
|
+
- **0.1.0**: Initial release with basic process support
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
fastprocesses/__init__.py,sha256=OG7vLPTeVifB2d4TZn55ZGUwSnPvzGIjjgwXtOh69KA,181
|
|
2
|
+
fastprocesses/api/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
3
|
+
fastprocesses/api/manager.py,sha256=wDxWd8nwu4xvOf4tJzyqFP6wiFrK4JbC3CjIydoQsm0,13850
|
|
4
|
+
fastprocesses/api/router.py,sha256=uymoKUoqCRtvPhK-qI1VJJZIVdyJEMhc0T8zDtSa5ks,6265
|
|
5
|
+
fastprocesses/api/server.py,sha256=9egolkONiMYDGlRsAFCPB3Zf2ayCjeS-XVdLAll77w8,671
|
|
6
|
+
fastprocesses/celery_worker.py,sha256=2BF7pey9nVrRffEqZJD2jCqNMxP8qsCLQejFng537wc,1211
|
|
7
|
+
fastprocesses/common.py,sha256=sZn8B6RfsvG7xwgMnsq8_svyGBOrndHgG6pW9Ozfmq0,1777
|
|
8
|
+
fastprocesses/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
9
|
+
fastprocesses/core/base_process.py,sha256=sAj_RfG3q9Pv2c7hhKu66NH4oIMlwhHhA_Hu8FH0MJI,5099
|
|
10
|
+
fastprocesses/core/cache.py,sha256=hZzJcpCYqP94hlllv5cyYTIZS0-aXq5kxHrXBDasoRc,1932
|
|
11
|
+
fastprocesses/core/config.py,sha256=I9hIKbGXUWEkSgDSS9KuGAZ4pEu9fwTE3AczRmdNct4,569
|
|
12
|
+
fastprocesses/core/logging.py,sha256=GpCQn5bvq-hVxtYMzVCYoHvZF37hiI2q4Kpj7vys9Io,1816
|
|
13
|
+
fastprocesses/core/models.py,sha256=67SVAQvh-K-tjlt_t79PcPc7ZJ4YYUGzRnoliqcHi2M,4796
|
|
14
|
+
fastprocesses/processes/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
15
|
+
fastprocesses/processes/process_registry.py,sha256=ugsXD0Rj5-Snj--e1FeIzg9CVKhRFlllJVXupBcURr0,4267
|
|
16
|
+
fastprocesses/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
17
|
+
fastprocesses/worker/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
18
|
+
fastprocesses/worker/celery_app.py,sha256=KEuulMqUp29zgD_XB5fsD49eI4qcU96YfWVpqxQ8Z5c,5058
|
|
19
|
+
fastprocesses-0.7.4.dist-info/AUTHORS.md,sha256=F8zDIs87H_lW-w4iCvDHMfX84oMW6x4AGtK1Rd4hGBY,9
|
|
20
|
+
fastprocesses-0.7.4.dist-info/METADATA,sha256=cf7MfKSgPNWk-OlkspYE3Wiu0ShEjkAF42A-oHpch_s,8478
|
|
21
|
+
fastprocesses-0.7.4.dist-info/WHEEL,sha256=XbeZDeTWKc1w7CSIyre5aMDU_-PohRwTQceYnisIYYY,88
|
|
22
|
+
fastprocesses-0.7.4.dist-info/entry_points.txt,sha256=MeSG-KBsVp1wDIvyaatauFal78lgb-0VJUFRsPZ5pkw,72
|
|
23
|
+
fastprocesses-0.7.4.dist-info/RECORD,,
|