datacrunch 1.10.0__py3-none-any.whl → 1.11.0__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.
@@ -6,16 +6,19 @@ from typing import Optional, Dict, Any, Union, Generator
6
6
  from urllib.parse import urlparse
7
7
  from enum import Enum
8
8
 
9
+
9
10
  class InferenceClientError(Exception):
10
11
  """Base exception for InferenceClient errors."""
11
12
  pass
12
13
 
14
+
13
15
  class AsyncStatus(int, Enum):
14
16
  Initialized = 0
15
17
  Queue = 1
16
18
  Inference = 2
17
19
  Completed = 3
18
20
 
21
+
19
22
  @dataclass_json(undefined=Undefined.EXCLUDE)
20
23
  @dataclass
21
24
  class InferenceResponse:
@@ -222,6 +225,22 @@ class InferenceClient:
222
225
  raise InferenceClientError(f"Request to {path} failed: {str(e)}")
223
226
 
224
227
  def run_sync(self, data: Dict[str, Any], path: str = "", timeout_seconds: int = 60 * 5, headers: Optional[Dict[str, str]] = None, http_method: str = "POST", stream: bool = False):
228
+ """Make a synchronous request to the inference endpoint.
229
+
230
+ Args:
231
+ data: The data payload to send with the request
232
+ path: API endpoint path. Defaults to empty string.
233
+ timeout_seconds: Request timeout in seconds. Defaults to 5 minutes.
234
+ headers: Optional headers to include in the request
235
+ http_method: HTTP method to use. Defaults to "POST".
236
+ stream: Whether to stream the response. Defaults to False.
237
+
238
+ Returns:
239
+ InferenceResponse: Object containing the response data.
240
+
241
+ Raises:
242
+ InferenceClientError: If the request fails
243
+ """
225
244
  response = self._make_request(
226
245
  http_method, path, json=data, timeout_seconds=timeout_seconds, headers=headers, stream=stream)
227
246
 
@@ -233,6 +252,23 @@ class InferenceClient:
233
252
  )
234
253
 
235
254
  def run(self, data: Dict[str, Any], path: str = "", timeout_seconds: int = 60 * 5, headers: Optional[Dict[str, str]] = None, http_method: str = "POST", no_response: bool = False):
255
+ """Make an asynchronous request to the inference endpoint.
256
+
257
+ Args:
258
+ data: The data payload to send with the request
259
+ path: API endpoint path. Defaults to empty string.
260
+ timeout_seconds: Request timeout in seconds. Defaults to 5 minutes.
261
+ headers: Optional headers to include in the request
262
+ http_method: HTTP method to use. Defaults to "POST".
263
+ no_response: If True, don't wait for response. Defaults to False.
264
+
265
+ Returns:
266
+ AsyncInferenceExecution: Object to track the async execution status.
267
+ If no_response is True, returns None.
268
+
269
+ Raises:
270
+ InferenceClientError: If the request fails
271
+ """
236
272
  # Add relevant headers to the request, to indicate that the request is async
237
273
  headers = headers or {}
238
274
  if no_response:
datacrunch/__version__.py CHANGED
@@ -1 +1 @@
1
- VERSION = '1.10.0'
1
+ VERSION = '1.11.0'
datacrunch/constants.py CHANGED
@@ -22,6 +22,7 @@ class VolumeActions:
22
22
 
23
23
 
24
24
  class InstanceStatus:
25
+ ORDERED = 'ordered'
25
26
  RUNNING = 'running'
26
27
  PROVISIONING = 'provisioning'
27
28
  OFFLINE = 'offline'
@@ -1,376 +1,113 @@
1
+ import time
1
2
  from typing import List, Union, Optional, Dict, Literal
2
- from datacrunch.helpers import stringify_class_object_properties
3
- from datacrunch.constants import Locations
3
+ from dataclasses import dataclass
4
+ from dataclasses_json import dataclass_json
5
+ from datacrunch.constants import Locations, InstanceStatus
4
6
 
5
7
  INSTANCES_ENDPOINT = '/instances'
6
8
 
7
9
  Contract = Literal['LONG_TERM', 'PAY_AS_YOU_GO', 'SPOT']
