Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
3d85931
Add __int__ methods
thisisnic Mar 17, 2025
3a12d51
Make changes more compact
thisisnic Mar 17, 2025
ad9de3c
Remove redundant docs
thisisnic Mar 17, 2025
60a613b
linter fixes
thisisnic Mar 17, 2025
a08a92a
Add test for __int__
thisisnic Mar 30, 2025
690a978
Remove redundant spacing
thisisnic Mar 30, 2025
776c9d7
Add floats and tests
thisisnic Mar 30, 2025
c3e3da5
Add bytes()
thisisnic Mar 30, 2025
b929e27
Run linter
thisisnic Mar 31, 2025
30af8c0
Implement bool dunder for booleans
thisisnic Mar 31, 2025
376063c
Add tests for boolean input
thisisnic Mar 31, 2025
8b0d08b
Add buffer dunder
thisisnic Apr 8, 2025
b42c6ef
Try using __getbuffer__()
thisisnic Apr 14, 2025
80e7822
Rename method __buffer__ to __getbuffer__
thisisnic Apr 14, 2025
7b87ed5
Try passing through params
thisisnic Apr 14, 2025
519eb4b
Try getting buffer first
thisisnic Apr 14, 2025
9af4764
Try with PyObject_GetBuffer
thisisnic Apr 14, 2025
53939b6
Create new buffer properties from scratch
thisisnic Apr 15, 2025
0492dd8
Remove extra whitespace
thisisnic Apr 15, 2025
c71fcee
Update python/pyarrow/scalar.pxi
thisisnic Apr 15, 2025
5435c3e
Add more specific tests for memview object
thisisnic Apr 17, 2025
5947541
Implement mapping for Map types
thisisnic Apr 17, 2025
2f4550a
Explicitly test that StructScalars implement sequences
thisisnic Apr 17, 2025
b049141
Add test for struct unpacking
thisisnic Apr 18, 2025
7f73e79
Document extracting values from StructScalars and revert test
thisisnic Apr 23, 2025
c08ef65
Appease linter, add back in deleted test
thisisnic Apr 23, 2025
390de50
Appease another linter
thisisnic Apr 23, 2025
d62ced1
Update docs/source/python/compute.rst
thisisnic Apr 28, 2025
4de77b7
Add failure for rtrieving buffer if none exists, remove duplicated co…
thisisnic Apr 28, 2025
e3ff08b
Add tests for if objects are sequence-like or mapping-like
thisisnic Apr 28, 2025
796f1f1
Update python/pyarrow/scalar.pxi
thisisnic May 2, 2025
46dbfe1
Parameterise tests for NULL binary objects
thisisnic May 6, 2025
1456801
Simplify buffer creation
thisisnic May 6, 2025
42e3859
Add test for empty string
thisisnic May 6, 2025
20e8add
Use keys to implement __getitem__ for MapScalar
thisisnic May 13, 2025
1581930
Inherit from sequence and mapping classes
thisisnic May 13, 2025
a89815b
Import Sequence and Mapping so can use class names for imports
thisisnic May 15, 2025
2312280
Update python/pyarrow/scalar.pxi
thisisnic May 21, 2025
b59b579
Remove unnecessary parentheses
thisisnic May 21, 2025
0727fec
Raise KeyError not ValueError
thisisnic May 21, 2025
7cafd65
Check buf is None on empty value test
thisisnic May 21, 2025
cc89ada
Different code paths for dereferencing MapScalars by index or key
thisisnic May 21, 2025
6b5e941
Update mappings to return value when provided a key
thisisnic May 21, 2025
caa9b23
__int__ -> __index__
thisisnic May 22, 2025
f5ff26d
Define __int__ for floats
thisisnic May 22, 2025
f7d9083
use numpy float
thisisnic May 22, 2025
b6a2f7d
Update halffloat __int__ to account for numpy float
thisisnic May 22, 2025
18d3af6
Don't test is numpy float
thisisnic May 22, 2025
5d451ad
Update bool method to return False not None if scalar is None
thisisnic May 27, 2025
2938a55
Revert changes which overrode rebased content
thisisnic Jun 9, 2025
032dd85
Revert halffloat change that was missed
thisisnic Jun 9, 2025
02872d4
Update python/pyarrow/tests/test_scalars.py
thisisnic Jun 9, 2025
c21e7ee
Fix number in test
thisisnic Jun 9, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions docs/source/python/compute.rst
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,21 @@ Below are a few simple examples::
>>> pc.multiply(x, y)
<pyarrow.DoubleScalar: 72.54>

