Skip to content

Commit e3806ee

Browse files
fix(kernel): preserve all local OS transfer errors
Signed-off-by: Aakash Saravanan <aakash.saravanan@databricks.com>
1 parent 993fe73 commit e3806ee

2 files changed

Lines changed: 32 additions & 12 deletions

File tree

‎src/databricks/sql/backend/kernel/_errors.py‎

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,12 @@ def reraise_kernel_error(
174174
new: Union[Error, OSError]
175175
# Local missing files have no HTTP status; remote missing files carry 404.
176176
if (
177+
file_transfer
178+
and os_error_code is not None
179+
and getattr(exc, "http_status", None) is None
180+
):
181+
new = OSError(*file_error_args)
182+
elif (
177183
error_code == "FILE_TRANSFER_PERMISSION_ERROR"
178184
and getattr(exc, "http_status", None) is None
179185
):
@@ -228,9 +234,10 @@ def wrap_kernel_exception(what: str, exc: BaseException) -> "Union[Error, OSErro
228234
return reraise_kernel_error(exc)
229235
if isinstance(exc, Error):
230236
return exc
231-
if isinstance(exc, (FileNotFoundError, PermissionError)) and getattr(
232-
exc, "error_code", None
233-
) in ("FILE_TRANSFER_ERROR", "FILE_TRANSFER_PERMISSION_ERROR"):
237+
if isinstance(exc, OSError) and getattr(exc, "error_code", None) in (
238+
"FILE_TRANSFER_ERROR",
239+
"FILE_TRANSFER_PERMISSION_ERROR",
240+
):
234241
return exc
235242
return OperationalError(
236243
f"Unexpected error from databricks_sql_kernel during {what}: {exc!r}"

‎tests/unit/test_kernel_client.py‎

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2760,28 +2760,37 @@ def test_file_transfer_error_matches_thrift_exception(
27602760

27612761

27622762
@pytest.mark.parametrize(
2763-
"code,error_code,raw,expected",
2763+
"code,error_code,raw,windows_raw,expected",
27642764
[
2765-
("NotFound", "FILE_TRANSFER_ERROR", errno.ENOENT, FileNotFoundError),
2765+
("NotFound", "FILE_TRANSFER_ERROR", errno.ENOENT, 2, FileNotFoundError),
27662766
(
27672767
"PermissionDenied",
27682768
"FILE_TRANSFER_PERMISSION_ERROR",
27692769
errno.EACCES,
2770+
5,
27702771
PermissionError,
27712772
),
27722773
(
27732774
"PermissionDenied",
27742775
"FILE_TRANSFER_PERMISSION_ERROR",
27752776
errno.EPERM,
2777+
5,
27762778
PermissionError,
27772779
),
2780+
("Internal", "FILE_TRANSFER_ERROR", errno.ENOTDIR, 267, NotADirectoryError),
2781+
("Internal", "FILE_TRANSFER_ERROR", errno.EISDIR, 5, IsADirectoryError),
2782+
("ResourceExhausted", "FILE_TRANSFER_ERROR", errno.ENOSPC, 112, OSError),
27782783
],
27792784
)
2780-
def test_local_transfer_error_preserves_os_code(code, error_code, raw, expected):
2785+
def test_local_transfer_error_preserves_os_code(
2786+
code, error_code, raw, windows_raw, expected
2787+
):
27812788
error = _FakeKernelError(code=code, message="File transfer failed")
27822789
error.error_code = error_code
27832790
if os.name == "nt":
2784-
raw = 2 if expected is FileNotFoundError else 5
2791+
raw = windows_raw
2792+
if expected is IsADirectoryError:
2793+
expected = PermissionError
27852794
error.os_error_code = raw
27862795
error.os_error_filename = "local-file.bin"
27872796
result = kernel_client._reraise_kernel_error(error)
@@ -2790,24 +2799,28 @@ def test_local_transfer_error_preserves_os_code(code, error_code, raw, expected)
27902799
assert result.filename == "local-file.bin"
27912800
if os.name == "nt":
27922801
assert result.winerror == raw
2793-
assert result.errno == (errno.ENOENT if raw == 2 else errno.EACCES)
2802+
assert result.errno == OSError(0, "", None, raw).errno
27942803
else:
27952804
assert result.errno == raw
27962805

27972806

27982807
@pytest.mark.parametrize(
2799-
"code,error_code",
2808+
"code,error_code,raw",
28002809
[
2801-
("NotFound", "FILE_TRANSFER_ERROR"),
2802-
("PermissionDenied", "FILE_TRANSFER_PERMISSION_ERROR"),
2810+
("NotFound", "FILE_TRANSFER_ERROR", None),
2811+
("PermissionDenied", "FILE_TRANSFER_PERMISSION_ERROR", None),
2812+
("Internal", "FILE_TRANSFER_ERROR", errno.ENOTDIR),
2813+
("ResourceExhausted", "FILE_TRANSFER_ERROR", errno.ENOSPC),
28032814
],
28042815
)
2805-
def test_nested_wrapping_preserves_mapped_local_transfer_error(code, error_code):
2816+
def test_nested_wrapping_preserves_mapped_local_transfer_error(code, error_code, raw):
28062817
from databricks.sql.backend.kernel._errors import wrap_kernel_exception
28072818

28082819
error = _FakeKernelError(code=code, sql_state="HY000", query_id="transfer-id")
28092820
error.error_code = error_code
2821+
error.os_error_code = raw
28102822
mapped = wrap_kernel_exception("inner", error)
2823+
assert isinstance(mapped, OSError)
28112824
wrapped = wrap_kernel_exception("outer", mapped)
28122825
assert wrapped is mapped
28132826
assert wrapped.code == code

0 commit comments

Comments
 (0)