9191)
9292
9393
94+ def _is_arrow_string_type(pa, pa_type) -> bool:
95+ """True for any Arrow string-like type, including the view-based layout.
96+
97+ ``string_view`` (Arrow's variable-length view layout, e.g. Polars'
98+ default export type for string columns via the PyCapsule interface) is
99+ not one of ``string``/``large_string``/``utf8``/``large_utf8`` but is
100+ handled identically everywhere those are.
101+ """
102+ if pa_type in (pa.string(), pa.large_string(), pa.utf8(), pa.large_utf8()):
103+ return True
104+ is_string_view = getattr(pa.types, "is_string_view", None)
105+ return bool(is_string_view is not None and is_string_view(pa_type))
106+
107+
108+ def _is_arrow_binary_type(pa, pa_type) -> bool:
109+ """True for any Arrow binary-like type, including the view-based layout."""
110+ if pa.types.is_binary(pa_type) or pa.types.is_large_binary(pa_type):
111+ return True
112+ is_binary_view = getattr(pa.types, "is_binary_view", None)
113+ return bool(is_binary_view is not None and is_binary_view(pa_type))
114+
115+
94116@dataclass(frozen=True)
95117class NullPolicy:
96118 """Default sentinels for inferred CTable scalar nulls.
@@ -165,9 +187,9 @@ def sentinel_for_arrow_type(self, pa, pa_type):
165187 return self.float_value
166188 if pa_type == pa.bool_():
167189 return self.bool_value
168- if pa_type in (pa.string(), pa.large_string(), pa.utf8(), pa.large_utf8() ):
190+ if _is_arrow_string_type (pa, pa_type ):
169191 return self.string_value
170- if pa.types.is_binary(pa_type) or pa.types.is_large_binary( pa_type):
192+ if _is_arrow_binary_type(pa, pa_type):
171193 return self.bytes_value
172194 if pa.types.is_timestamp(pa_type):
173195 return self.timestamp_value
@@ -6844,7 +6866,9 @@ def _arrow_type_needs_object_fallback(pa, pa_type) -> bool:
68446866 """True when *pa_type* has no typed CTable mapping."""
68456867 if pa.types.is_dictionary(pa_type):
68466868 vt = pa_type.value_type
6847- return vt not in (pa.string(), pa.large_string(), pa.utf8(), pa.large_utf8())
6869+ return not _is_arrow_string_type(pa, vt)
6870+ if _is_arrow_string_type(pa, pa_type):
6871+ return False
68486872 if pa_type in (
68496873 pa.int8(),
68506874 pa.int16(),
@@ -6857,13 +6881,9 @@ def _arrow_type_needs_object_fallback(pa, pa_type) -> bool:
68576881 pa.float32(),
68586882 pa.float64(),
68596883 pa.bool_(),
6860- pa.string(),
6861- pa.large_string(),
6862- pa.utf8(),
6863- pa.large_utf8(),
68646884 ):
68656885 return False
6866- if pa.types.is_binary(pa_type) or pa.types.is_large_binary( pa_type):
6886+ if _is_arrow_binary_type(pa, pa_type):
68676887 return False
68686888 if pa.types.is_timestamp(pa_type):
68696889 return False
@@ -6915,7 +6935,7 @@ def _arrow_type_to_spec( # noqa: C901
69156935
69166936 if pa.types.is_dictionary(pa_type):
69176937 vt = pa_type.value_type
6918- if vt in (pa.string(), pa.large_string(), pa.utf8(), pa.large_utf8() ):
6938+ if _is_arrow_string_type (pa, vt ):
69196939 index_type = pa_type.index_type
69206940 # Accept signed and unsigned integer index types; validate fit in int32.
69216941 if not (pa.types.is_integer(index_type) or pa.types.is_unsigned_integer(index_type)):
@@ -6988,7 +7008,7 @@ def _arrow_type_to_spec( # noqa: C901
69887008 item_arrow_col = None
69897009 nullable = True
69907010 item_string_max_length = string_max_length
6991- if pa_type.value_type in (pa.string(), pa.large_string(), pa.utf8(), pa.large_utf8() ):
7011+ if _is_arrow_string_type (pa, pa_type.value_type ):
69927012 item_string_max_length = max(string_max_length or 1, 1_000_000)
69937013 item_spec = CTable._arrow_type_to_spec(
69947014 pa,
@@ -7009,7 +7029,7 @@ def _arrow_type_to_spec( # noqa: C901
70097029 )
70107030 child_col = combined.field(field.name)
70117031 child_string_max_length = string_max_length
7012- if field.type in (pa.string(), pa.large_string(), pa.utf8(), pa.large_utf8() ):
7032+ if _is_arrow_string_type (pa, field.type ):
70137033 child_string_max_length = max(string_max_length or 1, 1_000_000)
70147034 fields[field.name] = CTable._arrow_type_to_spec(
70157035 pa,
@@ -7021,7 +7041,7 @@ def _arrow_type_to_spec( # noqa: C901
70217041 )
70227042 return b2s.struct(fields, nullable=nullable)
70237043
7024- if pa_type in (pa.string(), pa.large_string(), pa.utf8(), pa.large_utf8() ):
7044+ if _is_arrow_string_type (pa, pa_type ):
70257045 if string_max_length is None:
70267046 from blosc2.utf8_array import have_string_dtype
70277047
@@ -7036,7 +7056,7 @@ def _arrow_type_to_spec( # noqa: C901
70367056 max_length = max(string_max_length, len(null_value) if null_value is not None else 1, 1)
70377057 return b2s.string(max_length=max_length, null_value=null_value)
70387058
7039- if pa.types.is_binary(pa_type) or pa.types.is_large_binary( pa_type):
7059+ if _is_arrow_binary_type(pa, pa_type):
70407060 if string_max_length is None:
70417061 # No fixed-width threshold given: store as variable-length scalar bytes.
70427062 return b2s.vlbytes(nullable=nullable)
@@ -7102,12 +7122,8 @@ def _compiled_columns_from_arrow(
71027122 and not field_is_dictionary
71037123 and column_string_max_length is None
71047124 and (
7105- pa.types.is_binary(field.type)
7106- or pa.types.is_large_binary(field.type)
7107- or (
7108- not have_string_dtype()
7109- and (pa.types.is_string(field.type) or pa.types.is_large_string(field.type))
7110- )
7125+ _is_arrow_binary_type(pa, field.type)
7126+ or (not have_string_dtype() and _is_arrow_string_type(pa, field.type))
71117127 )
71127128 )
71137129 field_needs_object_fallback = cls._arrow_type_needs_object_fallback(pa, field.type)
0 commit comments