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.
Files changed (26) hide show
  1. {zipher-sdk-0.3.0/zipher_sdk.egg-info → zipher-sdk-0.3.9}/PKG-INFO +67 -1
  2. {zipher-sdk-0.3.0 → zipher-sdk-0.3.9}/README.md +67 -0
  3. {zipher-sdk-0.3.0 → zipher-sdk-0.3.9}/setup.py +2 -2
  4. {zipher-sdk-0.3.0 → zipher-sdk-0.3.9}/tests/test_client.py +3 -0
  5. zipher-sdk-0.3.9/zipher/__init__.py +2 -0
  6. {zipher-sdk-0.3.0 → zipher-sdk-0.3.9}/zipher/acl/zipher_installer.py +1 -1
  7. {zipher-sdk-0.3.0 → zipher-sdk-0.3.9}/zipher/client.py +23 -7
  8. {zipher-sdk-0.3.0 → zipher-sdk-0.3.9}/zipher/models.py +7 -0
  9. {zipher-sdk-0.3.0 → zipher-sdk-0.3.9/zipher_sdk.egg-info}/PKG-INFO +67 -1
  10. {zipher-sdk-0.3.0 → zipher-sdk-0.3.9}/zipher_sdk.egg-info/requires.txt +1 -1
  11. zipher-sdk-0.3.0/zipher/__init__.py +0 -1
  12. {zipher-sdk-0.3.0 → zipher-sdk-0.3.9}/LICENSE +0 -0
  13. {zipher-sdk-0.3.0 → zipher-sdk-0.3.9}/setup.cfg +0 -0
  14. {zipher-sdk-0.3.0 → zipher-sdk-0.3.9}/tests/__init__.py +0 -0
  15. {zipher-sdk-0.3.0 → zipher-sdk-0.3.9}/tests/test_acl/__init__.py +0 -0
  16. {zipher-sdk-0.3.0 → zipher-sdk-0.3.9}/tests/test_acl/sample_job.py +0 -0
  17. {zipher-sdk-0.3.0 → zipher-sdk-0.3.9}/tests/test_acl/test_acl.py +0 -0
  18. {zipher-sdk-0.3.0 → zipher-sdk-0.3.9}/zipher/acl/__init__.py +0 -0
  19. {zipher-sdk-0.3.0 → zipher-sdk-0.3.9}/zipher/acl/models.py +0 -0
  20. {zipher-sdk-0.3.0 → zipher-sdk-0.3.9}/zipher/cli.py +0 -0
  21. {zipher-sdk-0.3.0 → zipher-sdk-0.3.9}/zipher/exceptions.py +0 -0
  22. {zipher-sdk-0.3.0 → zipher-sdk-0.3.9}/zipher/utils.py +0 -0
  23. {zipher-sdk-0.3.0 → zipher-sdk-0.3.9}/zipher_sdk.egg-info/SOURCES.txt +0 -0
  24. {zipher-sdk-0.3.0 → zipher-sdk-0.3.9}/zipher_sdk.egg-info/dependency_links.txt +0 -0
  25. {zipher-sdk-0.3.0 → zipher-sdk-0.3.9}/zipher_sdk.egg-info/entry_points.txt +0 -0
  26. {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.0
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.0',
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==2.11.3",
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()
@@ -0,0 +1,2 @@
1
+ from .client import Client
2
+ from .models import Config
@@ -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(limit=100)
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 get_optimized_config(self, job_id: str) -> Dict:
37
- params = ConfFetcherRequest(customer_id=self.customer_id, job_id=job_id)
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.0
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,3 +1,3 @@
1
- pydantic==2.11.3
1
+ pydantic<3.0.0,>=2.7.3
2
2
  requests==2.32.3
3
3
  databricks-sdk==0.52.0
@@ -1 +0,0 @@
1
- from .client import Client
File without changes
File without changes
File without changes
File without changes
File without changes