databricks-sdk 0.19.0__py3-none-any.whl → 0.20.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.

Potentially problematic release.


This version of databricks-sdk might be problematic. Click here for more details.

@@ -124,7 +124,7 @@ class DirectoryEntry:
124
124
  """Last modification time of given file in milliseconds since unix epoch."""
125
125
 
126
126
  name: Optional[str] = None
127
- """The name of the file or directory."""
127
+ """The name of the file or directory. This is the last component of the path."""
128
128
 
129
129
  path: Optional[str] = None
130
130
  """The absolute path of the file or directory."""
@@ -151,8 +151,31 @@ class DirectoryEntry:
151
151
 
152
152
  @dataclass
153
153
  class DownloadResponse:
154
+ content_length: Optional[int] = None
155
+
156
+ content_type: Optional[str] = None
157
+
154
158
  contents: Optional[BinaryIO] = None
155
159
 
160
+ last_modified: Optional[str] = None
161
+
162
+ def as_dict(self) -> dict:
163
+ """Serializes the DownloadResponse into a dictionary suitable for use as a JSON request body."""
164
+ body = {}
165
+ if self.content_length is not None: body['content-length'] = self.content_length
166
+ if self.content_type is not None: body['content-type'] = self.content_type
167
+ if self.contents: body['contents'] = self.contents
168
+ if self.last_modified is not None: body['last-modified'] = self.last_modified
169
+ return body
170
+
171
+ @classmethod
172
+ def from_dict(cls, d: Dict[str, any]) -> DownloadResponse:
173
+ """Deserializes the DownloadResponse from a dictionary."""
174
+ return cls(content_length=d.get('content-length', None),
175
+ content_type=d.get('content-type', None),
176
+ contents=d.get('contents', None),
177
+ last_modified=d.get('last-modified', None))
178
+
156
179
 
157
180
  @dataclass
158
181
  class FileInfo:
@@ -186,6 +209,30 @@ class FileInfo:
186
209
  path=d.get('path', None))
187
210
 
188
211
 
212
+ @dataclass
213
+ class GetMetadataResponse:
214
+ content_length: Optional[int] = None
215
+
216
+ content_type: Optional[str] = None
217
+
218
+ last_modified: Optional[str] = None
219
+
220
+ def as_dict(self) -> dict:
221
+ """Serializes the GetMetadataResponse into a dictionary suitable for use as a JSON request body."""
222
+ body = {}
223
+ if self.content_length is not None: body['content-length'] = self.content_length
224
+ if self.content_type is not None: body['content-type'] = self.content_type
225
+ if self.last_modified is not None: body['last-modified'] = self.last_modified
226
+ return body
227
+
228
+ @classmethod
229
+ def from_dict(cls, d: Dict[str, any]) -> GetMetadataResponse:
230
+ """Deserializes the GetMetadataResponse from a dictionary."""
231
+ return cls(content_length=d.get('content-length', None),
232
+ content_type=d.get('content-type', None),
233
+ last_modified=d.get('last-modified', None))
234
+
235
+
189
236
  @dataclass
190
237
  class ListDirectoryResponse:
191
238
  contents: Optional[List[DirectoryEntry]] = None
@@ -338,6 +385,7 @@ class DbfsAPI:
338
385
  if data is not None: body['data'] = data
339
386
  if handle is not None: body['handle'] = handle
340
387
  headers = {'Accept': 'application/json', 'Content-Type': 'application/json', }
388
+
341
389
  self._api.do('POST', '/api/2.0/dbfs/add-block', body=body, headers=headers)
342
390
 
343
391
  def close(self, handle: int):
@@ -354,6 +402,7 @@ class DbfsAPI:
354
402
  body = {}
355
403
  if handle is not None: body['handle'] = handle
356
404
  headers = {'Accept': 'application/json', 'Content-Type': 'application/json', }
405
+
357
406
  self._api.do('POST', '/api/2.0/dbfs/close', body=body, headers=headers)
358
407
 