8
10
  Pricing = Literal['DYNAMIC_PRICE', 'FIXED_PRICE']
9
11
 
10
- class Instance:
11
- """An instance model class"""
12
-
13
- def __init__(self,
14
- id: str,
15
- instance_type: str,
16
- image: str,
17
- price_per_hour: float,
18
- hostname: str,
19
- description: str,
20
- ip: str,
21
- status: str,
22
- created_at: str,
23
- ssh_key_ids: List[str],
24
- cpu: dict,
25
- gpu: dict,
26
- memory: dict,
27
- storage: dict,
28
- os_volume_id: str,
29
- gpu_memory: dict,
30
- location: str = Locations.FIN_01,
31
- startup_script_id: str = None,
32
- is_spot: bool = False,
33
- contract: Contract = None,
34
- pricing: Pricing = None,
35
- ) -> None:
36
- """Initialize the instance object
37
-
38
- :param id: instance id
39
- :type id: str
40
- :param instance_type: instance type. e.g. '8V100.48M'
41
- :type instance_type: str
42
- :param image: instance image type. e.g. 'ubuntu-20.04-cuda-11.0'
43
- :type image: str
44
- :param price_per_hour: price per hour
45
- :type price_per_hour: float
46
- :param hostname: instance hostname
47
- :type hostname: str
48
- :param description: instance description
49
- :type description: str
50
- :param ip: instance ip address
51
- :type ip: str
52
- :param status: instance current status, might be out of date if changed
53
- :type status: str
54
- :param created_at: the time the instance was deployed (UTC)
55
- :type created_at: str
56
- :param ssh_key_ids: list of ssh keys ids
57
- :type ssh_key_ids: List[str]
58
- :param cpu: cpu details
59
- :type cpu: dict
60
- :param gpu: gpu details
61
- :type gpu: dict
62
- :param memory: memory details
63
- :type memory: dict
64
- :param storage: storate details
65
- :type storage: dict
66
- :param id: main OS volume id
67
- :type id: str
68
- :param memory: gpu memory details
69
- :type memory: dict
70
- :param location: datacenter location, defaults to "FIN-01"
71
- :type location: str, optional
72
- :param startup_script_id: startup script id, defaults to None
73
- :type startup_script_id: str, optional
74
- :param is_spot: is this a spot instance, defaults to None
75
- :type is_spot: bool, optional
76
- """
77
- self._id = id
78
- self._instance_type = instance_type
79
- self._image = image
80
- self._price_per_hour = price_per_hour
81
- self._location = location
82
- self._hostname = hostname
83
- self._description = description
84
- self._ip = ip
85
- self._status = status
86
- self._created_at = created_at
87
- self._ssh_key_ids = ssh_key_ids
88
- self._startup_script_id = startup_script_id
89
- self._cpu = cpu
90
- self._gpu = gpu
91
- self._memory = memory
92
- self._storage = storage
93
- self._os_volume_id = os_volume_id
94
- self._gpu_memory = gpu_memory
95
- self._is_spot = is_spot
96
- self._contract = contract
97
- self._pricing = pricing
98
-
99
- @property
100
- def id(self) -> str:
101
- """Get the instance id
102
-
103
- :return: instance id
104
- :rtype: str
105
- """
106
- return self._id
107
-
108
- @property
109
- def instance_type(self) -> str:
110
- """Get the instance type
111
-
112
- :return: instance type
113
- :rtype: str
114
- """
115
- return self._instance_type
116
-
117
- @property
118
- def image(self) -> str:
119
- """Get the instance image type
120
-
121
- :return: instance image type
122
- :rtype: str
123
- """
124
- return self._image
125
-
126
- @property
127
- def price_per_hour(self) -> float:
128
- """Get the instance price per hour
129
-
130
- :return: price per hour
131
- :rtype: float
132
- """
133
- return self._price_per_hour
134
-
135
- @property
136
- def location(self) -> str:
137
- """Get the instance datacenter location
138
-
139
- :return: datacenter location
140
- :rtype: str
141
- """
142
- return self._location
143
-
144
- @property
145
- def hostname(self) -> str:
146
- """Get the instance hostname
147
-
148
- :return: hostname
149
- :rtype: str
150
- """
151
- return self._hostname
152
-
153
- @property
154
- def description(self) -> str:
155
- """Get the instance description
156
-
157
- :return: instance description
158
- :rtype: str
159
- """
160
- return self._description
161
-
162
- @property
163
- def ip(self) -> str:
164
- """Get the instance ip address
165
-
166
- :return: ip address
167
- :rtype: str
168
- """
169
- return self._ip
170
-
171
- @property
172
- def status(self) -> str:
173
- """Get the current instance status. might be out of date if changed.
174
-
175
- :return: instance status
176
- :rtype: str
177
- """
178
- return self._status
179
-
180
- @property
181
- def created_at(self) -> str:
182
- """Get the time when the instance was deployed (UTC)
183
-
184
- :return: time
185
- :rtype: str
186
- """
187
- return self._created_at
188
-
189
- @property
190
- def ssh_key_ids(self) -> List[str]:
191
- """Get the SSH key IDs of the instance
192
-
193
- :return: SSH key IDs
194
- :rtype: List[str]
195
- """
196
- return self._ssh_key_ids
197
-
198
- @property
199
- def startup_script_id(self) -> Union[str, None]:
200
- """Get the startup script ID or None if the is no script
201
-
202
- :return: startup script ID or None
203
- :rtype: Union[str, None]
204
- """
205
- return self._startup_script_id
206
-
207
- @property
208
- def cpu(self) -> dict:
209
- """Get the instance cpu details
210
-
211
- :return: cpu details
212
- :rtype: dict
213
- """
214
- return self._cpu
215
-
216
- @property
217
- def gpu(self) -> dict:
218
- """Get the instance gpu details
219
12
 
220
- :return: gpu details
221
- :rtype: dict
222
- """
223
- return self._gpu
224
-
225
- @property
226
- def memory(self) -> dict:
227
- """Get the instance memory details
228
-
229
- :return: memory details
230
- :rtype: dict
231
- """
232
- return self._memory
233
-
234
- @property
235
- def storage(self) -> dict:
236
- """Get the instance storage details
237
-
238
- :return: storage details
239
- :rtype: dict
240
- """
241
- return self._storage
242
-
243
- @property
244
- def os_volume_id(self) -> str:
245
- """Get the main os volume id
246
-
247
- :return: main os volume id
248
- :rtype: str
249
- """
250
- return self._os_volume_id
251
-
252
- @property
253
- def gpu_memory(self) -> dict:
254
- """Get the instance gpu_memory details
255
-
256
- :return: gpu_memory details
257
- :rtype: dict
258
- """
259
- return self._gpu_memory
260
-
261
- @property
262
- def is_spot(self) -> bool:
263
- """Is this a spot instance
264
-
265
- :return: is spot details
266
- :rtype: bool
267
- """
268
- return self._is_spot
13
+ @dataclass_json
14
+ @dataclass
15
+ class Instance:
16
+ """Represents a cloud instance with its configuration and state.
17
+
18
+ Attributes:
19
+ id: Unique identifier for the instance.
20
+ instance_type: Type of the instance (e.g., '8V100.48V').
21
+ price_per_hour: Cost per hour of running the instance.
22
+ hostname: Network hostname of the instance.
23
+ description: Human-readable description of the instance.
24
+ status: Current operational status of the instance.
25
+ created_at: Timestamp of instance creation.
26
+ ssh_key_ids: List of SSH key IDs associated with the instance.
27
+ cpu: CPU configuration details.
28
+ gpu: GPU configuration details.
29
+ memory: Memory configuration details.
30
+ storage: Storage configuration details.
31
+ gpu_memory: GPU memory configuration details.
32
+ ip: IP address assigned to the instance.
33
+ os_volume_id: ID of the operating system volume.
34
+ location: Datacenter location code (default: Locations.FIN_01).
35
+ image: Image ID or type used for the instance.
36
+ startup_script_id: ID of the startup script to run.
37
+ is_spot: Whether the instance is a spot instance.
38
+ contract: Contract type for the instance. (e.g. 'LONG_TERM', 'PAY_AS_YOU_GO', 'SPOT')
39
+ pricing: Pricing model for the instance. (e.g. 'DYNAMIC_PRICE', 'FIXED_PRICE')
40
+ """
41
+
42
+ id: str
43
+ instance_type: str
44
+ price_per_hour: float
45
+ hostname: str
46
+ description: str
47
+ status: str
48
+ created_at: str
49
+ ssh_key_ids: List[str]
50
+ cpu: dict
51
+ gpu: dict
52
+ memory: dict
53
+ storage: dict
54
+ gpu_memory: dict
55
+ # Can be None if instance is still not provisioned
56
+ ip: Optional[str] = None
57
+ # Can be None if instance is still not provisioned
58
+ os_volume_id: Optional[str] = None
59
+ location: str = Locations.FIN_01
60
+ image: Optional[str] = None
61
+ startup_script_id: Optional[str] = None
62
+ is_spot: bool = False
63
+ contract: Optional[Contract] = None
64
+ pricing: Optional[Pricing] = None
269
65
 
