oomol-cloud-task-sdk 0.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.
- oomol_cloud_task_sdk-0.1.0/PKG-INFO +46 -0
- oomol_cloud_task_sdk-0.1.0/README.md +37 -0
- oomol_cloud_task_sdk-0.1.0/pyproject.toml +14 -0
- oomol_cloud_task_sdk-0.1.0/setup.cfg +4 -0
- oomol_cloud_task_sdk-0.1.0/src/oomol_cloud_task/__init__.py +12 -0
- oomol_cloud_task_sdk-0.1.0/src/oomol_cloud_task/client.py +154 -0
- oomol_cloud_task_sdk-0.1.0/src/oomol_cloud_task/errors.py +17 -0
- oomol_cloud_task_sdk-0.1.0/src/oomol_cloud_task/types.py +16 -0
- oomol_cloud_task_sdk-0.1.0/src/oomol_cloud_task_sdk.egg-info/PKG-INFO +46 -0
- oomol_cloud_task_sdk-0.1.0/src/oomol_cloud_task_sdk.egg-info/SOURCES.txt +11 -0
- oomol_cloud_task_sdk-0.1.0/src/oomol_cloud_task_sdk.egg-info/dependency_links.txt +1 -0
- oomol_cloud_task_sdk-0.1.0/src/oomol_cloud_task_sdk.egg-info/requires.txt +1 -0
- oomol_cloud_task_sdk-0.1.0/src/oomol_cloud_task_sdk.egg-info/top_level.txt +1 -0
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: oomol-cloud-task-sdk
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Python SDK for Oomol Cloud Task API
|
|
5
|
+
License-Expression: MIT
|
|
6
|
+
Requires-Python: >=3.7
|
|
7
|
+
Description-Content-Type: text/markdown
|
|
8
|
+
Requires-Dist: requests>=2.25.0
|
|
9
|
+
|
|
10
|
+
# Oomol Cloud Task SDK (Python)
|
|
11
|
+
|
|
12
|
+
A lightweight, developer-friendly Python SDK for `https://cloud-task.oomol.com/v1`.
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
pip install oomol-cloud-task-sdk
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
(Note: You need to build the package locally first or publish it to PyPI)
|
|
21
|
+
|
|
22
|
+
## Usage
|
|
23
|
+
|
|
24
|
+
```python
|
|
25
|
+
from oomol_cloud_task import OomolTaskClient, BackoffStrategy
|
|
26
|
+
|
|
27
|
+
client = OomolTaskClient(api_key="YOUR_API_KEY")
|
|
28
|
+
|
|
29
|
+
task_id, result = client.create_and_wait(
|
|
30
|
+
applet_id="54dfbca0-6b2a-4738-bc38-c602981d9be6",
|
|
31
|
+
input_values={
|
|
32
|
+
"input_pdf": "...",
|
|
33
|
+
"output_path": "..."
|
|
34
|
+
},
|
|
35
|
+
interval_ms=2000,
|
|
36
|
+
backoff_strategy=BackoffStrategy.EXPONENTIAL
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
print(result)
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Features
|
|
43
|
+
|
|
44
|
+
- **Automatic Polling**: `create_and_wait` handles creation and polling in one step.
|
|
45
|
+
- **Backoff Strategies**: Supports `Fixed` and `Exponential` backoff to reduce server load.
|
|
46
|
+
- **Type Hints**: Fully typed for better IDE support.
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# Oomol Cloud Task SDK (Python)
|
|
2
|
+
|
|
3
|
+
A lightweight, developer-friendly Python SDK for `https://cloud-task.oomol.com/v1`.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pip install oomol-cloud-task-sdk
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
(Note: You need to build the package locally first or publish it to PyPI)
|
|
12
|
+
|
|
13
|
+
## Usage
|
|
14
|
+
|
|
15
|
+
```python
|
|
16
|
+
from oomol_cloud_task import OomolTaskClient, BackoffStrategy
|
|
17
|
+
|
|
18
|
+
client = OomolTaskClient(api_key="YOUR_API_KEY")
|
|
19
|
+
|
|
20
|
+
task_id, result = client.create_and_wait(
|
|
21
|
+
applet_id="54dfbca0-6b2a-4738-bc38-c602981d9be6",
|
|
22
|
+
input_values={
|
|
23
|
+
"input_pdf": "...",
|
|
24
|
+
"output_path": "..."
|
|
25
|
+
},
|
|
26
|
+
interval_ms=2000,
|
|
27
|
+
backoff_strategy=BackoffStrategy.EXPONENTIAL
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
print(result)
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Features
|
|
34
|
+
|
|
35
|
+
- **Automatic Polling**: `create_and_wait` handles creation and polling in one step.
|
|
36
|
+
- **Backoff Strategies**: Supports `Fixed` and `Exponential` backoff to reduce server load.
|
|
37
|
+
- **Type Hints**: Fully typed for better IDE support.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=61.0"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "oomol-cloud-task-sdk"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Python SDK for Oomol Cloud Task API"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.7"
|
|
11
|
+
license = "MIT"
|
|
12
|
+
dependencies = [
|
|
13
|
+
"requests>=2.25.0",
|
|
14
|
+
]
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
from .client import OomolTaskClient
|
|
2
|
+
from .errors import ApiError, TaskFailedError, TimeoutError
|
|
3
|
+
from .types import BackoffStrategy, TaskStatus
|
|
4
|
+
|
|
5
|
+
__all__ = [
|
|
6
|
+
"OomolTaskClient",
|
|
7
|
+
"ApiError",
|
|
8
|
+
"TaskFailedError",
|
|
9
|
+
"TimeoutError",
|
|
10
|
+
"BackoffStrategy",
|
|
11
|
+
"TaskStatus",
|
|
12
|
+
]
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import time
|
|
2
|
+
import requests
|
|
3
|
+
from typing import Optional, Callable, Dict, Any, Tuple
|
|
4
|
+
from .errors import ApiError, TaskFailedError, TimeoutError
|
|
5
|
+
from .types import BackoffStrategy, TaskStatus, InputValues, Metadata
|
|
6
|
+
|
|
7
|
+
DEFAULT_BASE_URL = "https://cloud-task.oomol.com/v1"
|
|
8
|
+
|
|
9
|
+
class OomolTaskClient:
|
|
10
|
+
def __init__(
|
|
11
|
+
self,
|
|
12
|
+
api_key: str,
|
|
13
|
+
base_url: str = DEFAULT_BASE_URL,
|
|
14
|
+
default_headers: Optional[Dict[str, str]] = None
|
|
15
|
+
):
|
|
16
|
+
self.api_key = api_key
|
|
17
|
+
self.base_url = base_url.rstrip("/")
|
|
18
|
+
self.default_headers = default_headers or {}
|
|
19
|
+
self.session = requests.Session()
|
|
20
|
+
|
|
21
|
+
def create_task(
|
|
22
|
+
self,
|
|
23
|
+
applet_id: str,
|
|
24
|
+
input_values: InputValues,
|
|
25
|
+
webhook_url: Optional[str] = None,
|
|
26
|
+
metadata: Optional[Metadata] = None
|
|
27
|
+
) -> str:
|
|
28
|
+
"""
|
|
29
|
+
Creates a task and returns the task ID.
|
|
30
|
+
"""
|
|
31
|
+
url = f"{self.base_url}/task/applet"
|
|
32
|
+
|
|
33
|
+
body = {
|
|
34
|
+
"appletID": applet_id,
|
|
35
|
+
"inputValues": input_values
|
|
36
|
+
}
|
|
37
|
+
if webhook_url:
|
|
38
|
+
body["webhookUrl"] = webhook_url
|
|
39
|
+
if metadata:
|
|
40
|
+
body["metadata"] = metadata
|
|
41
|
+
|
|
42
|
+
headers = self._get_headers()
|
|
43
|
+
|
|
44
|
+
response = self.session.post(url, json=body, headers=headers)
|
|
45
|
+
|
|
46
|
+
if not response.ok:
|
|
47
|
+
self._handle_error(response)
|
|
48
|
+
|
|
49
|
+
data = response.json()
|
|
50
|
+
return data["taskID"]
|
|
51
|
+
|
|
52
|
+
def get_task_result(self, task_id: str) -> Dict[str, Any]:
|
|
53
|
+
"""
|
|
54
|
+
Fetches the result of a task.
|
|
55
|
+
"""
|
|
56
|
+
url = f"{self.base_url}/task/{task_id}/result"
|
|
57
|
+
headers = self._get_headers()
|
|
58
|
+
|
|
59
|
+
response = self.session.get(url, headers=headers)
|
|
60
|
+
|
|
61
|
+
if not response.ok:
|
|
62
|
+
self._handle_error(response)
|
|
63
|
+
|
|
64
|
+
return response.json()
|
|
65
|
+
|
|
66
|
+
def await_result(
|
|
67
|
+
self,
|
|
68
|
+
task_id: str,
|
|
69
|
+
interval_ms: int = 2000,
|
|
70
|
+
timeout_ms: Optional[int] = None,
|
|
71
|
+
backoff_strategy: BackoffStrategy = BackoffStrategy.FIXED,
|
|
72
|
+
max_interval_ms: int = 15000,
|
|
73
|
+
on_progress: Optional[Callable[[Optional[float], str], None]] = None
|
|
74
|
+
) -> Dict[str, Any]:
|
|
75
|
+
"""
|
|
76
|
+
Polls for the task result until completion or timeout.
|
|
77
|
+
"""
|
|
78
|
+
start_time = time.time()
|
|
79
|
+
attempt = 0
|
|
80
|
+
current_interval = interval_ms / 1000.0
|
|
81
|
+
max_interval = max_interval_ms / 1000.0
|
|
82
|
+
|
|
83
|
+
while True:
|
|
84
|
+
# Check timeout
|
|
85
|
+
if timeout_ms is not None:
|
|
86
|
+
elapsed = (time.time() - start_time) * 1000
|
|
87
|
+
if elapsed > timeout_ms:
|
|
88
|
+
raise TimeoutError()
|
|
89
|
+
|
|
90
|
+
result = self.get_task_result(task_id)
|
|
91
|
+
status = result.get("status")
|
|
92
|
+
progress = result.get("progress")
|
|
93
|
+
|
|
94
|
+
if status == TaskStatus.SUCCESS.value:
|
|
95
|
+
return result
|
|
96
|
+
|
|
97
|
+
if status == TaskStatus.FAILED.value:
|
|
98
|
+
raise TaskFailedError(task_id, result.get("error") or result)
|
|
99
|
+
|
|
100
|
+
if on_progress:
|
|
101
|
+
on_progress(progress, status)
|
|
102
|
+
|
|
103
|
+
attempt += 1
|
|
104
|
+
|
|
105
|
+
# Backoff logic
|
|
106
|
+
if backoff_strategy == BackoffStrategy.EXPONENTIAL:
|
|
107
|
+
# 1.5x multiplier
|
|
108
|
+
next_interval = min(max_interval, (interval_ms / 1000.0) * (1.5 ** attempt))
|
|
109
|
+
else:
|
|
110
|
+
next_interval = current_interval
|
|
111
|
+
|
|
112
|
+
time.sleep(next_interval)
|
|
113
|
+
|
|
114
|
+
def create_and_wait(
|
|
115
|
+
self,
|
|
116
|
+
applet_id: str,
|
|
117
|
+
input_values: InputValues,
|
|
118
|
+
webhook_url: Optional[str] = None,
|
|
119
|
+
metadata: Optional[Metadata] = None,
|
|
120
|
+
interval_ms: int = 2000,
|
|
121
|
+
timeout_ms: Optional[int] = None,
|
|
122
|
+
backoff_strategy: BackoffStrategy = BackoffStrategy.FIXED,
|
|
123
|
+
max_interval_ms: int = 15000,
|
|
124
|
+
on_progress: Optional[Callable[[Optional[float], str], None]] = None
|
|
125
|
+
) -> Tuple[str, Dict[str, Any]]:
|
|
126
|
+
"""
|
|
127
|
+
Creates a task and waits for its completion.
|
|
128
|
+
Returns (task_id, result).
|
|
129
|
+
"""
|
|
130
|
+
task_id = self.create_task(applet_id, input_values, webhook_url, metadata)
|
|
131
|
+
result = self.await_result(
|
|
132
|
+
task_id=task_id,
|
|
133
|
+
interval_ms=interval_ms,
|
|
134
|
+
timeout_ms=timeout_ms,
|
|
135
|
+
backoff_strategy=backoff_strategy,
|
|
136
|
+
max_interval_ms=max_interval_ms,
|
|
137
|
+
on_progress=on_progress
|
|
138
|
+
)
|
|
139
|
+
return task_id, result
|
|
140
|
+
|
|
141
|
+
def _get_headers(self) -> Dict[str, str]:
|
|
142
|
+
headers = {
|
|
143
|
+
"Content-Type": "application/json",
|
|
144
|
+
"Authorization": f"Bearer {self.api_key}",
|
|
145
|
+
}
|
|
146
|
+
headers.update(self.default_headers)
|
|
147
|
+
return headers
|
|
148
|
+
|
|
149
|
+
def _handle_error(self, response: requests.Response):
|
|
150
|
+
try:
|
|
151
|
+
body = response.json()
|
|
152
|
+
except ValueError:
|
|
153
|
+
body = response.text
|
|
154
|
+
raise ApiError(f"Request failed: {response.status_code}", response.status_code, body)
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
class ApiError(Exception):
|
|
2
|
+
def __init__(self, message: str, status: int, body: any = None):
|
|
3
|
+
super().__init__(message)
|
|
4
|
+
self.status = status
|
|
5
|
+
self.body = body
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class TaskFailedError(Exception):
|
|
9
|
+
def __init__(self, task_id: str, detail: any = None):
|
|
10
|
+
super().__init__(f"Task execution failed: {task_id}")
|
|
11
|
+
self.task_id = task_id
|
|
12
|
+
self.detail = detail
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class TimeoutError(Exception):
|
|
16
|
+
def __init__(self, message: str = "Operation timed out"):
|
|
17
|
+
super().__init__(message)
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
from enum import Enum
|
|
2
|
+
from typing import Dict, Optional, Any, Union
|
|
3
|
+
|
|
4
|
+
class BackoffStrategy(Enum):
|
|
5
|
+
FIXED = "fixed"
|
|
6
|
+
EXPONENTIAL = "exp"
|
|
7
|
+
|
|
8
|
+
class TaskStatus(str, Enum):
|
|
9
|
+
PENDING = "pending"
|
|
10
|
+
RUNNING = "running"
|
|
11
|
+
SUCCESS = "success"
|
|
12
|
+
FAILED = "failed"
|
|
13
|
+
|
|
14
|
+
# Type aliases for better readability
|
|
15
|
+
InputValues = Dict[str, Any]
|
|
16
|
+
Metadata = Dict[str, Any]
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: oomol-cloud-task-sdk
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Python SDK for Oomol Cloud Task API
|
|
5
|
+
License-Expression: MIT
|
|
6
|
+
Requires-Python: >=3.7
|
|
7
|
+
Description-Content-Type: text/markdown
|
|
8
|
+
Requires-Dist: requests>=2.25.0
|
|
9
|
+
|
|
10
|
+
# Oomol Cloud Task SDK (Python)
|
|
11
|
+
|
|
12
|
+
A lightweight, developer-friendly Python SDK for `https://cloud-task.oomol.com/v1`.
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
pip install oomol-cloud-task-sdk
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
(Note: You need to build the package locally first or publish it to PyPI)
|
|
21
|
+
|
|
22
|
+
## Usage
|
|
23
|
+
|
|
24
|
+
```python
|
|
25
|
+
from oomol_cloud_task import OomolTaskClient, BackoffStrategy
|
|
26
|
+
|
|
27
|
+
client = OomolTaskClient(api_key="YOUR_API_KEY")
|
|
28
|
+
|
|
29
|
+
task_id, result = client.create_and_wait(
|
|
30
|
+
applet_id="54dfbca0-6b2a-4738-bc38-c602981d9be6",
|
|
31
|
+
input_values={
|
|
32
|
+
"input_pdf": "...",
|
|
33
|
+
"output_path": "..."
|
|
34
|
+
},
|
|
35
|
+
interval_ms=2000,
|
|
36
|
+
backoff_strategy=BackoffStrategy.EXPONENTIAL
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
print(result)
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Features
|
|
43
|
+
|
|
44
|
+
- **Automatic Polling**: `create_and_wait` handles creation and polling in one step.
|
|
45
|
+
- **Backoff Strategies**: Supports `Fixed` and `Exponential` backoff to reduce server load.
|
|
46
|
+
- **Type Hints**: Fully typed for better IDE support.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
README.md
|
|
2
|
+
pyproject.toml
|
|
3
|
+
src/oomol_cloud_task/__init__.py
|
|
4
|
+
src/oomol_cloud_task/client.py
|
|
5
|
+
src/oomol_cloud_task/errors.py
|
|
6
|
+
src/oomol_cloud_task/types.py
|
|
7
|
+
src/oomol_cloud_task_sdk.egg-info/PKG-INFO
|
|
8
|
+
src/oomol_cloud_task_sdk.egg-info/SOURCES.txt
|
|
9
|
+
src/oomol_cloud_task_sdk.egg-info/dependency_links.txt
|
|
10
|
+
src/oomol_cloud_task_sdk.egg-info/requires.txt
|
|
11
|
+
src/oomol_cloud_task_sdk.egg-info/top_level.txt
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
requests>=2.25.0
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
oomol_cloud_task
|