359
408
  def create(self, path: str, *, overwrite: Optional[bool] = None) -> CreateResponse:
@@ -379,6 +428,7 @@ class DbfsAPI:
379
428
  if overwrite is not None: body['overwrite'] = overwrite
380
429
  if path is not None: body['path'] = path
381
430
  headers = {'Accept': 'application/json', 'Content-Type': 'application/json', }
431
+
382
432
  res = self._api.do('POST', '/api/2.0/dbfs/create', body=body, headers=headers)
383
433
  return CreateResponse.from_dict(res)
384
434
 
@@ -412,6 +462,7 @@ class DbfsAPI:
412
462
  if path is not None: body['path'] = path
413
463
  if recursive is not None: body['recursive'] = recursive
414
464
  headers = {'Accept': 'application/json', 'Content-Type': 'application/json', }
465
+
415
466
  self._api.do('POST', '/api/2.0/dbfs/delete', body=body, headers=headers)
416
467
 
417
468
  def get_status(self, path: str) -> FileInfo:
@@ -429,6 +480,7 @@ class DbfsAPI:
429
480
  query = {}
430
481
  if path is not None: query['path'] = path
431
482
  headers = {'Accept': 'application/json', }
483
+
432
484
  res = self._api.do('GET', '/api/2.0/dbfs/get-status', query=query, headers=headers)
433
485
  return FileInfo.from_dict(res)
434
486
 
@@ -454,6 +506,7 @@ class DbfsAPI:
454
506
  query = {}
455
507
  if path is not None: query['path'] = path
456
508
  headers = {'Accept': 'application/json', }
509
+
457
510
  json = self._api.do('GET', '/api/2.0/dbfs/list', query=query, headers=headers)
458
511
  parsed = ListStatusResponse.from_dict(json).files
459
512
  return parsed if parsed is not None else []
@@ -474,6 +527,7 @@ class DbfsAPI:
474
527
  body = {}
475
528
  if path is not None: body['path'] = path
476
529
  headers = {'Accept': 'application/json', 'Content-Type': 'application/json', }
530
+
477
531
  self._api.do('POST', '/api/2.0/dbfs/mkdirs', body=body, headers=headers)
478
532
 
479
533
  def move(self, source_path: str, destination_path: str):
@@ -495,6 +549,7 @@ class DbfsAPI:
495
549
  if destination_path is not None: body['destination_path'] = destination_path
496
550
  if source_path is not None: body['source_path'] = source_path
497
551
  headers = {'Accept': 'application/json', 'Content-Type': 'application/json', }
552
+
498
553
  self._api.do('POST', '/api/2.0/dbfs/move', body=body, headers=headers)
499
554
 
500
555
  def put(self, path: str, *, contents: Optional[str] = None, overwrite: Optional[bool] = None):
@@ -525,6 +580,7 @@ class DbfsAPI:
525
580
  if overwrite is not None: body['overwrite'] = overwrite
526
581
  if path is not None: body['path'] = path
527
582
  headers = {'Accept': 'application/json', 'Content-Type': 'application/json', }
583
+
528
584
  self._api.do('POST', '/api/2.0/dbfs/put', body=body, headers=headers)
529
585
 
530
586
  def read(self, path: str, *, length: Optional[int] = None, offset: Optional[int] = None) -> ReadResponse:
@@ -554,12 +610,24 @@ class DbfsAPI:
554
610
  if offset is not None: query['offset'] = offset
555
611
  if path is not None: query['path'] = path
556
612
  headers = {'Accept': 'application/json', }
613
+
557
614
  res = self._api.do('GET', '/api/2.0/dbfs/read', query=query, headers=headers)
558
615
  return ReadResponse.from_dict(res)
559
616
 
560
617
 
561
618
  class FilesAPI:
562
- """The Files API allows you to read, write, and delete files and directories in Unity Catalog volumes."""
619
+ """The Files API allows you to read, write, list, and delete files and directories. We support Unity Catalog
620
+ volumes with paths starting with "/Volumes/<catalog>/<schema>/<volume>".
621
+
622
+ The Files API is designed like a standard HTTP API, rather than as a JSON RPC API. This is intended to
623
+ make it easier and more efficient to work with file contents as raw bytes.
624
+
625
+ Because the Files API is a standard HTTP API, the URI path is used to specify the file or directory to
626
+ operate on. The path is always absolute.
627
+
628
+ The Files API has separate endpoints for working with files, `/fs/files`, and working with directories,
629
+ `/fs/directories`. The standard HTTP methods `GET`, `HEAD`, `PUT`, and `DELETE` work as expected on these
630
+ endpoints."""
563
631
 
564
632
  def __init__(self, api_client):
565
633
  self._api = api_client
@@ -567,7 +635,9 @@ class FilesAPI:
567
635
  def create_directory(self, directory_path: str):
568
636
  """Create a directory.
569
637
 
570
- Creates an empty directory. If called on an existing directory, the API returns a success response.
638
+ Creates an empty directory. If necessary, also creates any parent directories of the new, empty
639
+ directory (like the shell command `mkdir -p`). If called on an existing directory, returns a success
640
+ response; this method is idempotent.
571
641
 
572
642
  :param directory_path: str
573
643
  The absolute path of a directory.
@@ -576,12 +646,13 @@ class FilesAPI:
576
646
  """
577
647
 
578
648
  headers = {}
649
+
579
650
  self._api.do('PUT', f'/api/2.0/fs/directories{directory_path}', headers=headers)
580
651
 
581
652
  def delete(self, file_path: str):
582
653
  """Delete a file.
583
654
 
584
- Deletes a file.
655
+ Deletes a file. If the request is successful, there is no response body.
585
656
 
586
657
  :param file_path: str
587
658
  The absolute path of the file.
@@ -590,12 +661,16 @@ class FilesAPI:
590
661
  """
591
662
 
592
663
  headers = {}
664
+
593
665
  self._api.do('DELETE', f'/api/2.0/fs/files{file_path}', headers=headers)
594
666
 
595
667
  def delete_directory(self, directory_path: str):
596
668
  """Delete a directory.
597
669
 
598
- Deletes an empty directory. If the directory is not empty, the API returns a HTTP 400 error.
670
+ Deletes an empty directory.
671
+
672
+ To delete a non-empty directory, first delete all of its contents. This can be done by listing the
673
+ directory contents and deleting each file and subdirectory recursively.
599
674
 
600
675
  :param directory_path: str
601
676
  The absolute path of a directory.
@@ -604,12 +679,14 @@ class FilesAPI:
604
679
  """
605
680
 
606
681
  headers = {}
682
+
607
683
  self._api.do('DELETE', f'/api/2.0/fs/directories{directory_path}', headers=headers)
608
684
 
609
685
  def download(self, file_path: str) -> DownloadResponse:
610
686
  """Download a file.
611
687
 
612
- Downloads a file of up to 5 GiB.
688
+ Downloads a file of up to 5 GiB. The file contents are the response body. This is a standard HTTP file
689
+ download, not a JSON RPC.
613
690
 
614
691
  :param file_path: str
615
692
  The absolute path of the file.
@@ -618,8 +695,53 @@ class FilesAPI:
618
695
  """
619
696
 
620
697
  headers = {'Accept': 'application/octet-stream', }