270
- @property
271
- def contract(self) -> bool:
272
- """Get contract type
273
66
 
274
- :return: contract type
275
- :rtype: str
276
- """
277
- return self._contract
67
+ class InstancesService:
68
+ """Service for managing cloud instances through the API.
278
69
 
279
- @property
280
- def pricing(self) -> bool:
281
- """Get pricing type
70
+ This service provides methods to create, retrieve, and manage cloud instances
71
+ through the DataCrunch API.
72
+ """
282
73
 
283
- :return: pricing type
284
- :rtype: str
285
- """
286
- return self._pricing
287
-
288
- def __str__(self) -> str:
289
- """Returns a string of the json representation of the instance
74
+ def __init__(self, http_client) -> None:
75
+ """Initializes the InstancesService with an HTTP client.
290
76
 
291
- :return: json representation of the instance
292
- :rtype: str
77
+ Args:
78
+ http_client: HTTP client for making API requests.
293
79
  """
294
- return stringify_class_object_properties(self)
295
-
296
-
297
- class InstancesService:
298
- """A service for interacting with the instances endpoint"""
299
-
300
- def __init__(self, http_client) -> None:
301
80
  self._http_client = http_client
302
81
 
303
- def get(self, status: str = None) -> List[Instance]:
304
- """Get all of the client's non-deleted instances, or instances with specific status.
82
+ def get(self, status: Optional[str] = None) -> List[Instance]:
83
+ """Retrieves all non-deleted instances or instances with specific status.
84
+
85
+ Args:
86
+ status: Optional status filter for instances. If None, returns all
87
+ non-deleted instances.
305
88
 
306
- :param status: optional, status of the instances, defaults to None
307
- :type status: str, optional
308
- :return: list of instance details objects
309
- :rtype: List[Instance]
89
+ Returns:
90
+ List of instance objects matching the criteria.
310
91
  """
