zipher-sdk 0.3.0__tar.gz → 0.4.1__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.
- {zipher-sdk-0.3.0 → zipher_sdk-0.4.1}/PKG-INFO +78 -5
- zipher-sdk-0.3.0/zipher_sdk.egg-info/PKG-INFO → zipher_sdk-0.4.1/README.md +65 -15
- {zipher-sdk-0.3.0 → zipher_sdk-0.4.1}/setup.py +1 -1
- zipher_sdk-0.4.1/zipher/__init__.py +2 -0
- {zipher-sdk-0.3.0 → zipher_sdk-0.4.1}/zipher/acl/zipher_installer.py +1 -1
- {zipher-sdk-0.3.0 → zipher_sdk-0.4.1}/zipher/client.py +23 -7
- {zipher-sdk-0.3.0 → zipher_sdk-0.4.1}/zipher/models.py +7 -0
- zipher-sdk-0.3.0/README.md → zipher_sdk-0.4.1/zipher_sdk.egg-info/PKG-INFO +90 -0
- {zipher-sdk-0.3.0 → zipher_sdk-0.4.1}/zipher_sdk.egg-info/entry_points.txt +0 -1
- zipher-sdk-0.3.0/zipher/__init__.py +0 -1
- {zipher-sdk-0.3.0 → zipher_sdk-0.4.1}/LICENSE +0 -0
- {zipher-sdk-0.3.0 → zipher_sdk-0.4.1}/setup.cfg +0 -0
- {zipher-sdk-0.3.0 → zipher_sdk-0.4.1}/tests/__init__.py +0 -0
- {zipher-sdk-0.3.0 → zipher_sdk-0.4.1}/tests/test_acl/__init__.py +0 -0
- {zipher-sdk-0.3.0 → zipher_sdk-0.4.1}/tests/test_acl/sample_job.py +0 -0
- {zipher-sdk-0.3.0 → zipher_sdk-0.4.1}/tests/test_acl/test_acl.py +0 -0
- {zipher-sdk-0.3.0 → zipher_sdk-0.4.1}/tests/test_client.py +0 -0
- {zipher-sdk-0.3.0 → zipher_sdk-0.4.1}/zipher/acl/__init__.py +0 -0
- {zipher-sdk-0.3.0 → zipher_sdk-0.4.1}/zipher/acl/models.py +0 -0
- {zipher-sdk-0.3.0 → zipher_sdk-0.4.1}/zipher/cli.py +0 -0
- {zipher-sdk-0.3.0 → zipher_sdk-0.4.1}/zipher/exceptions.py +0 -0
- {zipher-sdk-0.3.0 → zipher_sdk-0.4.1}/zipher/utils.py +0 -0
- {zipher-sdk-0.3.0 → zipher_sdk-0.4.1}/zipher_sdk.egg-info/SOURCES.txt +0 -0
- {zipher-sdk-0.3.0 → zipher_sdk-0.4.1}/zipher_sdk.egg-info/dependency_links.txt +0 -0
- {zipher-sdk-0.3.0 → zipher_sdk-0.4.1}/zipher_sdk.egg-info/requires.txt +0 -0
- {zipher-sdk-0.3.0 → zipher_sdk-0.4.1}/zipher_sdk.egg-info/top_level.txt +0 -0
|
@@ -1,17 +1,25 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: zipher-sdk
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.1
|
|
4
4
|
Summary: Python SDK for programmatic access to the Zipher API
|
|
5
|
-
Home-page: UNKNOWN
|
|
6
5
|
Author: Zipher Inc.
|
|
7
6
|
Author-email: yoav@zipher.cloud
|
|
8
|
-
License: UNKNOWN
|
|
9
|
-
Platform: UNKNOWN
|
|
10
7
|
Classifier: Programming Language :: Python :: 3
|
|
11
8
|
Classifier: License :: OSI Approved :: MIT License
|
|
12
9
|
Classifier: Operating System :: OS Independent
|
|
13
10
|
Description-Content-Type: text/markdown
|
|
14
11
|
License-File: LICENSE
|
|
12
|
+
Requires-Dist: pydantic==2.11.3
|
|
13
|
+
Requires-Dist: requests==2.32.3
|
|
14
|
+
Requires-Dist: databricks-sdk==0.52.0
|
|
15
|
+
Dynamic: author
|
|
16
|
+
Dynamic: author-email
|
|
17
|
+
Dynamic: classifier
|
|
18
|
+
Dynamic: description
|
|
19
|
+
Dynamic: description-content-type
|
|
20
|
+
Dynamic: license-file
|
|
21
|
+
Dynamic: requires-dist
|
|
22
|
+
Dynamic: summary
|
|
15
23
|
|
|
16
24
|
|
|
17
25
|
# Zipher SDK
|
|
@@ -136,4 +144,69 @@ optimized_cluster = client.update_existing_conf(job_id="my-job-id", existing_con
|
|
|
136
144
|
|
|
137
145
|
```
|
|
138
146
|
|
|
147
|
+
### Update Existing Multiple Tasks Configuration
|
|
139
148
|
|
|
149
|
+
You can update multiple databricks tasks by initializing a zipher Client and sending a JSON representing a list of dbx SubmitTask objects to
|
|
150
|
+
the `get_optimized_tasks` function.
|
|
151
|
+
|
|
152
|
+
```python
|
|
153
|
+
from zipher import Client
|
|
154
|
+
|
|
155
|
+
client = Client(customer_id="my_customer_id") # assuming the zipher API key is stored in ZIPHER_API_KEY environment variable
|
|
156
|
+
|
|
157
|
+
tasks_to_optimize = [
|
|
158
|
+
{
|
|
159
|
+
"task_key": "task_1",
|
|
160
|
+
"description": "Test notebook task",
|
|
161
|
+
"notebook_task": {
|
|
162
|
+
"notebook_path": "/path/to/your/notebook",
|
|
163
|
+
"base_parameters": {
|
|
164
|
+
"param1": "value1"
|
|
165
|
+
}
|
|
166
|
+
},
|
|
167
|
+
"new_cluster": {
|
|
168
|
+
"spark_version": "14.3.x-scala2.12",
|
|
169
|
+
"node_type_id": "m6id.large",
|
|
170
|
+
"driver_node_type_id": "m6id.large",
|
|
171
|
+
"num_workers": 2,
|
|
172
|
+
"aws_attributes": {
|
|
173
|
+
"first_on_demand": 0,
|
|
174
|
+
"availability": "SPOT",
|
|
175
|
+
"zone_id": "auto",
|
|
176
|
+
"spot_bid_price_percent": 100,
|
|
177
|
+
"ebs_volume_count": 0
|
|
178
|
+
},
|
|
179
|
+
"spark_conf": {
|
|
180
|
+
"spark.driver.maxResultSize": "4g"
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
},
|
|
184
|
+
{
|
|
185
|
+
"task_key": "task_2",
|
|
186
|
+
"description": "Test Python task",
|
|
187
|
+
"spark_python_task": {
|
|
188
|
+
"python_file": "/path/to/your/python_file.py",
|
|
189
|
+
},
|
|
190
|
+
"new_cluster": {
|
|
191
|
+
"spark_version": "14.3.x-scala2.12",
|
|
192
|
+
"node_type_id": "m6id.large",
|
|
193
|
+
"driver_node_type_id": "m6id.large",
|
|
194
|
+
"num_workers": 2,
|
|
195
|
+
"spark_conf": {
|
|
196
|
+
"spark.driver.maxResultSize": "4g"
|
|
197
|
+
}
|
|
198
|
+
},
|
|
199
|
+
"timeout_seconds": 3600,
|
|
200
|
+
"depends_on": [
|
|
201
|
+
{
|
|
202
|
+
"task_key": "task_1"
|
|
203
|
+
}
|
|
204
|
+
]
|
|
205
|
+
}
|
|
206
|
+
]
|
|
207
|
+
|
|
208
|
+
# Update tasks
|
|
209
|
+
optimized_tasks = client.get_optimized_tasks(job_id="my-job-id", tasks=tasks_to_optimize)
|
|
210
|
+
|
|
211
|
+
# Continue with sending the optimized tasks to Databricks via the Databricks python SDK, Airflow operator, etc.
|
|
212
|
+
```
|
|
@@ -1,18 +1,3 @@
|
|
|
1
|
-
Metadata-Version: 2.1
|
|
2
|
-
Name: zipher-sdk
|
|
3
|
-
Version: 0.3.0
|
|
4
|
-
Summary: Python SDK for programmatic access to the Zipher API
|
|
5
|
-
Home-page: UNKNOWN
|
|
6
|
-
Author: Zipher Inc.
|
|
7
|
-
Author-email: yoav@zipher.cloud
|
|
8
|
-
License: UNKNOWN
|
|
9
|
-
Platform: UNKNOWN
|
|
10
|
-
Classifier: Programming Language :: Python :: 3
|
|
11
|
-
Classifier: License :: OSI Approved :: MIT License
|
|
12
|
-
Classifier: Operating System :: OS Independent
|
|
13
|
-
Description-Content-Type: text/markdown
|
|
14
|
-
License-File: LICENSE
|
|
15
|
-
|
|
16
1
|
|
|
17
2
|
# Zipher SDK
|
|
18
3
|
|
|
@@ -136,4 +121,69 @@ optimized_cluster = client.update_existing_conf(job_id="my-job-id", existing_con
|
|
|
136
121
|
|
|
137
122
|
```
|
|
138
123
|
|
|
124
|
+
### Update Existing Multiple Tasks Configuration
|
|
125
|
+
|
|
126
|
+
You can update multiple databricks tasks by initializing a zipher Client and sending a JSON representing a list of dbx SubmitTask objects to
|
|
127
|
+
the `get_optimized_tasks` function.
|
|
128
|
+
|
|
129
|
+
```python
|
|
130
|
+
from zipher import Client
|
|
131
|
+
|
|
132
|
+
client = Client(customer_id="my_customer_id") # assuming the zipher API key is stored in ZIPHER_API_KEY environment variable
|
|
133
|
+
|
|
134
|
+
tasks_to_optimize = [
|
|
135
|
+
{
|
|
136
|
+
"task_key": "task_1",
|
|
137
|
+
"description": "Test notebook task",
|
|
138
|
+
"notebook_task": {
|
|
139
|
+
"notebook_path": "/path/to/your/notebook",
|
|
140
|
+
"base_parameters": {
|
|
141
|
+
"param1": "value1"
|
|
142
|
+
}
|
|
143
|
+
},
|
|
144
|
+
"new_cluster": {
|
|
145
|
+
"spark_version": "14.3.x-scala2.12",
|
|
146
|
+
"node_type_id": "m6id.large",
|
|
147
|
+
"driver_node_type_id": "m6id.large",
|
|
148
|
+
"num_workers": 2,
|
|
149
|
+
"aws_attributes": {
|
|
150
|
+
"first_on_demand": 0,
|
|
151
|
+
"availability": "SPOT",
|
|
152
|
+
"zone_id": "auto",
|
|
153
|
+
"spot_bid_price_percent": 100,
|
|
154
|
+
"ebs_volume_count": 0
|
|
155
|
+
},
|
|
156
|
+
"spark_conf": {
|
|
157
|
+
"spark.driver.maxResultSize": "4g"
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
"task_key": "task_2",
|
|
163
|
+
"description": "Test Python task",
|
|
164
|
+
"spark_python_task": {
|
|
165
|
+
"python_file": "/path/to/your/python_file.py",
|
|
166
|
+
},
|
|
167
|
+
"new_cluster": {
|
|
168
|
+
"spark_version": "14.3.x-scala2.12",
|
|
169
|
+
"node_type_id": "m6id.large",
|
|
170
|
+
"driver_node_type_id": "m6id.large",
|
|
171
|
+
"num_workers": 2,
|
|
172
|
+
"spark_conf": {
|
|
173
|
+
"spark.driver.maxResultSize": "4g"
|
|
174
|
+
}
|
|
175
|
+
},
|
|
176
|
+
"timeout_seconds": 3600,
|
|
177
|
+
"depends_on": [
|
|
178
|
+
{
|
|
179
|
+
"task_key": "task_1"
|
|
180
|
+
}
|
|
181
|
+
]
|
|
182
|
+
}
|
|
183
|
+
]
|
|
184
|
+
|
|
185
|
+
# Update tasks
|
|
186
|
+
optimized_tasks = client.get_optimized_tasks(job_id="my-job-id", tasks=tasks_to_optimize)
|
|
139
187
|
|
|
188
|
+
# Continue with sending the optimized tasks to Databricks via the Databricks python SDK, Airflow operator, etc.
|
|
189
|
+
```
|
|
@@ -8,7 +8,7 @@ with open('README.md', encoding='utf-8') as f:
|
|
|
8
8
|
|
|
9
9
|
setup(
|
|
10
10
|
name='zipher-sdk',
|
|
11
|
-
version='0.
|
|
11
|
+
version='0.4.1',
|
|
12
12
|
description='Python SDK for programmatic access to the Zipher API',
|
|
13
13
|
long_description=long_description,
|
|
14
14
|
long_description_content_type='text/markdown',
|
|
@@ -122,7 +122,7 @@ class ZipherInstaller:
|
|
|
122
122
|
start_date = datetime.now() - timedelta(days=days_back)
|
|
123
123
|
start_date_ms_int = int(start_date.timestamp() * 1000)
|
|
124
124
|
|
|
125
|
-
jobs = self.dbx_client.jobs.list(
|
|
125
|
+
jobs = self.dbx_client.jobs.list()
|
|
126
126
|
runs = self.dbx_client.jobs.list_runs(limit=0, start_time_from=start_date_ms_int)
|
|
127
127
|
|
|
128
128
|
all_job_ids = set()
|
|
@@ -4,11 +4,9 @@ from typing import Dict, Optional
|
|
|
4
4
|
|
|
5
5
|
import requests
|
|
6
6
|
from databricks.sdk.service.compute import ClusterSpec
|
|
7
|
-
|
|
8
|
-
from zipher.models import ConfFetcherRequest, Config
|
|
7
|
+
from zipher.models import ConfFetcherRequest, GetOptimizedTasksRequest, Config
|
|
9
8
|
from zipher.exceptions import MissingAPIKeyError
|
|
10
9
|
|
|
11
|
-
|
|
12
10
|
class Client:
|
|
13
11
|
def __init__(self, customer_id: str, zipher_api_key: str = '', config: Optional[Config] = None):
|
|
14
12
|
self.config = config or Config()
|
|
@@ -33,17 +31,35 @@ class Client:
|
|
|
33
31
|
else:
|
|
34
32
|
response.raise_for_status()
|
|
35
33
|
|
|
36
|
-
def
|
|
37
|
-
|
|
34
|
+
def _call_get_optimized_tasks_api(self, params: GetOptimizedTasksRequest):
|
|
35
|
+
headers = {
|
|
36
|
+
'x-api-key': self.zipher_api_key
|
|
37
|
+
}
|
|
38
|
+
response = requests.get(
|
|
39
|
+
url=self.config.zipher_get_optimized_tasks_api_endpoint,
|
|
40
|
+
headers=headers,
|
|
41
|
+
params=params.model_dump()
|
|
42
|
+
)
|
|
43
|
+
if response.ok:
|
|
44
|
+
return response.json()
|
|
45
|
+
else:
|
|
46
|
+
response.raise_for_status()
|
|
47
|
+
|
|
48
|
+
def get_optimized_tasks(self, job_id: str, tasks: list[dict]) -> list[dict]:
|
|
49
|
+
params = GetOptimizedTasksRequest(customer_id=self.customer_id, job_id=job_id, tasks=json.dumps(tasks))
|
|
50
|
+
return self._call_get_optimized_tasks_api(params)
|
|
51
|
+
|
|
52
|
+
def get_optimized_config(self, job_id: str, task_key: Optional[str] = None) -> Dict:
|
|
53
|
+
params = ConfFetcherRequest(customer_id=self.customer_id, job_id=job_id, task_key=task_key)
|
|
38
54
|
return self._call_conf_fetcher_api(params)
|
|
39
55
|
|
|
40
56
|
def get_optimized_config_as_dbx_cluster_spec(self, job_id: str) -> ClusterSpec:
|
|
41
57
|
return ClusterSpec.from_dict(self.get_optimized_config(job_id))
|
|
42
58
|
|
|
43
|
-
def update_existing_conf(self, job_id: str, existing_conf: Dict) -> Dict:
|
|
59
|
+
def update_existing_conf(self, job_id: str, existing_conf: Dict, task_key: Optional[str] = None) -> Dict:
|
|
44
60
|
if 'new_cluster' in existing_conf:
|
|
45
61
|
existing_conf = existing_conf['new_cluster']
|
|
46
|
-
params = ConfFetcherRequest(customer_id=self.customer_id, job_id=job_id, merge_with=json.dumps(existing_conf))
|
|
62
|
+
params = ConfFetcherRequest(customer_id=self.customer_id, job_id=job_id, merge_with=json.dumps(existing_conf), task_key=task_key)
|
|
47
63
|
try:
|
|
48
64
|
return self._call_conf_fetcher_api(params)
|
|
49
65
|
except:
|
|
@@ -12,6 +12,7 @@ class WorkspaceClientAuthType(Enum):
|
|
|
12
12
|
class ConfFetcherRequest(BaseModel):
|
|
13
13
|
job_id: str
|
|
14
14
|
customer_id: str
|
|
15
|
+
task_key: Optional[str] = None
|
|
15
16
|
merge_with: Optional[str] = None
|
|
16
17
|
|
|
17
18
|
|
|
@@ -24,3 +25,9 @@ class Config(BaseModel, extra='forbid', use_enum_values=True):
|
|
|
24
25
|
databricks_client_secret_env_var: str = 'DATABRICKS_CLIENT_SECRET'
|
|
25
26
|
|
|
26
27
|
zipher_config_fetcher_api_endpoint: str = 'https://api.zipher.cloud/default/get_clusterspec'
|
|
28
|
+
zipher_get_optimized_tasks_api_endpoint: str = 'https://api.zipher.cloud/default/get_optimized_tasks'
|
|
29
|
+
|
|
30
|
+
class GetOptimizedTasksRequest(BaseModel):
|
|
31
|
+
customer_id: str
|
|
32
|
+
job_id: str
|
|
33
|
+
tasks: Optional[str] = None
|
|
@@ -1,3 +1,26 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: zipher-sdk
|
|
3
|
+
Version: 0.4.1
|
|
4
|
+
Summary: Python SDK for programmatic access to the Zipher API
|
|
5
|
+
Author: Zipher Inc.
|
|
6
|
+
Author-email: yoav@zipher.cloud
|
|
7
|
+
Classifier: Programming Language :: Python :: 3
|
|
8
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
9
|
+
Classifier: Operating System :: OS Independent
|
|
10
|
+
Description-Content-Type: text/markdown
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Requires-Dist: pydantic==2.11.3
|
|
13
|
+
Requires-Dist: requests==2.32.3
|
|
14
|
+
Requires-Dist: databricks-sdk==0.52.0
|
|
15
|
+
Dynamic: author
|
|
16
|
+
Dynamic: author-email
|
|
17
|
+
Dynamic: classifier
|
|
18
|
+
Dynamic: description
|
|
19
|
+
Dynamic: description-content-type
|
|
20
|
+
Dynamic: license-file
|
|
21
|
+
Dynamic: requires-dist
|
|
22
|
+
Dynamic: summary
|
|
23
|
+
|
|
1
24
|
|
|
2
25
|
# Zipher SDK
|
|
3
26
|
|
|
@@ -120,3 +143,70 @@ optimized_cluster = client.update_existing_conf(job_id="my-job-id", existing_con
|
|
|
120
143
|
# Continue with sending the optimized configuration to Databricks via the Databricks python SDK, Airflow operator, etc.
|
|
121
144
|
|
|
122
145
|
```
|
|
146
|
+
|
|
147
|
+
### Update Existing Multiple Tasks Configuration
|
|
148
|
+
|
|
149
|
+
You can update multiple databricks tasks by initializing a zipher Client and sending a JSON representing a list of dbx SubmitTask objects to
|
|
150
|
+
the `get_optimized_tasks` function.
|
|
151
|
+
|
|
152
|
+
```python
|
|
153
|
+
from zipher import Client
|
|
154
|
+
|
|
155
|
+
client = Client(customer_id="my_customer_id") # assuming the zipher API key is stored in ZIPHER_API_KEY environment variable
|
|
156
|
+
|
|
157
|
+
tasks_to_optimize = [
|
|
158
|
+
{
|
|
159
|
+
"task_key": "task_1",
|
|
160
|
+
"description": "Test notebook task",
|
|
161
|
+
"notebook_task": {
|
|
162
|
+
"notebook_path": "/path/to/your/notebook",
|
|
163
|
+
"base_parameters": {
|
|
164
|
+
"param1": "value1"
|
|
165
|
+
}
|
|
166
|
+
},
|
|
167
|
+
"new_cluster": {
|
|
168
|
+
"spark_version": "14.3.x-scala2.12",
|
|
169
|
+
"node_type_id": "m6id.large",
|
|
170
|
+
"driver_node_type_id": "m6id.large",
|
|
171
|
+
"num_workers": 2,
|
|
172
|
+
"aws_attributes": {
|
|
173
|
+
"first_on_demand": 0,
|
|
174
|
+
"availability": "SPOT",
|
|
175
|
+
"zone_id": "auto",
|
|
176
|
+
"spot_bid_price_percent": 100,
|
|
177
|
+
"ebs_volume_count": 0
|
|
178
|
+
},
|
|
179
|
+
"spark_conf": {
|
|
180
|
+
"spark.driver.maxResultSize": "4g"
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
},
|
|
184
|
+
{
|
|
185
|
+
"task_key": "task_2",
|
|
186
|
+
"description": "Test Python task",
|
|
187
|
+
"spark_python_task": {
|
|
188
|
+
"python_file": "/path/to/your/python_file.py",
|
|
189
|
+
},
|
|
190
|
+
"new_cluster": {
|
|
191
|
+
"spark_version": "14.3.x-scala2.12",
|
|
192
|
+
"node_type_id": "m6id.large",
|
|
193
|
+
"driver_node_type_id": "m6id.large",
|
|
194
|
+
"num_workers": 2,
|
|
195
|
+
"spark_conf": {
|
|
196
|
+
"spark.driver.maxResultSize": "4g"
|
|
197
|
+
}
|
|
198
|
+
},
|
|
199
|
+
"timeout_seconds": 3600,
|
|
200
|
+
"depends_on": [
|
|
201
|
+
{
|
|
202
|
+
"task_key": "task_1"
|
|
203
|
+
}
|
|
204
|
+
]
|
|
205
|
+
}
|
|
206
|
+
]
|
|
207
|
+
|
|
208
|
+
# Update tasks
|
|
209
|
+
optimized_tasks = client.get_optimized_tasks(job_id="my-job-id", tasks=tasks_to_optimize)
|
|
210
|
+
|
|
211
|
+
# Continue with sending the optimized tasks to Databricks via the Databricks python SDK, Airflow operator, etc.
|
|
212
|
+
```
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
from .client import Client
|
|
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
|