Skip to content

GH-48470: [Python] Construct UuidArray from list of UuidScalars - #48746

Merged
rok merged 9 commits into
apache:mainfrom
tadeja:48470-extension-scalar
Mar 18, 2026
Merged

GH-48470: [Python] Construct UuidArray from list of UuidScalars#48746
rok merged 9 commits into
apache:mainfrom
tadeja:48470-extension-scalar

Conversation

@tadeja

@tadejatadeja commented Jan 6, 2026

Copy link
Copy Markdown
Member

Rationale for this change

Fixes#48470. Also fixes all extension types, not just UUID.

What changes are included in this PR?

An extension scalar is unwrapped to its storage type when building arrays.

Are these changes tested?

Yes, new test_array_from_extension_scalars covers builtin (uuid, bool8, json_, opaque) and custom types across all storage types (int, float, bool, string, binary, large string/binary, decimal, fixed-size binary, struct, timestamp, duration, date).

Are there any user-facing changes?

Now user can run such an example to get the output below instead of ArrowInvalid message.
This now works for any extension type, not just UUID.

importpyarrowaspapa.array([pa.scalar(b'1'*16, type=pa.uuid())], type=pa.uuid())
<pyarrow.lib.UuidArray object at 0x128186970>
[
31313131313131313131313131313131
]

@github-actions

Copy link
Copy Markdown

⚠️ GitHub issue #48470has been automatically assigned in GitHub to PR creator.

@tadeja
tadejaforce-pushed the 48470-extension-scalar branch from 043c8a8 to dbf1194CompareMarch 4, 2026 19:25
@tadeja
tadeja marked this pull request as ready for review March 4, 2026 19:43

@rokrok left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good. Some minor change and more extensive tests suggestions.

Comment on lines +587 to +594
// Helper function to unwrap extension scalar to its storage scalar
const Scalar& GetStorageScalar(const Scalar& scalar) {
if (scalar.type->id() == Type::EXTENSION) {
return *checked_cast<const ExtensionScalar&>(scalar).value;
}
return scalar;
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about using Result here?

Suggested change
// Helper function to unwrap extension scalar to its storage scalar
const Scalar& GetStorageScalar(const Scalar& scalar) {
if (scalar.type->id() == Type::EXTENSION) {
return *checked_cast<const ExtensionScalar&>(scalar).value;
}
return scalar;
}
// Helper function to unwrap extension scalar to its storage scalar
Result<const Scalar*> GetStorageScalar(const Scalar& scalar) {
if (scalar.type->id() != Type::EXTENSION) {
return &scalar;
}
constauto& extension_scalar = checked_cast<const ExtensionScalar&>(scalar);
return extension_scalar.value.get();
}

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps Result is not needed here - if its kind of failure path is unlikely then const Scalar& might be better?
Looking at the line 757 check if (PyValue::IsNull(this->options_, value)) { ...
( For an (unlikely?) non-None extension scalar with internal storage .value of a null shared_ptr both approaches don't avoid it? )

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Result is probably not needed indeed, since no error can be returned here. As you prefer @tadeja.

Comment threadpython/pyarrow/src/arrow/python/python_to_arrow.cc
Comment threadpython/pyarrow/tests/test_extension_type.py
Comment threadpython/pyarrow/tests/test_extension_type.py
@github-actionsgithub-actionsBot added awaiting changes Awaiting changes and removed awaiting review Awaiting review labels Mar 5, 2026
Co-authored-by: Rok Mihevc <rok@mihevc.org>
@github-actionsgithub-actionsBot added awaiting change review Awaiting change review and removed awaiting changes Awaiting changes labels Mar 11, 2026
@tadeja
tadejaforce-pushed the 48470-extension-scalar branch from a38cfda to 483e866CompareMarch 11, 2026 19:28
@tadeja
tadeja requested a review from rokMarch 17, 2026 17:13
@tadeja

Copy link
Copy Markdown
MemberAuthor

For the C++ part of changes, @pitrou would you have a chance to take a look?

rok
rok approved these changes Mar 17, 2026
@github-actionsgithub-actionsBot added awaiting merge Awaiting merge and removed awaiting change review Awaiting change review labels Mar 17, 2026


def test_array_from_extension_scalars():
import datetime

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can move this stdlib import to the top of file.

@pitroupitrou left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Neat @tadeja ! Just minor suggestions below.

rok
rok approved these changes Mar 18, 2026
@rok
rok merged commit d08d5e6 into apache:mainMar 18, 2026
17 checks passed
@rokrok removed the awaiting merge Awaiting merge label Mar 18, 2026
@rok

rok commented Mar 18, 2026

Copy link
Copy Markdown
Member

Thanks for sanity check @pitrou! Merging.

@conbench-apache-arrow

Copy link
Copy Markdown

After merging your PR, Conbench analyzed the 3 benchmarking runs that have been run so far on merge-commit d08d5e6.

There were no benchmark performance regressions. 🎉

The full Conbench report has more details.

thisisnic pushed a commit to thisisnic/arrow that referenced this pull request Apr 6, 2026
…apache#48746)
### Rationale for this change
Fixesapache#48470. Also fixes all extension types, not just UUID.
### What changes are included in this PR?
An extension scalar is unwrapped to its storage type when building arrays.
### Are these changes tested?
Yes, new `test_array_from_extension_scalars` covers builtin (uuid, bool8, json_, opaque) and custom types across all storage types (int, float, bool, string, binary, large string/binary, decimal, fixed-size binary, struct, timestamp, duration, date).
### Are there any user-facing changes?
Now user can run such an example to get the output below instead of `ArrowInvalid` message.
This now works for any extension type, not just UUID.
```python
import pyarrow as pa
pa.array([pa.scalar(b'1'*16, type=pa.uuid())], type=pa.uuid())
``` ```
<pyarrow.lib.UuidArray object at 0x128186970>
[
31313131313131313131313131313131
]
```
* GitHub Issue: apache#48470
Lead-authored-by: Tadeja Kadunc <tadeja.kadunc@gmail.com>
Co-authored-by: tadeja <tadeja@users.noreply.github.com>
Co-authored-by: Rok Mihevc <rok@mihevc.org>
Signed-off-by: Rok Mihevc <rok@mihevc.org>
@tadeja
tadeja deleted the 48470-extension-scalar branch April 9, 2026 12:13
Mottl pushed a commit to Mottl/arrow that referenced this pull request May 26, 2026
…apache#48746)
### Rationale for this change
Fixesapache#48470. Also fixes all extension types, not just UUID.
### What changes are included in this PR?
An extension scalar is unwrapped to its storage type when building arrays.
### Are these changes tested?
Yes, new `test_array_from_extension_scalars` covers builtin (uuid, bool8, json_, opaque) and custom types across all storage types (int, float, bool, string, binary, large string/binary, decimal, fixed-size binary, struct, timestamp, duration, date).
### Are there any user-facing changes?
Now user can run such an example to get the output below instead of `ArrowInvalid` message.
This now works for any extension type, not just UUID.
```python
import pyarrow as pa
pa.array([pa.scalar(b'1'*16, type=pa.uuid())], type=pa.uuid())
``` ```
<pyarrow.lib.UuidArray object at 0x128186970>
[
31313131313131313131313131313131
]
```
* GitHub Issue: apache#48470
Lead-authored-by: Tadeja Kadunc <tadeja.kadunc@gmail.com>
Co-authored-by: tadeja <tadeja@users.noreply.github.com>
Co-authored-by: Rok Mihevc <rok@mihevc.org>
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.

[Python] Cannot construct UuidArray from list of UuidScalars

3 participants

@tadeja@rok@pitrou