311
92
  instances_dict = self._http_client.get(
312
93
  INSTANCES_ENDPOINT, params={'status': status}).json()
313
- instances = list(map(lambda instance_dict: Instance(
314
- id=instance_dict['id'],
315
- instance_type=instance_dict['instance_type'],
316
- image=instance_dict['image'],
317
- price_per_hour=instance_dict['price_per_hour'] if 'price_per_hour' in instance_dict else None,
318
- location=instance_dict['location'],
319
- hostname=instance_dict['hostname'],
320
- description=instance_dict['description'],
321
- ip=instance_dict['ip'],
322
- status=instance_dict['status'],
323
- created_at=instance_dict['created_at'],
324
- ssh_key_ids=instance_dict['ssh_key_ids'] if 'ssh_key_ids' in instance_dict else [
325
- ],
326
- startup_script_id=instance_dict['startup_script_id'] if 'startup_script_id' in instance_dict else None,
327
- cpu=instance_dict['cpu'],
328
- gpu=instance_dict['gpu'],
329
- memory=instance_dict['memory'],
330
- storage=instance_dict['storage'],
331
- os_volume_id=instance_dict['os_volume_id'] if 'os_volume_id' in instance_dict else None,
332
- gpu_memory=instance_dict['gpu_memory'] if 'gpu_memory' in instance_dict else None,
333
- is_spot=instance_dict['is_spot'] if 'is_spot' in instance_dict else False,
334
- contract=instance_dict['contract'] if 'contract' in instance_dict else False,
335
- pricing=instance_dict['pricing'] if 'pricing' in instance_dict else False,
336
- ), instances_dict))
337
- return instances
94
+ return [Instance.from_dict(instance_dict, infer_missing=True) for instance_dict in instances_dict]
338
95
 
