geoarrow-pyarrow 0.1.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,127 @@
1
+ """
2
+ Contains pyarrow integration for the geoarrow Python bindings.
3
+
4
+ Examples
5
+ --------
6
+
7
+ >>> import geoarrow.pyarrow as ga
8
+ """
9
+
10
+ from geoarrow.c.lib import GeometryType, Dimensions, CoordType, EdgeType, CrsType
11
+
12
+ from geoarrow.pyarrow._type import (
13
+ GeometryExtensionType,
14
+ WktType,
15
+ WkbType,
16
+ PointType,
17
+ LinestringType,
18
+ PolygonType,
19
+ MultiPointType,
20
+ MultiLinestringType,
21
+ MultiPolygonType,
22
+ wkb,
23
+ large_wkb,
24
+ wkt,
25
+ large_wkt,
26
+ point,
27
+ linestring,
28
+ polygon,
29
+ multipoint,
30
+ multilinestring,
31
+ multipolygon,
32
+ extension_type,
33
+ geometry_type_common,
34
+ register_extension_types,
35
+ unregister_extension_types,
36
+ )
37
+
38
+ from geoarrow.pyarrow._kernel import Kernel
39
+
40
+ from geoarrow.pyarrow._array import array
41
+
42
+ from geoarrow.pyarrow import _scalar
43
+
44
+ from geoarrow.pyarrow._compute import (
45
+ parse_all,
46
+ as_wkt,
47
+ as_wkb,
48
+ infer_type_common,
49
+ as_geoarrow,
50
+ format_wkt,
51
+ make_point,
52
+ unique_geometry_types,
53
+ box,
54
+ box_agg,
55
+ with_coord_type,
56
+ with_crs,
57
+ with_dimensions,
58
+ with_edge_type,
59
+ with_geometry_type,
60
+ rechunk,
61
+ point_coords,
62
+ to_geopandas,
63
+ )
64
+
65
+ __all__ = [
66
+ "GeometryType",
67
+ "Dimensions",
68
+ "CoordType",
69
+ "EdgeType",
70
+ "CrsType",
71
+ "GeometryExtensionType",
72
+ "WktType",
73
+ "WkbType",
74
+ "PointType",
75
+ "LinestringType",
76
+ "PolygonType",
77
+ "MultiPointType",
78
+ "MultiLinestringType",
79
+ "MultiPolygonType",
80
+ "wkb",
81
+ "large_wkb",
82
+ "wkt",
83
+ "large_wkt",
84
+ "point",
85
+ "linestring",
86
+ "polygon",
87
+ "multipoint",
88
+ "multilinestring",
89
+ "multipolygon",
90
+ "extension_type",
91
+ "geometry_type_common",
92
+ "register_extension_types",
93
+ "unregister_extension_types",
94
+ "Kernel",
95
+ "array",
96
+ "parse_all",
97
+ "as_wkt",
98
+ "as_wkb",
99
+ "infer_type_common",
100
+ "as_geoarrow",
101
+ "format_wkt",
102
+ "make_point",
103
+ "unique_geometry_types",
104
+ "box",
105
+ "box_agg",
106
+ "with_coord_type",
107
+ "with_crs",
108
+ "with_dimensions",
109
+ "with_edge_type",
110
+ "with_geometry_type",
111
+ "rechunk",
112
+ "point_coords",
113
+ "to_geopandas",
114
+ "_scalar",
115
+ ]
116
+
117
+ try:
118
+ register_extension_types()
119
+ except Exception as e:
120
+ import warnings
121
+
122
+ warnings.warn(
123
+ "Failed to register one or more extension types.\n"
124
+ "If this warning appears from pytest, you may have to re-run with --import-mode=importlib.\n"
125
+ "You may also be able to run `unregister_extension_types()` and `register_extension_types()`.\n"
126
+ f"The original error was {e}"
127
+ )
@@ -0,0 +1,184 @@
1
+ import pyarrow as pa
2
+ import pyarrow_hotfix as _ # noqa: F401
3
+
4
+ from geoarrow.c import lib
5
+
6
+ from geoarrow.pyarrow._kernel import Kernel
7
+ from geoarrow.pyarrow._type import (
8
+ GeometryExtensionType,
9
+ wkb,
10
+ wkt,
11
+ large_wkb,
12
+ large_wkt,
13
+ )
14
+
15
+
16
+ class GeometryExtensionArray(pa.ExtensionArray):
17
+ def geobuffers(self):
18
+ import numpy as np
19
+
20
+ cschema = lib.SchemaHolder()
21
+ self.type._export_to_c(cschema._addr())
22
+ carray = lib.ArrayHolder()
23
+ self._export_to_c(carray._addr())
24
+
25
+ array_view = lib.CArrayView(carray, cschema)
26
+ buffers = array_view.buffers()
27
+ return [np.array(b) if b is not None else None for b in buffers]
28
+
29
+ def __repr__(self):
30
+ n_values_to_show = 10
31
+ max_width = 70
32
+
33
+ if len(self) > n_values_to_show:
34
+ n_extra = len(self) - n_values_to_show
35
+ value_s = "values" if n_extra != 1 else "value"
36
+ head = self[: int(n_values_to_show / 2)]
37
+ mid = f"...{n_extra} {value_s}..."
38
+ tail = self[int(-n_values_to_show / 2) :]
39
+ else:
40
+ head = self
41
+ mid = ""
42
+ tail = self[:0]
43
+
44
+ try:
45
+ kernel = Kernel.format_wkt(self.type, max_element_size_bytes=max_width)
46
+ head = kernel.push(head)
47
+ tail = kernel.push(tail)
48
+ except Exception as e:
49
+ err = f"* 1 or more display values failed to parse\n* {str(e)}"
50
+ type_name = type(self).__name__
51
+ super_repr = super().__repr__()
52
+ return f"{type_name}:{repr(self.type)}[{len(self)}]\n{err}\n{super_repr}"
53
+
54
+ head_str = [f"<{item.as_py()}>" for item in head]
55
+ tail_str = [f"<{item.as_py()}>" for item in tail]
56
+ for i in range(len(head)):
57
+ if len(head_str[i]) > max_width:
58
+ head_str[i] = f"{head_str[i][:(max_width - 4)]}...>"
59
+ for i in range(len(tail)):
60
+ if len(tail_str[i]) > max_width:
61
+ tail_str[i] = f"{tail_str[i][:(max_width - 4)]}...>"
62
+
63
+ type_name = type(self).__name__
64
+ head_str = "\n".join(head_str)
65
+ tail_str = "\n".join(tail_str)
66
+ items_str = f"{head_str}\n{mid}\n{tail_str}"
67
+
68
+ return f"{type_name}:{repr(self.type)}[{len(self)}]\n{items_str}".strip()
69
+
70
+
71
+ class PointArray(GeometryExtensionArray):
72
+ pass
73
+
74
+
75
+ class LinestringArray(GeometryExtensionArray):
76
+ pass
77
+
78
+
79
+ class PolygonArray(GeometryExtensionArray):
80
+ pass
81
+
82
+
83
+ class MultiPointArray(GeometryExtensionArray):
84
+ pass
85
+
86
+
87
+ class MultiLinestringArray(GeometryExtensionArray):
88
+ pass
89
+
90
+
91
+ class MultiPolygonArray(GeometryExtensionArray):
92
+ pass
93
+
94
+
95
+ def array_cls_from_name(name):
96
+ if name == "geoarrow.wkb":
97
+ return GeometryExtensionArray
98
+ elif name == "geoarrow.wkt":
99
+ return GeometryExtensionArray
100
+ elif name == "geoarrow.point":
101
+ return PointArray
102
+ elif name == "geoarrow.linestring":
103
+ return LinestringArray
104
+ elif name == "geoarrow.polygon":
105
+ return PolygonArray
106
+ elif name == "geoarrow.multipoint":
107
+ return MultiPointArray
108
+ elif name == "geoarrow.multilinestring":
109
+ return MultiLinestringArray
110
+ elif name == "geoarrow.multipolygon":
111
+ return MultiPolygonArray
112
+ else:
113
+ raise ValueError(f'Expected valid extension name but got "{name}"')
114
+
115
+
116
+ # Inject array_cls_from_name exactly once to avoid circular import
117
+ if GeometryExtensionType._array_cls_from_name is None:
118
+ GeometryExtensionType._array_cls_from_name = array_cls_from_name
119
+
120
+
121
+ def array(obj, type_=None, *args, **kwargs) -> GeometryExtensionArray:
122
+ """Attempt to create an Array or ChunkedArray with a geoarrow extension type
123
+ from ``obj``. This constructor attempts to perform the fewest transformations
124
+ possible (i.e., WKB is left as WKB, WKT is left as WKT), whereas
125
+ :func:`geoarrow.pyarrow.as_geoarrow` actively attempts a conversion to
126
+ a geoarrow-encoding based on a common geometry type. GeoPandas objects are
127
+ supported. This implementation relies heavily on ``pyarrow.array()`` and has
128
+ similar behaviour.
129
+
130
+ >>> import geoarrow.pyarrow as ga
131
+ >>> ga.array(["POINT (0 1)"])
132
+ GeometryExtensionArray:WktType(geoarrow.wkt)[1]
133
+ <POINT (0 1)>
134
+ >>> ga.as_geoarrow(["POINT (0 1)"])
135
+ PointArray:PointType(geoarrow.point)[1]
136
+ <POINT (0 1)>
137
+ """
138
+ # Convert GeoPandas to WKB
139
+ if type(obj).__name__ == "GeoSeries":
140
+ if obj.crs:
141
+ type_ = wkb().with_crs(obj.crs.to_json(), lib.CrsType.PROJJSON)
142
+ else:
143
+ type_ = wkb()
144
+
145
+ # Prefer ISO WKB
146
+ obj = obj.to_wkb(flavor="iso")
147
+
148
+ # Convert obj to array if it isn't already one
149
+ if isinstance(obj, pa.Array) or isinstance(obj, pa.ChunkedArray):
150
+ arr = obj
151
+ else:
152
+ arr = pa.array(obj, *args, **kwargs)
153
+
154
+ # Handle the case where we get to pick the type
155
+ if type_ is None:
156
+ if isinstance(arr.type, GeometryExtensionType):
157
+ return arr
158
+ elif arr.type == pa.utf8():
159
+ return wkt().wrap_array(arr)
160
+ elif arr.type == pa.large_utf8():
161
+ return large_wkt().wrap_array(arr)
162
+ elif arr.type == pa.binary():
163
+ return wkb().wrap_array(arr)
164
+ elif arr.type == pa.large_binary():
165
+ return large_wkb().wrap_array(arr)
166
+ else:
167
+ raise TypeError(
168
+ f"Can't create geoarrow.array from Arrow array of type {type_}"
169
+ )
170
+
171
+ # Handle the case where the type requested is already the correct type
172
+ if type_ == arr.type:
173
+ return arr
174
+
175
+ type_is_geoarrow = isinstance(type_, GeometryExtensionType)
176
+ type_is_wkb_or_wkt = type_.extension_name in ("geoarrow.wkt", "geoarrow.wkb")
177
+
178
+ if type_is_geoarrow and type_is_wkb_or_wkt:
179
+ arr = arr.cast(type_.storage_type)
180
+ return type_.wrap_array(arr)
181
+
182
+ # Eventually we will be able to handle more types (e.g., parse wkt or wkb
183
+ # into a geoarrow type)
184
+ raise TypeError(f"Can't create geoarrow.array for type {type_}")