621
- res = self._api.do('GET', f'/api/2.0/fs/files{file_path}', headers=headers, raw=True)
622
- return DownloadResponse(contents=res)
698
+ response_headers = ['content-length', 'content-type', 'last-modified', ]
699
+ res = self._api.do('GET',
700
+ f'/api/2.0/fs/files{file_path}',
701
+ headers=headers,
702
+ response_headers=response_headers,
703
+ raw=True)
704
+ return DownloadResponse.from_dict(res)
705
+
706
+ def get_directory_metadata(self, directory_path: str):
707
+ """Get directory metadata.
708
+
709
+ Get the metadata of a directory. The response HTTP headers contain the metadata. There is no response
710
+ body.
711
+
712
+ This method is useful to check if a directory exists and the caller has access to it.
713
+
714
+ If you wish to ensure the directory exists, you can instead use `PUT`, which will create the directory
715
+ if it does not exist, and is idempotent (it will succeed if the directory already exists).
716
+
717
+ :param directory_path: str
718
+ The absolute path of a directory.
719
+
720
+
721
+ """
722
+
723
+ headers = {}
724
+
725
+ self._api.do('HEAD', f'/api/2.0/fs/directories{directory_path}', headers=headers)
726
+
727
+ def get_metadata(self, file_path: str) -> GetMetadataResponse:
728
+ """Get file metadata.
729
+
730
+ Get the metadata of a file. The response HTTP headers contain the metadata. There is no response body.
731
+
732
+ :param file_path: str
733
+ The absolute path of the file.
734
+
735
+ :returns: :class:`GetMetadataResponse`
736
+ """
737
+
738
+ headers = {}
739
+ response_headers = ['content-length', 'content-type', 'last-modified', ]
740
+ res = self._api.do('HEAD',
741
+ f'/api/2.0/fs/files{file_path}',
742
+ headers=headers,
743
+ response_headers=response_headers)
744
+ return GetMetadataResponse.from_dict(res)
623
745
 
624
746
  def list_directory_contents(self,
625
747
  directory_path: str,
@@ -634,16 +756,22 @@ class FilesAPI:
634
756
  :param directory_path: str
635
757
  The absolute path of a directory.
636
758
  :param page_size: int (optional)
637
- The maximum number of directory entries to return. The API may return fewer than this value.
638
- Receiving fewer results does not imply there are no more results. As long as the response contains a
639
- next_page_token, there may be more results.
759
+ The maximum number of directory entries to return. The response may contain fewer entries. If the
760
+ response contains a `next_page_token`, there may be more entries, even if fewer than `page_size`
761
+ entries are in the response.
762
+
763
+ We recommend not to set this value unless you are intentionally listing less than the complete
764
+ directory contents.
640
765
 
641
766
  If unspecified, at most 1000 directory entries will be returned. The maximum value is 1000. Values
642
767
  above 1000 will be coerced to 1000.
643
768
  :param page_token: str (optional)
644
- A page token, received from a previous `list` call. Provide this to retrieve the subsequent page.
645
- When paginating, all other parameters provided to `list` must match the call that provided the page
646
- token.
769
+ An opaque page token which was the `next_page_token` in the response of the previous request to list
770
+ the contents of this directory. Provide this token to retrieve the next page of directory entries.
771
+ When providing a `page_token`, all other parameters provided to the request must match the previous
772
+ request. To list all of the entries in a directory, it is necessary to continue requesting pages of
773
+ entries until the response contains no `next_page_token`. Note that the number of entries returned
774
+ must not be used to determine when the listing is complete.
647
775
 
648
776
  :returns: Iterator over :class:`DirectoryEntry`
649
777
  """
@@ -668,7 +796,10 @@ class FilesAPI:
668
796
  def upload(self, file_path: str, contents: BinaryIO, *, overwrite: Optional[bool] = None):
669
797
  """Upload a file.
670
798
 
671
- Uploads a file of up to 5 GiB.
799
+ Uploads a file of up to 5 GiB. The file contents should be sent as the request body as raw bytes (an
800
+ octet stream); do not encode or otherwise modify the bytes before sending. The contents of the
801
+ resulting file will be exactly the bytes sent in the request body. If the request is successful, there
802
+ is no response body.
672
803
 
673
804
  :param file_path: str
674
805
  The absolute path of the file.
@@ -682,4 +813,5 @@ class FilesAPI:
682
813
  query = {}
683
814
  if overwrite is not None: query['overwrite'] = overwrite
684
815
  headers = {'Content-Type': 'application/octet-stream', }
816
+
685
817
  self._api.do('PUT', f'/api/2.0/fs/files{file_path}', query=query, headers=headers, data=contents)