339
96
  def get_by_id(self, id: str) -> Instance:
340
- """Get an instance with specified id.
97
+ """Retrieves a specific instance by its ID.
98
+
99
+ Args:
100
+ id: Unique identifier of the instance to retrieve.
101
+
102
+ Returns:
103
+ Instance object with the specified ID.
341
104
 
342
- :param id: instance id
343
- :type id: str
344
- :return: instance details object
345
- :rtype: Instance
105
+ Raises:
106
+ HTTPError: If the instance is not found or other API error occurs.
346
107
  """
347
108
  instance_dict = self._http_client.get(
348
109
  INSTANCES_ENDPOINT + f'/{id}').json()
349
- instance = Instance(
350
- id=instance_dict['id'],
351
- instance_type=instance_dict['instance_type'],
352
- image=instance_dict['image'],
353
- price_per_hour=instance_dict['price_per_hour'] if 'price_per_hour' in instance_dict else None,
354
- location=instance_dict['location'],
355
- hostname=instance_dict['hostname'],
356
- description=instance_dict['description'],
357
- ip=instance_dict['ip'],
358
- status=instance_dict['status'],
359
- created_at=instance_dict['created_at'],
360
- ssh_key_ids=instance_dict['ssh_key_ids'] if 'ssh_key_ids' in instance_dict else [
361
- ],
362
- startup_script_id=instance_dict['startup_script_id'] if 'startup_script_id' in instance_dict else None,
363
- cpu=instance_dict['cpu'],
364
- gpu=instance_dict['gpu'],
365
- memory=instance_dict['memory'],
366
- storage=instance_dict['storage'],
367
- os_volume_id=instance_dict['os_volume_id'] if 'os_volume_id' in instance_dict else None,
368
- gpu_memory=instance_dict['gpu_memory'] if 'gpu_memory' in instance_dict else None,
369
- is_spot=instance_dict['is_spot'] if 'is_spot' in instance_dict else False,
370
- contract=instance_dict['contract'] if 'contract' in instance_dict else False,
371
- pricing=instance_dict['pricing'] if 'pricing' in instance_dict else False,
372
- )
373
- return instance
110
+ return Instance.from_dict(instance_dict, infer_missing=True)
374
111
 
375
112
  def create(self,
376
113
  instance_type: str,
@@ -379,46 +116,37 @@ class InstancesService:
379
116
  description: str,
380
117
  ssh_key_ids: list = [],
381
118
  location: str = Locations.FIN_01,
382
- startup_script_id: str = None,
383
- volumes: List[Dict] = None,
384
- existing_volumes: List[str] = None,
385
- os_volume: Dict = None,
119
+ startup_script_id: Optional[str] = None,
120
+ volumes: Optional[List[Dict]] = None,
121
+ existing_volumes: Optional[List[str]] = None,
122
+ os_volume: Optional[Dict] = None,
386
123
  is_spot: bool = False,
387
- contract: Contract = None,
388
- pricing: Pricing = None,
389
- coupon: str = None) -> Instance:
390
- """Creates (deploys) a new instance
391
-
392
- :param instance_type: instance type. e.g. '8V100.48M'
393
- :type instance_type: str
394
- :param image: instance image type. e.g. 'ubuntu-20.04-cuda-11.0', or existing OS volume id
395
- :type image: str
396
- :param ssh_key_ids: list of ssh key ids
397
- :type ssh_key_ids: list
398
- :param hostname: instance hostname
399
- :type hostname: str
400
- :param description: instance description
401
- :type description: str
402
- :param location: datacenter location, defaults to "FIN-01"
403
- :type location: str, optional
404
- :param startup_script_id: startup script id, defaults to None
405
- :type startup_script_id: str, optional
406
- :param volumes: List of volume data dictionaries to create alongside the instance
407
- :type volumes: List[Dict], optional
408
- :param existing_volumes: List of existing volume ids to attach to the instance
409
- :type existing_volumes: List[str], optional
410
- :param os_volume: OS volume details, defaults to None
411
- :type os_volume: Dict, optional
412
- :param is_spot: Is spot instance
413
- :type is_spot: bool, optional
414
- :param pricing: Pricing type
415
- :type pricing: str, optional
416
- :param contract: Contract type
417
- :type contract: str, optional
418
- :param coupon: coupon code
419
- :type coupon: str, optional
420
- :return: the new instance object
421
- :rtype: id
124
+ contract: Optional[Contract] = None,
125
+ pricing: Optional[Pricing] = None,
126
+ coupon: Optional[str] = None) -> Instance:
127
+ """Creates and deploys a new cloud instance.
128
+
129
+ Args:
130
+ instance_type: Type of instance to create (e.g., '8V100.48V').
131
+ image: Image type or existing OS volume ID for the instance.
132
+ hostname: Network hostname for the instance.
133
+ description: Human-readable description of the instance.
134
+ ssh_key_ids: List of SSH key IDs to associate with the instance.
135
+ location: Datacenter location code (default: Locations.FIN_01).
136
+ startup_script_id: Optional ID of startup script to run.
137
+ volumes: Optional list of volume configurations to create.
138
+ existing_volumes: Optional list of existing volume IDs to attach.
139
+ os_volume: Optional OS volume configuration details.
140
+ is_spot: Whether to create a spot instance.
141
+ contract: Optional contract type for the instance.
142
+ pricing: Optional pricing model for the instance.
143
+ coupon: Optional coupon code for discounts.
144
+
145
+ Returns:
146
+ The newly created instance object.
147
+
148
+ Raises:
149
+ HTTPError: If instance creation fails or other API error occurs.
422
150
  """