If you are using a compute function which returns more than one value, results
will be returned as a ``StructScalar``. You can extract the individual values by
calling the :meth:`pyarrow.StructScalar.values` method::

>>> import pyarrow as pa
>>> import pyarrow.compute as pc
>>> a = pa.array([1, 1, 2, 3])
>>> pc.min_max(a)
<pyarrow.StructScalar: [('min', 1), ('max', 3)]>
>>> a, b = pc.min_max(a).values()
>>> a
<pyarrow.Int64Scalar: 1>
>>> b
<pyarrow.Int64Scalar: 3>

These functions can do more than just element-by-element operations.
Here is an example of sorting a table::

Expand Down
90 changes: 84 additions & 6 deletions python/pyarrow/scalar.pxi
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import collections
import warnings
from uuid import UUID
from collections.abc import Sequence, Mapping


cdef class Scalar(_Weakrefable):
Expand Down Expand Up @@ -219,6 +220,8 @@ cdef class BooleanScalar(Scalar):
cdef CBooleanScalar* sp = <CBooleanScalar*> self.wrapped.get()
return sp.value if sp.is_valid else None

def __bool__(self):
return self.as_py() or False

cdef class UInt8Scalar(Scalar):
"""
Expand All @@ -238,6 +241,9 @@ cdef class UInt8Scalar(Scalar):
cdef CUInt8Scalar* sp = <CUInt8Scalar*> self.wrapped.get()
return sp.value if sp.is_valid else None

def __index__(self):
return self.as_py()


cdef class Int8Scalar(Scalar):
"""
Expand All @@ -257,6 +263,9 @@ cdef class Int8Scalar(Scalar):
cdef CInt8Scalar* sp = <CInt8Scalar*> self.wrapped.get()
return sp.value if sp.is_valid else None

def __index__(self):
return self.as_py()


cdef class UInt16Scalar(Scalar):
"""
Expand All @@ -276,6 +285,9 @@ cdef class UInt16Scalar(Scalar):
cdef CUInt16Scalar* sp = <CUInt16Scalar*> self.wrapped.get()
return sp.value if sp.is_valid else None

def __index__(self):
return self.as_py()


cdef class Int16Scalar(Scalar):
"""
Expand All @@ -295,6 +307,9 @@ cdef class Int16Scalar(Scalar):
cdef CInt16Scalar* sp = <CInt16Scalar*> self.wrapped.get()
return sp.value if sp.is_valid else None

def __index__(self):
return self.as_py()


cdef class UInt32Scalar(Scalar):
"""
Expand All @@ -314,6 +329,9 @@ cdef class UInt32Scalar(Scalar):
cdef CUInt32Scalar* sp = <CUInt32Scalar*> self.wrapped.get()
return sp.value if sp.is_valid else None

def __index__(self):
return self.as_py()


cdef class Int32Scalar(Scalar):
"""
Expand All @@ -333,6 +351,9 @@ cdef class Int32Scalar(Scalar):
cdef CInt32Scalar* sp = <CInt32Scalar*> self.wrapped.get()
return sp.value if sp.is_valid else None

def __index__(self):
return self.as_py()


cdef class UInt64Scalar(Scalar):
"""
Expand All @@ -352,6 +373,9 @@ cdef class UInt64Scalar(Scalar):
cdef CUInt64Scalar* sp = <CUInt64Scalar*> self.wrapped.get()
return sp.value if sp.is_valid else None

def __index__(self):
return self.as_py()


cdef class Int64Scalar(Scalar):
"""
Expand All @@ -371,6 +395,9 @@ cdef class Int64Scalar(Scalar):
cdef CInt64Scalar* sp = <CInt64Scalar*> self.wrapped.get()
return sp.value if sp.is_valid else None

