Skip to content

Commit b688bf4

Browse files
committed
clean up class, make true optional import
1 parent d93a77d commit b688bf4

5 files changed

Lines changed: 73 additions & 27 deletions

File tree

pins/databricks/fs.py

Lines changed: 61 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22
from io import BytesIO
33
from pathlib import Path, PurePath
44

5-
from databricks.sdk import WorkspaceClient
6-
from databricks.sdk.errors import NotFound
75
from fsspec import AbstractFileSystem
86

97
from pins.errors import PinsError
@@ -13,18 +11,18 @@ class DatabricksFs(AbstractFileSystem):
1311
protocol = "dbc"
1412

1513
def ls(self, path, detail=False, **kwargs):
16-
return self._databricks_ls(self, path, detail)
14+
return self._databricks_ls(path, detail)
1715

1816
def exists(self, path: str, **kwargs):
19-
return self._databricks_exists(self, path)
17+
return self._databricks_exists(path)
2018

2119
def open(self, path: str, mode: str = "rb", *args, **kwargs):
2220
if mode != "rb":
2321
raise NotImplementedError
24-
return self._databricks_open(self, path)
22+
return self._databricks_open(path)
2523

2624
def get(self, rpath, lpath, recursive=False, **kwargs):
27-
self._databricks_get(self, rpath, lpath, recursive, **kwargs)
25+
self._databricks_get(rpath, lpath, recursive, **kwargs)
2826

2927
def mkdir(self, path, create_parents=True, **kwargs):
3028
if not create_parents:
@@ -50,11 +48,18 @@ def rm(self, path, recursive=True, maxdepth=None) -> None:
5048
raise NotImplementedError
5149
if maxdepth is not None:
5250
raise NotImplementedError
53-
if self._databricks_exists(self, path):
54-
self._databricks_rm_dir(self, path)
51+
if self._databricks_exists(path):
52+
self._databricks_rm_dir(path)
5553

5654
@staticmethod
5755
def _databricks_put(lpath, rpath):
56+
try:
57+
from databricks.sdk import WorkspaceClient
58+
except ModuleNotFoundError:
59+
raise PinsError(
60+
"Install the `databricks-sdk` package for Databricks board support."
61+
)
62+
5863
w = WorkspaceClient()
5964
path = Path(lpath).absolute()
6065
orig_path = path
@@ -74,15 +79,21 @@ def _upload_files(path):
7479

7580
_upload_files(path)
7681

77-
@staticmethod
7882
def _databricks_get(self, board, rpath, lpath, recursive=False, **kwargs):
83+
try:
84+
from databricks.sdk import WorkspaceClient
85+
except ModuleNotFoundError:
86+
raise PinsError(
87+
"Install the `databricks-sdk` package for Databricks board support."
88+
)
89+
7990
w = WorkspaceClient()
8091
file_type = self._databricks_is_type(rpath)
8192
if file_type == "file":
8293
board.fs.get(rpath, lpath, **kwargs)
8394
return
8495

85-
def _get_files(self, path, recursive, **kwargs):
96+
def _get_files(path, recursive, **kwargs):
8697
raw_contents = w.files.list_directory_contents(path)
8798
contents = list(raw_contents)
8899
details = list(map(self._databricks_content_details, contents))
@@ -96,11 +107,17 @@ def _get_files(self, path, recursive, **kwargs):
96107
target_path = PurePath(lpath).joinpath(rel_path)
97108
board.fs.get(item_path, str(target_path))
98109

99-
_get_files(self, rpath, recursive, **kwargs)
110+
_get_files(rpath, recursive, **kwargs)
100111

101-
@staticmethod
102112
def _databricks_open(self, path):
103-
if not self._databricks_exists(self, path):
113+
try:
114+
from databricks.sdk import WorkspaceClient
115+
except ModuleNotFoundError:
116+
raise PinsError(
117+
"Install the `databricks-sdk` package for Databricks board support."
118+
)
119+
120+
if not self._databricks_exists(path):
104121
raise PinsError("File or directory does not exist")
105122
w = WorkspaceClient()
106123
resp = w.files.download(path)
@@ -109,7 +126,6 @@ def _databricks_open(self, path):
109126
f.seek(0)
110127
return f
111128

112-
@staticmethod
113129
def _databricks_exists(self, path: str):
114130
if self._databricks_is_type(path) == "nothing":
115131
return False
@@ -118,6 +134,14 @@ def _databricks_exists(self, path: str):
118134

119135
@staticmethod
120136
def _databricks_is_type(path: str):
137+
try:
138+
from databricks.sdk import WorkspaceClient
139+
from databricks.sdk.errors import NotFound
140+
except ModuleNotFoundError:
141+
raise PinsError(
142+
"Install the `databricks-sdk` package for Databricks board support."
143+
)
144+
121145
w = WorkspaceClient()
122146
try:
123147
w.files.get_metadata(path)
@@ -131,9 +155,15 @@ def _databricks_is_type(path: str):
131155
else:
132156
return "file"
133157

