zipher-sdk 0.3.0__tar.gz → 0.3.9__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.egg-info → zipher-sdk-0.3.9}/PKG-INFO +67 -1
- {zipher-sdk-0.3.0 → zipher-sdk-0.3.9}/README.md +67 -0
- {zipher-sdk-0.3.0 → zipher-sdk-0.3.9}/setup.py +2 -2
- {zipher-sdk-0.3.0 → zipher-sdk-0.3.9}/tests/test_client.py +3 -0
- zipher-sdk-0.3.9/zipher/__init__.py +2 -0
- {zipher-sdk-0.3.0 → zipher-sdk-0.3.9}/zipher/acl/zipher_installer.py +1 -1
- {zipher-sdk-0.3.0 → zipher-sdk-0.3.9}/zipher/client.py +23 -7
- {zipher-sdk-0.3.0 → zipher-sdk-0.3.9}/zipher/models.py +7 -0
- {zipher-sdk-0.3.0 → zipher-sdk-0.3.9/zipher_sdk.egg-info}/PKG-INFO +67 -1
- {zipher-sdk-0.3.0 → zipher-sdk-0.3.9}/zipher_sdk.egg-info/requires.txt +1 -1
- zipher-sdk-0.3.0/zipher/__init__.py +0 -1
- {zipher-sdk-0.3.0 → zipher-sdk-0.3.9}/LICENSE +0 -0
- {zipher-sdk-0.3.0 → zipher-sdk-0.3.9}/setup.cfg +0 -0
- {zipher-sdk-0.3.0 → zipher-sdk-0.3.9}/tests/__init__.py +0 -0
- {zipher-sdk-0.3.0 → zipher-sdk-0.3.9}/tests/test_acl/__init__.py +0 -0
- {zipher-sdk-0.3.0 → zipher-sdk-0.3.9}/tests/test_acl/sample_job.py +0 -0
- {zipher-sdk-0.3.0 → zipher-sdk-0.3.9}/tests/test_acl/test_acl.py +0 -0
- {zipher-sdk-0.3.0 → zipher-sdk-0.3.9}/zipher/acl/__init__.py +0 -0
- {zipher-sdk-0.3.0 → zipher-sdk-0.3.9}/zipher/acl/models.py +0 -0
- {zipher-sdk-0.3.0 → zipher-sdk-0.3.9}/zipher/cli.py +0 -0
- {zipher-sdk-0.3.0 → zipher-sdk-0.3.9}/zipher/exceptions.py +0 -0
- {zipher-sdk-0.3.0 → zipher-sdk-0.3.9}/zipher/utils.py +0 -0
- {zipher-sdk-0.3.0 → zipher-sdk-0.3.9}/zipher_sdk.egg-info/SOURCES.txt +0 -0
- {zipher-sdk-0.3.0 → zipher-sdk-0.3.9}/zipher_sdk.egg-info/dependency_links.txt +0 -0
- {zipher-sdk-0.3.0 → zipher-sdk-0.3.9}/zipher_sdk.egg-info/entry_points.txt +0 -0
- {zipher-sdk-0.3.0 → zipher-sdk-0.3.9}/zipher_sdk.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: zipher-sdk
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.9
|
|
4
4
|
Summary: Python SDK for programmatic access to the Zipher API
|
|
5
5
|
Home-page: UNKNOWN
|
|
6
6
|
Author: Zipher Inc.
|
|
@@ -136,4 +136,70 @@ optimized_cluster = client.update_existing_conf(job_id="my-job-id", existing_con
|
|
|
136
136
|
|
|
137
137
|
```
|
|
138
138
|
|
|
139
|
+
### Update Existing Multiple Tasks Configuration
|
|
140
|
+
|
|
141
|
+
You can update multiple databricks tasks by initializing a zipher Client and sending a JSON representing a list of dbx SubmitTask objects to
|
|
142
|
+
the `get_optimized_tasks` function.
|
|
143
|
+
|
|
144
|
+
```python
|
|
145
|
+
from zipher import Client
|
|
146
|
+
|
|
147
|
+
client = Client(customer_id="my_customer_id") # assuming the zipher API key is stored in ZIPHER_API_KEY environment variable
|
|
148
|
+
|
|
149
|
+
tasks_to_optimize = [
|
|
150
|
+
{
|
|
151
|
+
"task_key": "task_1",
|
|
152
|
+
"description": "Test notebook task",
|
|
153
|
+
"notebook_task": {
|
|
154
|
+
"notebook_path": "/path/to/your/notebook",
|
|
155
|
+
"base_parameters": {
|
|
156
|
+
"param1": "value1"
|
|
157
|
+
}
|
|
158
|
+
},
|
|
159
|
+
"new_cluster": {
|
|
160
|
+
"spark_version": "14.3.x-scala2.12",
|
|
161
|
+
"node_type_id": "m6id.large",
|
|
162
|
+
"driver_node_type_id": "m6id.large",
|
|
163
|
+
"num_workers": 2,
|
|
164
|
+
"aws_attributes": {
|
|
165
|
+
"first_on_demand": 0,
|
|
166
|
+
"availability": "SPOT",
|
|
167
|
+
"zone_id": "auto",
|
|
168
|
+
"spot_bid_price_percent": 100,
|
|
169
|
+
"ebs_volume_count": 0
|
|
170
|
+
},
|
|
171
|
+
"spark_conf": {
|
|
172
|
+
"spark.driver.maxResultSize": "4g"
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
},
|
|
176
|
+
{
|
|
177
|
+
"task_key": "task_2",
|
|
178
|
+
"description": "Test Python task",
|
|
179
|
+
"spark_python_task": {
|
|
180
|
+
"python_file": "/path/to/your/python_file.py",
|
|
181
|
+
},
|
|
182
|
+
"new_cluster": {
|
|
183
|
+
"spark_version": "14.3.x-scala2.12",
|
|
184
|
+
"node_type_id": "m6id.large",
|
|
185
|
+
"driver_node_type_id": "m6id.large",
|
|
186
|
+
"num_workers": 2,
|
|
187
|
+
"spark_conf": {
|
|
188
|
+
"spark.driver.maxResultSize": "4g"
|
|
189
|
+
}
|
|
190
|
+
},
|
|
191
|
+
"timeout_seconds": 3600,
|
|
192
|
+
"depends_on": [
|
|
193
|
+
{
|
|
194
|
+
"task_key": "task_1"
|
|
195
|
+
}
|
|
196
|
+
]
|
|
197
|
+
}
|
|
198
|
+
]
|
|
199
|
+
|
|
200
|
+
# Update tasks
|
|
201
|
+
optimized_tasks = client.get_optimized_tasks(job_id="my-job-id", tasks=tasks_to_optimize)
|
|
202
|
+
|
|
203
|
+
# Continue with sending the optimized tasks to Databricks via the Databricks python SDK, Airflow operator, etc.
|
|
204
|
+
```
|
|
139
205
|
|
|
@@ -120,3 +120,70 @@ optimized_cluster = client.update_existing_conf(job_id="my-job-id", existing_con
|
|
|
120
120
|
# Continue with sending the optimized configuration to Databricks via the Databricks python SDK, Airflow operator, etc.
|
|
121
121
|
|
|
122
122
|
```
|
|
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)
|
|
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.3.
|
|
11
|
+
version='0.3.9',
|
|
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',
|
|
@@ -16,7 +16,7 @@ setup(
|
|
|
16
16
|
author_email='yoav@zipher.cloud',
|
|
17
17
|
packages=find_packages(),
|
|
18
18
|
install_requires=[
|
|
19
|
-
"pydantic
|
|
19
|
+
"pydantic>=2.7.3,<3.0.0",
|
|
20
20
|
"requests==2.32.3",
|
|
21
21
|
"databricks-sdk==0.52.0"
|
|
22
22
|
],
|
|
@@ -49,6 +49,9 @@ class TestClient(unittest.TestCase):
|
|
|
49
49
|
res = self.client.update_existing_conf(job_id="1234", existing_conf=config_to_update)
|
|
50
50
|
self.assertDictEqual(config_to_update, res)
|
|
51
51
|
|
|
52
|
+
def test_pydantic_version(self):
|
|
53
|
+
import pydantic
|
|
54
|
+
print(pydantic.__version__)
|
|
52
55
|
|
|
53
56
|
if __name__ == '__main__':
|
|
54
57
|
unittest.main()
|
|
@@ -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,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: zipher-sdk
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.9
|
|
4
4
|
Summary: Python SDK for programmatic access to the Zipher API
|
|
5
5
|
Home-page: UNKNOWN
|
|
6
6
|
Author: Zipher Inc.
|
|
@@ -136,4 +136,70 @@ optimized_cluster = client.update_existing_conf(job_id="my-job-id", existing_con
|
|
|
136
136
|
|
|
137
137
|
```
|
|
138
138
|
|
|
139
|
+
### Update Existing Multiple Tasks Configuration
|
|
140
|
+
|
|
141
|
+
You can update multiple databricks tasks by initializing a zipher Client and sending a JSON representing a list of dbx SubmitTask objects to
|
|
142
|
+
the `get_optimized_tasks` function.
|
|
143
|
+
|
|
144
|
+
```python
|
|
145
|
+
from zipher import Client
|
|
146
|
+
|
|
147
|
+
client = Client(customer_id="my_customer_id") # assuming the zipher API key is stored in ZIPHER_API_KEY environment variable
|
|
148
|
+
|
|
149
|
+
tasks_to_optimize = [
|
|
150
|
+
{
|
|
151
|
+
"task_key": "task_1",
|
|
152
|
+
"description": "Test notebook task",
|
|
153
|
+
"notebook_task": {
|
|
154
|
+
"notebook_path": "/path/to/your/notebook",
|
|
155
|
+
"base_parameters": {
|
|
156
|
+
"param1": "value1"
|
|
157
|
+
}
|
|
158
|
+
},
|
|
159
|
+
"new_cluster": {
|
|
160
|
+
"spark_version": "14.3.x-scala2.12",
|
|
161
|
+
"node_type_id": "m6id.large",
|
|
162
|
+
"driver_node_type_id": "m6id.large",
|
|
163
|
+
"num_workers": 2,
|
|
164
|
+
"aws_attributes": {
|
|
165
|
+
"first_on_demand": 0,
|
|
166
|
+
"availability": "SPOT",
|
|
167
|
+
"zone_id": "auto",
|
|
168
|
+
"spot_bid_price_percent": 100,
|
|
169
|
+
"ebs_volume_count": 0
|
|
170
|
+
},
|
|
171
|
+
"spark_conf": {
|
|
172
|
+
"spark.driver.maxResultSize": "4g"
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
},
|
|
176
|
+
{
|
|
177
|
+
"task_key": "task_2",
|
|
178
|
+
"description": "Test Python task",
|
|
179
|
+
"spark_python_task": {
|
|
180
|
+
"python_file": "/path/to/your/python_file.py",
|
|
181
|
+
},
|
|
182
|
+
"new_cluster": {
|
|
183
|
+
"spark_version": "14.3.x-scala2.12",
|
|
184
|
+
"node_type_id": "m6id.large",
|
|
185
|
+
"driver_node_type_id": "m6id.large",
|
|
186
|
+
"num_workers": 2,
|
|
187
|
+
"spark_conf": {
|
|
188
|
+
"spark.driver.maxResultSize": "4g"
|
|
189
|
+
}
|
|
190
|
+
},
|
|
191
|
+
"timeout_seconds": 3600,
|
|
192
|
+
"depends_on": [
|
|
193
|
+
{
|
|
194
|
+
"task_key": "task_1"
|
|
195
|
+
}
|
|
196
|
+
]
|
|
197
|
+
}
|
|
198
|
+
]
|
|
199
|
+
|
|
200
|
+
# Update tasks
|
|
201
|
+
optimized_tasks = client.get_optimized_tasks(job_id="my-job-id", tasks=tasks_to_optimize)
|
|
202
|
+
|
|
203
|
+
# Continue with sending the optimized tasks to Databricks via the Databricks python SDK, Airflow operator, etc.
|
|
204
|
+
```
|
|
139
205
|
|
|
@@ -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
|