423
151
  payload = {
424
152
  "instance_type": instance_type,
@@ -439,18 +167,33 @@ class InstancesService:
439
167
  if pricing:
440
168
  payload['pricing'] = pricing
441
169
  id = self._http_client.post(INSTANCES_ENDPOINT, json=payload).text
442
- instance = self.get_by_id(id)
443
- return instance
170
+
171
+ # Wait for instance to enter provisioning state with timeout
172
+ MAX_WAIT_TIME = 60 # Maximum wait time in seconds
173
+ POLL_INTERVAL = 0.5 # Time between status checks
174
+
175
+ start_time = time.time()
176
+ while True:
177
+ instance = self.get_by_id(id)
178
+ if instance.status != InstanceStatus.ORDERED:
179
+ return instance
180
+
181
+ if time.time() - start_time > MAX_WAIT_TIME:
182
+ raise TimeoutError(
183
+ f"Instance {id} did not enter provisioning state within {MAX_WAIT_TIME} seconds")
184
+
185
+ time.sleep(POLL_INTERVAL)
444
186
 
445
187
  def action(self, id_list: Union[List[str], str], action: str, volume_ids: Optional[List[str]] = None) -> None:
446
- """Performs an action on a list of instances / single instance
447
-
448
- :param id_list: list of instance ids, or an instance id
449
- :type id_list: Union[List[str], str]
450
- :param action: the action to perform
451
- :type action: str
452
- :param volume_ids: the volume ids to delete
453
- :type volume_ids: Optional[List[str]]
188
+ """Performs an action on one or more instances.
189
+
190
+ Args:
191
+ id_list: Single instance ID or list of instance IDs to act upon.
192
+ action: Action to perform on the instances.
193
+ volume_ids: Optional list of volume IDs to delete.
194
+
195
+ Raises:
196
+ HTTPError: If the action fails or other API error occurs.
454
197
  """
455
198
  if type(id_list) is str:
456
199
  id_list = [id_list]
@@ -464,34 +207,31 @@ class InstancesService:
464
207
  self._http_client.put(INSTANCES_ENDPOINT, json=payload)
465
208
  return
466
209
 
467
- # TODO: use enum/const for location_code
468
- def is_available(self, instance_type: str, is_spot: bool = False, location_code: str = None) -> bool:
469
- """Returns True if a specific instance type is now available for deployment
470
-
471
- :param instance_type: instance type
472
- :type instance_type: str
473
- :param is_spot: Is spot instance
474
- :type is_spot: bool, optional
475
- :param location_code: datacenter location, defaults to "FIN-01"
476
- :type location_code: str, optional
477
- :return: True if available to deploy, False otherwise
478
- :rtype: bool
210
+ def is_available(self, instance_type: str, is_spot: bool = False, location_code: Optional[str] = None) -> bool:
211
+ """Checks if a specific instance type is available for deployment.
212
+
213
+ Args:
214
+ instance_type: Type of instance to check availability for.
215
+ is_spot: Whether to check spot instance availability.
216
+ location_code: Optional datacenter location code.
217
+
218
+ Returns:
219
+ True if the instance type is available, False otherwise.
479
220
  """
480
221
  is_spot = str(is_spot).lower()
481
222
  query_params = {'isSpot': is_spot, 'location_code': location_code}
482
223
  url = f'/instance-availability/{instance_type}'
483
224
  return self._http_client.get(url, query_params).json()
484
225
 
485
- # TODO: use enum/const for location_code
486
- def get_availabilities(self, is_spot: bool = None, location_code: str = None) -> bool:
487
- """Returns a list of available instance types
226
+ def get_availabilities(self, is_spot: Optional[bool] = None, location_code: Optional[str] = None) -> List[Dict]:
227
+ """Retrieves a list of available instance types across locations.
228
+
229
+ Args:
230
+ is_spot: Optional flag to filter spot instance availability.
231
+ location_code: Optional datacenter location code to filter by.
488
232
 
489
- :param is_spot: Is spot instance
490
- :type is_spot: bool, optional
491
- :param location_code: datacenter location, defaults to "FIN-01"
492
- :type location_code: str, optional
493
- :return: list of available instance types in every location
494
- :rtype: list
233
+ Returns:
234
+ List of available instance types and their details.
495
235
  """
496
236
  is_spot = str(is_spot).lower() if is_spot is not None else None
497
237
  query_params = {'isSpot': is_spot, 'locationCode': location_code}
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: datacrunch
3
- Version: 1.10.0
3
+ Version: 1.11.0
4
4
  Summary: Official Python SDK for DataCrunch Public API
5
5
  Home-page: https://github.com/DataCrunch-io
6
6
  Author: DataCrunch Oy
@@ -1,11 +1,11 @@
1
1
  datacrunch/__init__.py,sha256=OG-5Avmuq3NXyBs_66GMwyzscUi0c-T6vWW5sRIfnZg,51
2
- datacrunch/__version__.py,sha256=VntYBWPvXjh_VXu4WVj3EEodB6Jeg2IODCkHTuqpLfc,19
3
- datacrunch/constants.py,sha256=uBtS1kTe6ip5oWzA4SKAVftdapkKwUU45GdLYOuBzAA,2354
2
+ datacrunch/__version__.py,sha256=PZXNp6jInd8yQ1-bKHKA0wcJLwj4YpA4waxO3RnKNa0,19
3
+ datacrunch/constants.py,sha256=i0jCX91H2lKp1Uvk4GDsaTeXk0WmjyeSGpMfPs69BB4,2378
4
4
  datacrunch/datacrunch.py,sha256=2IqrTY39sLuwtuQ_QP3jCI1d5AaCwriYgAUEFoZZzPU,3488
5
5
  datacrunch/exceptions.py,sha256=uOP_YU2HEUi_mcMxQ9WYrIjqWUuUrwdube-RdL1C4Ps,781
6
6
  datacrunch/helpers.py,sha256=Eq5htNxpJUCJG9D6QxbnWwch3ppmi2lfi-rFCGXf3fs,634
7
7
  datacrunch/InferenceClient/__init__.py,sha256=oe7RQfoKbKJnIFWOt6TNtdzjXk5Gcl4-smO5DjLE6M0,117
8
- datacrunch/InferenceClient/inference_client.py,sha256=x3nWsQc5ds_ndXINdfk0KVW_R_rito_ArLouug0C_rI,14174
8
+ datacrunch/InferenceClient/inference_client.py,sha256=CM-ijRQuvaSf8BSbltkeocaIBvsAoBKT7xxnOT1q-Xs,15555
9
9
  datacrunch/authentication/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
10
  datacrunch/authentication/authentication.py,sha256=CThTxA99jseh7TKIdUR1M9RErIJoXvTB8CbF1VGFPCE,3589
11
11
  datacrunch/balance/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -19,7 +19,7 @@ datacrunch/images/images.py,sha256=hCAtSzozHcAAJ_UZOvnAbQSEU7BfCuixpIsmcd2RM2k,2
19
19
  datacrunch/instance_types/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
20
20
  datacrunch/instance_types/instance_types.py,sha256=NLkUI6UdfXg-zDkMu9j9RzVISLG8jdABhT_R7XpfBdA,5289
21
21
  datacrunch/instances/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
22
- datacrunch/instances/instances.py,sha256=DAjFSQPwugN4_u-13Q9K4gyjrPYwdTrIw2exHwhJ1bw,16626
22
+ datacrunch/instances/instances.py,sha256=GKPpZshn5JBsduR5zyT57fonB0GDdOLkPfPmGqgJQow,9239
23
23
  datacrunch/locations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
24
24
  datacrunch/locations/locations.py,sha256=2f1OF2ObNaqGam_Mm0Btie1GymnAI9UzXulhqSSm7zo,404
25
25
  datacrunch/ssh_keys/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -30,7 +30,7 @@ datacrunch/volume_types/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG
30
30
  datacrunch/volume_types/volume_types.py,sha256=CNJ8kfd_nxmF99x-UAJeku-uN4Gdh-yg15Aa8WGLgWU,1828
31
31
  datacrunch/volumes/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
32
32
  datacrunch/volumes/volumes.py,sha256=aAH4UIVG-7NehjHu-a_4MGSdZ1jmeApV-kKh-X6TB-s,11908
33
- datacrunch-1.10.0.dist-info/licenses/LICENSE,sha256=LkdhbR2MArjDfV8M0dySL5mG_kfzxF2ntMgbJvWGyUQ,1069
33
+ datacrunch-1.11.0.dist-info/licenses/LICENSE,sha256=LkdhbR2MArjDfV8M0dySL5mG_kfzxF2ntMgbJvWGyUQ,1069
34
34
  tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
35
35
  tests/integration_tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
36
36
  tests/integration_tests/conftest.py,sha256=PWf6K1G3NoddebmDIy_Pk02dHQrEKfrNxpWwqE8Eqrk,546
@@ -63,7 +63,7 @@ tests/unit_tests/volume_types/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5N
63
63
  tests/unit_tests/volume_types/test_volume_types.py,sha256=vGuC3dWjhQLD8bTYgw_we3dZ6vlUKRmKZbb9yCfhe0w,1386
64
64
  tests/unit_tests/volumes/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
65
65
  tests/unit_tests/volumes/test_volumes.py,sha256=p53eSIHddWKL7U9oLLTnxo849LrJSoi6A5lpWF6ydHs,20672
66
- datacrunch-1.10.0.dist-info/METADATA,sha256=SZ0jATJaVzH7jJ-jc7vRcQfIN-RUTe85nwCpu4w-YrM,6261
67
- datacrunch-1.10.0.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
68
- datacrunch-1.10.0.dist-info/top_level.txt,sha256=FvH4EZJkbUxNm-aKx0RjmWwnduAMpfRT13Fo123i7yE,17
69
- datacrunch-1.10.0.dist-info/RECORD,,
66
+ datacrunch-1.11.0.dist-info/METADATA,sha256=G2A9RigmIn__-clRNM6vUd-J3A7uM_mwaDBjR0_SI3U,6261
67
+ datacrunch-1.11.0.dist-info/WHEEL,sha256=ck4Vq1_RXyvS4Jt6SI0Vz6fyVs4GWg7AINwpsaGEgPE,91
68
+ datacrunch-1.11.0.dist-info/top_level.txt,sha256=FvH4EZJkbUxNm-aKx0RjmWwnduAMpfRT13Fo123i7yE,17
69
+ datacrunch-1.11.0.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (78.1.0)
2
+ Generator: setuptools (80.0.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5