Skip to content

[Python] Fix UUID extension type round-trip to pandas returning bytes natively - #55

Draft
rok wants to merge 2 commits into
mainfrom
review/pr-50325-native-uuid
Draft

[Python] Fix UUID extension type round-trip to pandas returning bytes natively#55
rok wants to merge 2 commits into
mainfrom
review/pr-50325-native-uuid

Conversation

@rok

@rokrok commented Jul 21, 2026

Copy link
Copy Markdown
Owner

This is to discuss perhaps changing approach on apache#50325

@rokrok changed the title Review/pr 50325 native UUID[Python] Fix UUID extension type round-trip to pandas returning bytes nativelyJul 21, 2026
@github-actions
github-actionsBot marked this pull request as draft July 21, 2026 10:56
Repository owner deleted a comment from github-actionsBotJul 21, 2026
rok pushed a commit to apache/arrow that referenced this pull request Aug 18, 2026
…ning bytes (#50325)
### Rationale for this change
Converting a Table with an `arrow.uuid` extension column to pandas currently produces a column of `bytes` instead of `uuid.UUID` objects. Without a dedicated conversion path, `Table.to_pandas()` / `Array.to_pandas()` falls back to the storage type (`fixed_size_binary(16)`) and materializes raw bytes. Downstream callers (and tests such as those landing via pandas UUID Parquet coverage) expect `uuid.UUID` objects, matching what `to_pylist()` / `UuidScalar.as_py()` already return.
Note: the original issue suggested this might be specific to Python 3.14, but the same `bytes` result reproduces on Python 3.10-3.14 with current PyArrow - `UuidType` never had a pandas conversion path.
Closes#50312
### What changes are included in this PR?
Convert UUID extension arrays to `uuid.UUID` objects in the C++ pandas conversion path (integrated from @ rok's proposal in rok#55), rather than relying on a Python `to_pandas_dtype()` / `__from_arrow__` compat layer:
- Construct `uuid.UUID` objects from storage bytes in `helpers.cc` (`UuidFromBytes`) and use that from `arrow_to_pandas.cc`
- Reuse empty kwargs / shared empty tuple constants so conversion does not allocate per element
- Keep `to_numpy(zero_copy_only=False)` on UUID extension arrays returning storage `bytes` (extension to NumPy should follow storage type)
- Add/extend regression tests for pandas round-trip and NumPy behavior
### Are these changes tested?
Yes.
Acceptance criteria:
- [x] Tests added for the UUID to pandas round-trip (and NumPy storage behavior)
- [x] Relevant local / CI Python tests passing for the touched paths
- [x] Follows project style / review feedback (lint fix included)
- [x] No intentional breaking public API change beyond correcting incorrect `bytes` return values to `uuid.UUID` for `to_pandas()`
Before / after evidence (backend; console):
```text
# Before (repro on Python 3.10-3.14 with unfixed PyArrow)
>>> type(result_df.loc[0, "id"])
<class 'bytes'>
# After (with this PR)
>>> type(result_df.loc[0, "id"])
<class 'uuid.UUID'>
```
Also covered by added unit tests in `python/pyarrow/tests/parquet/test_data_types.py` and `python/pyarrow/tests/test_extension_type.py`.
### Are there any user-facing changes?
Yes. `Table.to_pandas()` / `Array.to_pandas()` now returns `uuid.UUID` for `arrow.uuid` columns instead of `bytes`. `to_numpy(zero_copy_only=False)` continues to expose storage `bytes`.
* GitHub Issue: #50312
Authored-by: parker-cassar <parker.cassar@berkeley.edu>
Signed-off-by: Rok Mihevc <rok@mihevc.org>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@rok@parker-cassar