Skip to content

Commit d119a79

Browse files
Preserve transfer filenames when the OS error code is absent
Signed-off-by: Aakash Saravanan <aakash.saravanan@databricks.com>
1 parent a90f623 commit d119a79

2 files changed

Lines changed: 15 additions & 9 deletions

File tree

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

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@
1616
raw to connector callers. Wrapped in
1717
``OperationalError`` here.
1818
19-
Local missing transfer files use the built-in ``FileNotFoundError`` class;
20-
the original OS error code and requested local filename are preserved
21-
when available.
19+
Local transfer failures use built-in ``OSError`` classes, including
20+
``FileNotFoundError``, ``PermissionError`` and other platform subclasses.
21+
The original OS error code and requested filename are preserved when available.
2222
2323
These primitives live in their own module so both ``client.py``
2424
(which orchestrates PyO3 calls) and ``result_set.py`` (which calls
@@ -126,8 +126,9 @@ def reraise_kernel_error(
126126
) -> "Union[Error, OSError]":
127127
"""Map a kernel error and forward its structured attributes.
128128
129-
Local missing files use ``FileNotFoundError``; filesystem permission
130-
failures use ``PermissionError``. Other errors use PEP 249 classes.
129+
Local transfer failures use built-in ``OSError`` classes, including
130+
missing-file, permission, directory and disk-full errors. Non-local
131+
errors use PEP 249 classes.
131132
132133
The returned exception is raised by callers with ``raise ... from
133134
exc``; the ``from`` clause is what sets ``__cause__``, so we don't
@@ -169,7 +170,11 @@ def reraise_kernel_error(
169170
os_error_filename = getattr(exc, "os_error_filename", None)
170171
file_error_args: tuple
171172
if os_error_code is None:
172-
file_error_args = (message,)
173+
file_error_args = (
174+
(None, message, os_error_filename)
175+
if os_error_filename is not None
176+
else (message,)
177+
)
173178
elif os.name == "nt":
174179
file_error_args = (0, message, os_error_filename, os_error_code)
175180
else:
@@ -221,8 +226,8 @@ def wrap_kernel_exception(what: str, exc: BaseException) -> "Union[Error, OSErro
221226
"""Map a PyO3 exception to the connector's public error contract.
222227
223228
- ``KernelError`` → mapped class with structured attrs forwarded.
224-
A local missing transfer file maps to ``FileNotFoundError`` with
225-
its original OS error code and requested filename when available.
229+
Local transfer failures map to built-in ``OSError`` classes with
230+
their original OS error code and requested filename when available.
226231
- Already-mapped PEP 249 or local transfer errors → passed through
227232
unchanged so nested callers preserve their class and attributes.
228233
- Anything else (``TypeError`` / ``ValueError`` / etc. from PyO3

‎tests/unit/test_kernel_client.py‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2762,14 +2762,15 @@ def test_file_transfer_error_matches_thrift_exception(
27622762
error = _FakeKernelError(code=code, message="File transfer failed")
27632763
error.error_code = error_code
27642764
error.http_status = http_status
2765+
error.os_error_filename = "local-file.bin"
27652766
result = kernel_client._reraise_kernel_error(error)
27662767
assert type(result) is expected
27672768
assert result.error_code == error_code
27682769
assert result.code == code
27692770
assert result.http_status == http_status
27702771
if issubclass(expected, OSError):
27712772
assert result.errno is None
2772-
assert result.filename is None
2773+
assert result.filename == "local-file.bin"
27732774

27742775

27752776
@pytest.mark.parametrize(

0 commit comments

Comments
 (0)