134-
@staticmethod
135158
def _databricks_ls(self, path, detail):
136-
if not self._databricks_exists(self, path):
159+
try:
160+
from databricks.sdk import WorkspaceClient
161+
except ModuleNotFoundError:
162+
raise PinsError(
163+
"Install the `databricks-sdk` package for Databricks board support."
164+
)
165+
166+
if not self._databricks_exists(path):
137167
raise PinsError("File or directory does not exist")
138168
w = WorkspaceClient()
139169
if self._databricks_is_type(path) == "file":
@@ -159,22 +189,35 @@ def _databricks_ls(self, path, detail):
159189
items.append(item_path)
160190
return items
161191

162-
@staticmethod
163192
def _databricks_rm_dir(self, path):
193+
try:
194+
from databricks.sdk import WorkspaceClient
195+
except ModuleNotFoundError:
196+
raise PinsError(
197+
"Install the `databricks-sdk` package for Databricks board support."
198+
)
199+
164200
w = WorkspaceClient()
165201
raw_contents = w.files.list_directory_contents(path)
166202
contents = list(raw_contents)
167203
details = list(map(self._databricks_content_details, contents))
168204
for item in details:
169205
item_path = item.get("path")
170206
if item.get("is_directory"):
171-
self._databricks_rm_dir(self, item_path)
207+
self._databricks_rm_dir(item_path)
172208
else:
173209
w.files.delete(item_path)
174210
w.files.delete_directory(path)
175211

176212
@staticmethod
177213
def _databricks_mkdir(path):
214+
try:
215+
from databricks.sdk import WorkspaceClient
216+
except ModuleNotFoundError:
217+
raise PinsError(
218+
"Install the `databricks-sdk` package for Databricks board support."
219+
)
220+
178221
w = WorkspaceClient()
179222
w.files.create_directory(path)
180223

pins/tests/conftest.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
pytest.param(lambda: BoardBuilder("s3"), id="s3", marks=m.fs_s3),
2929
pytest.param(lambda: BoardBuilder("gcs"), id="gcs", marks=m.fs_gcs),
3030
pytest.param(lambda: BoardBuilder("abfs"), id="abfs", marks=m.fs_abfs),
31-
pytest.param(lambda: DbcBoardBuilder("dbc"), id="dbc", marks=m.fs_dbc)
31+
pytest.param(lambda: DbcBoardBuilder("dbc"), id="dbc", marks=m.fs_dbc),
3232
]
3333

3434
# rsc should only be used once, because users are created at docker setup time

pins/tests/helpers.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,11 @@
4040

4141
def skip_if_dbc(func):
4242
"""Decorator to skip test if board protocol is 'dbc'"""
43+
4344
@functools.wraps(func)
4445
def wrapper(*args, **kwargs):
4546
import inspect
47+
4648
board = None
4749

4850
# Get function signature to map args to parameter names.
@@ -52,21 +54,22 @@ def wrapper(*args, **kwargs):
5254
bound_args = sig.bind_partial(*args, **kwargs)
5355
all_args = {**bound_args.arguments, **kwargs}
5456

55-
if 'board' in all_args:
56-
board = all_args['board']
57-
elif 'board_with_cache' in all_args:
58-
board = all_args['board_with_cache']
57+
if "board" in all_args:
58+
board = all_args["board"]
59+
elif "board_with_cache" in all_args:
60+
board = all_args["board_with_cache"]
5961
else:
6062
# Check all arguments for something that looks like a board
6163
for arg_value in all_args.values():
62-
if hasattr(arg_value, 'fs') and hasattr(arg_value.fs, 'protocol'):
64+
if hasattr(arg_value, "fs") and hasattr(arg_value.fs, "protocol"):
6365
board = arg_value
6466
break
6567

6668
if board and board.fs.protocol == "dbc":
6769
pytest.skip("All Databricks tests must be read only")
6870

6971
return func(*args, **kwargs)
72+
7073
return wrapper
7174

7275

pins/tests/test_compat.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ def test_compat_pin_meta(board):
117117
elif board.fs.protocol == "dbc":
118118
assert meta.title == "df_csv: a pinned 3 x 2 DataFrame"
119119
assert meta.description is None
120-
assert meta.created == "20220214T163720Z"
120+
assert meta.created == "20250410T083026Z"
121121
assert meta.file == "df_csv.csv"
122122
assert meta.file_size == 16
123123
assert meta.pin_hash == "a173cd6a53908980"
@@ -186,7 +186,7 @@ def test_compat_pin_read(board):
186186

187187
# TODO: update when dbc boards are not read-only
188188
if board.fs.protocol == "dbc":
189-
dst_df = pd.DataFrame({'x': [1, 2, 3], 'y': [4, 5, 6]})
189+
dst_df = pd.DataFrame({"x": [1, 2, 3], "y": [4, 5, 6]})
190190
else:
191191
dst_df = pd.read_csv(p_data)
192192

pins/tests/test_constructors.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ def test_constructor_boards(board, df_csv, tmp_cache):
192192
# check data
193193
# TODO: update when dbc boards are not read-only
194194
if board.fs.protocol == "dbc":
195-
df_csv = pd.DataFrame({'x': [1, 2, 3], 'y': [4, 5, 6]})
195+
df_csv = pd.DataFrame({"x": [1, 2, 3], "y": [4, 5, 6]})
196196

197197
assert_frame_equal(df, df_csv)
198198

0 commit comments

Comments
 (0)