def __index__(self):
return self.as_py()


cdef class HalfFloatScalar(Scalar):
"""
Expand All @@ -390,6 +417,12 @@ cdef class HalfFloatScalar(Scalar):
cdef CHalfFloatScalar* sp = <CHalfFloatScalar*> self.wrapped.get()
return PyFloat_FromHalf(sp.value) if sp.is_valid else None

def __float__(self):
return self.as_py()

def __int__(self):
return int(self.as_py())


cdef class FloatScalar(Scalar):
"""
Expand All @@ -409,6 +442,12 @@ cdef class FloatScalar(Scalar):
cdef CFloatScalar* sp = <CFloatScalar*> self.wrapped.get()
return sp.value if sp.is_valid else None

def __float__(self):
return self.as_py()

def __int__(self):
return int(float(self))


cdef class DoubleScalar(Scalar):
"""
Expand All @@ -428,6 +467,12 @@ cdef class DoubleScalar(Scalar):
cdef CDoubleScalar* sp = <CDoubleScalar*> self.wrapped.get()
return sp.value if sp.is_valid else None

def __float__(self):
return self.as_py()

def __int__(self):
return int(float(self))


cdef class Decimal32Scalar(Scalar):
"""
Expand Down Expand Up @@ -843,6 +888,15 @@ cdef class BinaryScalar(Scalar):
buffer = self.as_buffer()
return None if buffer is None else buffer.to_pybytes()

def __bytes__(self):
return self.as_py()

def __getbuffer__(self, cp.Py_buffer* buffer, int flags):
buf = self.as_buffer()
if buf is None:
raise ValueError("Cannot export buffer from null Arrow Scalar")
cp.PyObject_GetBuffer(buf, buffer, flags)


cdef class LargeBinaryScalar(BinaryScalar):
pass
Expand Down Expand Up @@ -883,7 +937,7 @@ cdef class StringViewScalar(StringScalar):
pass


cdef class ListScalar(Scalar):
cdef class ListScalar(Scalar, Sequence):
"""
Concrete class for list-like scalars.
"""
Expand Down Expand Up @@ -952,7 +1006,7 @@ cdef class LargeListViewScalar(ListScalar):
pass


cdef class StructScalar(Scalar, collections.abc.Mapping):
cdef class StructScalar(Scalar, Mapping):
"""
Concrete class for struct scalars.
"""
Expand Down Expand Up @@ -1051,20 +1105,34 @@ cdef class StructScalar(Scalar, collections.abc.Mapping):
return str(self._as_py_tuple())


cdef class MapScalar(ListScalar):
cdef class MapScalar(ListScalar, Mapping):
"""
Concrete class for map scalars.
"""

def __getitem__(self, i):
"""
Return the value at the given index.
Return the value at the given index or key.
"""

arr = self.values
if arr is None:
raise IndexError(i)
raise IndexError(i) if isinstance(i, int) else KeyError(i)

key_field = self.type.key_field.name
item_field = self.type.item_field.name

if isinstance(i, (bytes, str)):
try:
key_index = list(self.keys()).index(i)
except ValueError:
raise KeyError(i)

dct = arr[_normalize_index(key_index, len(arr))]
return dct[item_field]

dct = arr[_normalize_index(i, len(arr))]
return (dct[self.type.key_field.name], dct[self.type.item_field.name])
return (dct[key_field], dct[item_field])

def __iter__(self):
"""
Expand Down Expand Up @@ -1118,6 +1186,16 @@ cdef class MapScalar(ListScalar):
result_dict[key] = value
return result_dict

def keys(self):
"""
Return the keys of the map as a list.
"""
arr = self.values
if arr is None:
return []
key_field = self.type.key_field.name
return [k.as_py() for k in arr.field(key_field)]


cdef class DictionaryScalar(Scalar):
"""
Expand Down
Loading
Loading