fastquadtree 1.2.1__cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl → 1.3.0__cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.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.

Potentially problematic release.


This version of fastquadtree might be problematic. Click here for more details.

@@ -18,6 +18,8 @@ from ._item import Item # base class for PointItem and RectItem
18
18
  from ._obj_store import ObjStore
19
19
 
20
20
  if TYPE_CHECKING:
21
+ from typing import Self # Only in Python 3.11+
22
+
21
23
  from numpy.typing import NDArray
22
24
 
23
25
  Bounds = Tuple[float, float, float, float]
@@ -46,6 +48,7 @@ class _BaseQuadTree(Generic[G, HitT, ItemType], ABC):
46
48
  "_bounds",
47
49
  "_capacity",
48
50
  "_count",
51
+ "_dtype",
49
52
  "_max_depth",
50
53
  "_native",
51
54
  "_next_id",
@@ -59,6 +62,10 @@ class _BaseQuadTree(Generic[G, HitT, ItemType], ABC):
59
62
  def _new_native(self, bounds: Bounds, capacity: int, max_depth: int | None) -> Any:
60
63
  """Create the native engine instance."""
61
64
 
65
+ @classmethod
66
+ def _new_native_from_bytes(cls, data: bytes, dtype: str) -> Any:
67
+ """Create the native engine instance from serialized bytes."""
68
+
62
69
  @staticmethod
63
70
  @abstractmethod
64
71
  def _make_item(id_: int, geom: G, obj: Any | None) -> ItemType:
@@ -73,10 +80,12 @@ class _BaseQuadTree(Generic[G, HitT, ItemType], ABC):
73
80
  *,
74
81
  max_depth: int | None = None,
75
82
  track_objects: bool = False,
83
+ dtype: str = "f32",
76
84
  ):
77
85
  self._bounds = bounds
78
86
  self._max_depth = max_depth
79
87
  self._capacity = capacity
88
+ self._dtype = dtype
80
89
  self._native = self._new_native(bounds, capacity, max_depth)
81
90
 
82
91
  self._track_objects = bool(track_objects)
@@ -132,12 +141,13 @@ class _BaseQuadTree(Generic[G, HitT, ItemType], ABC):
132
141
  return pickle.dumps(self.to_dict())
133
142
 
134
143
  @classmethod
135
- def from_bytes(cls, data: bytes) -> _BaseQuadTree[G, HitT, ItemType]:
144
+ def from_bytes(cls, data: bytes, dtype: str = "f32") -> Self:
136
145
  """
137
- Deserialize a quadtree from bytes.
146
+ Deserialize a quadtree from bytes. Specifiy the dtype if the original tree that was serialized used a non-default dtype.
138
147
 
139
148
  Args:
140
149
  data: Bytes representing the serialized quadtree from `to_bytes()`.
150
+ dtype: The data type used in the native engine ('f32', 'f64', 'i32', 'i64') when saved to bytes.
141
151
 
142
152
  Returns:
143
153
  A new quadtree instance with the same state as when serialized.
@@ -154,7 +164,15 @@ class _BaseQuadTree(Generic[G, HitT, ItemType], ABC):
154
164
  store_dict = in_dict["store"]
155
165
 
156
166
  qt = cls.__new__(cls) # type: ignore[call-arg]
157
- qt._native = cls._new_native_from_bytes(core_bytes)
167
+ try:
168
+ qt._native = cls._new_native_from_bytes(core_bytes, dtype=dtype)
169
+ except ValueError as ve:
170
+ raise ValueError(
171
+ "Failed to deserialize quadtree native core. "
172
+ "This may be due to a dtype mismatch. "
173
+ "Ensure the dtype used in from_bytes() matches the original tree. "
174
+ "Error details: " + str(ve)
175
+ ) from ve
158
176
 
159
177
  if store_dict is not None:
160
178
  qt._store = ObjStore.from_dict(store_dict, qt._make_item)
Binary file
@@ -5,10 +5,17 @@ from typing import Any, Literal, Tuple, overload
5
5
 
6
6
  from ._base_quadtree import Bounds, _BaseQuadTree
7
7
  from ._item import Point, PointItem
8
- from ._native import QuadTree as _RustQuadTree # native point tree
8
+ from ._native import QuadTree as QuadTreeF32, QuadTreeF64, QuadTreeI32, QuadTreeI64
9
9
 
10
10
  _IdCoord = Tuple[int, float, float]
11
11
 
12
+ DTYPE_MAP = {
13
+ "f32": QuadTreeF32,
14
+ "f64": QuadTreeF64,
15
+ "i32": QuadTreeI32,
16
+ "i64": QuadTreeI64,
17
+ }
18
+
12
19
 
13
20
  class QuadTree(_BaseQuadTree[Point, _IdCoord, PointItem]):
14
21
  """
@@ -29,6 +36,7 @@ class QuadTree(_BaseQuadTree[Point, _IdCoord, PointItem]):
29
36
  capacity: Max number of points per node before splitting.
30
37
  max_depth: Optional max tree depth. If omitted, engine decides.
31
38
  track_objects: Enable id <-> object mapping inside Python.
39
+ dtype: Data type for coordinates and ids in the native engine. Default is 'f32'. Options are 'f32', 'f64', 'i32', 'i64'.
32
40
 
33
41
  Raises:
34
42
  ValueError: If parameters are invalid or inserts are out of bounds.
@@ -41,26 +49,16 @@ class QuadTree(_BaseQuadTree[Point, _IdCoord, PointItem]):
41
49
  *,
42
50
  max_depth: int | None = None,
43
51
  track_objects: bool = False,
52
+ dtype: str = "f32",
44
53
  ):
45
54
  super().__init__(
46
55
  bounds,
47
56
  capacity,
48
57
  max_depth=max_depth,
49
58
  track_objects=track_objects,
59
+ dtype=dtype,
50
60
  )
51
61
 
52
- @classmethod
53
- def from_bytes(cls, data: bytes) -> QuadTree:
54
- """
55
- Create a QuadTree instance from serialized bytes.
56
-
57
- Args:
58
- data: Serialized byte data from `to_bytes()`.
59
- Returns:
60
- A QuadTree instance.
61
- """
62
- return super().from_bytes(data)
63
-
64
62
  @overload
65
63
  def query(
66
64
  self, rect: Bounds, *, as_items: Literal[False] = ...
@@ -160,14 +158,19 @@ class QuadTree(_BaseQuadTree[Point, _IdCoord, PointItem]):
160
158
  return out
161
159
 
162
160
  def _new_native(self, bounds: Bounds, capacity: int, max_depth: int | None) -> Any:
163
- if max_depth is None:
164
- return _RustQuadTree(bounds, capacity)
165
- return _RustQuadTree(bounds, capacity, max_depth=max_depth)
161
+ """Create the native engine instance."""
162
+ rust_cls = DTYPE_MAP.get(self._dtype)
163
+ if rust_cls is None:
164
+ raise ValueError(f"Unsupported dtype: {self._dtype}")
165
+ return rust_cls(bounds, capacity, max_depth)
166
166
 
167
167
  @classmethod
168
- def _new_native_from_bytes(cls, data: bytes) -> Any:
168
+ def _new_native_from_bytes(cls, data: bytes, dtype: str = "f32") -> Any:
169
169
  """Create a new native engine instance from serialized bytes."""
170
- return _RustQuadTree.from_bytes(data)
170
+ rust_cls = DTYPE_MAP.get(dtype)
171
+ if rust_cls is None:
172
+ raise ValueError(f"Unsupported dtype: {dtype}")
173
+ return rust_cls.from_bytes(data)
171
174
 
172
175
  @staticmethod
173
176
  def _make_item(id_: int, geom: Point, obj: Any | None) -> PointItem:
@@ -5,10 +5,21 @@ from typing import Any, Literal, Tuple, overload
5
5
 
6
6
  from ._base_quadtree import Bounds, _BaseQuadTree
7
7
  from ._item import RectItem
8
- from ._native import RectQuadTree as _RustRectQuadTree # native rect tree
8
+ from ._native import (
9
+ RectQuadTree as RectQuadTreeF32,
10
+ RectQuadTreeF64,
11
+ RectQuadTreeI32,
12
+ RectQuadTreeI64,
13
+ )
9
14
 
10
15
  _IdRect = Tuple[int, float, float, float, float]
11
- Point = Tuple[float, float] # only for type hints in docstrings
16
+
17
+ DTYPE_MAP = {
18
+ "f32": RectQuadTreeF32,
19
+ "f64": RectQuadTreeF64,
20
+ "i32": RectQuadTreeI32,
21
+ "i64": RectQuadTreeI64,
22
+ }
12
23
 
13
24
 
14
25
  class RectQuadTree(_BaseQuadTree[Bounds, _IdRect, RectItem]):
@@ -30,6 +41,7 @@ class RectQuadTree(_BaseQuadTree[Bounds, _IdRect, RectItem]):
30
41
  capacity: Max number of points per node before splitting.
31
42
  max_depth: Optional max tree depth. If omitted, engine decides.
32
43
  track_objects: Enable id <-> object mapping inside Python.
44
+ dtype: Data type for coordinates and ids in the native engine. Default is 'f32'. Options are 'f32', 'f64', 'i32', 'i64'.
33
45
 
34
46
  Raises:
35
47
  ValueError: If parameters are invalid or inserts are out of bounds.
@@ -42,26 +54,16 @@ class RectQuadTree(_BaseQuadTree[Bounds, _IdRect, RectItem]):
42
54
  *,
43
55
  max_depth: int | None = None,
44
56
  track_objects: bool = False,
57
+ dtype: str = "f32",
45
58
  ):
46
59
  super().__init__(
47
60
  bounds,
48
61
  capacity,
49
62
  max_depth=max_depth,
50
63
  track_objects=track_objects,
64
+ dtype=dtype,
51
65
  )
52
66
 
53
- @classmethod
54
- def from_bytes(cls, data: bytes) -> RectQuadTree:
55
- """
56
- Create a RectQuadTree instance from serialized bytes.
57
-
58
- Args:
59
- data: Serialized byte data from `to_bytes()`.
60
- Returns:
61
- A RectQuadTree instance.
62
- """
63
- return super().from_bytes(data)
64
-
65
67
  @overload
66
68
  def query(
67
69
  self, rect: Bounds, *, as_items: Literal[False] = ...
@@ -96,14 +98,19 @@ class RectQuadTree(_BaseQuadTree[Bounds, _IdRect, RectItem]):
96
98
  return self._store.get_many_by_ids(self._native.query_ids(rect))
97
99
 
98
100
  def _new_native(self, bounds: Bounds, capacity: int, max_depth: int | None) -> Any:
99
- if max_depth is None:
100
- return _RustRectQuadTree(bounds, capacity)
101
- return _RustRectQuadTree(bounds, capacity, max_depth=max_depth)
101
+ """Create the native engine instance."""
102
+ rust_cls = DTYPE_MAP.get(self._dtype)
103
+ if rust_cls is None:
104
+ raise ValueError(f"Unsupported dtype: {self._dtype}")
105
+ return rust_cls(bounds, capacity, max_depth)
102
106
 
103
107
  @classmethod
104
- def _new_native_from_bytes(cls, data: bytes) -> Any:
108
+ def _new_native_from_bytes(cls, data: bytes, dtype: str = "f32") -> Any:
105
109
  """Create a new native engine instance from serialized bytes."""
106
- return _RustRectQuadTree.from_bytes(data)
110
+ rust_cls = DTYPE_MAP.get(dtype)
111
+ if rust_cls is None:
112
+ raise ValueError(f"Unsupported dtype: {dtype}")
113
+ return rust_cls.from_bytes(data)
107
114
 
108
115
  @staticmethod
109
116
  def _make_item(id_: int, geom: Bounds, obj: Any | None) -> RectItem:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fastquadtree
3
- Version: 1.2.1
3
+ Version: 1.3.0
4
4
  Classifier: Programming Language :: Python :: 3
5
5
  Classifier: Programming Language :: Python :: 3 :: Only
6
6
  Classifier: Programming Language :: Rust
@@ -26,12 +26,13 @@ Requires-Dist: mkdocs-minify-plugin ; extra == 'dev'
26
26
  Requires-Dist: maturin>=1.5 ; extra == 'dev'
27
27
  Requires-Dist: pyqtree==1.0.0 ; extra == 'dev'
28
28
  Requires-Dist: numpy ; extra == 'dev'
29
+ Requires-Dist: pre-commit ; extra == 'dev'
29
30
  Provides-Extra: dev
30
31
  License-File: LICENSE
31
32
  Summary: Rust-accelerated quadtree for Python with fast inserts, range queries, and k-NN search.
32
33
  Keywords: quadtree,spatial-index,geometry,rust,pyo3,nearest-neighbor,k-nn
33
34
  Author: Ethan Anderson
34
- Requires-Python: >=3.8
35
+ Requires-Python: >=3.9
35
36
  Description-Content-Type: text/markdown
36
37
  Project-URL: Homepage, https://github.com/Elan456/fastquadtree
37
38
  Project-URL: Repository, https://github.com/Elan456/fastquadtree
@@ -45,6 +46,8 @@ Project-URL: Issues, https://github.com/Elan456/fastquadtree/issues
45
46
 
46
47
  Rust-optimized quadtree with a clean Python API
47
48
 
49
+ 👉 **Check out the Docs:** https://elan456.github.io/fastquadtree/
50
+
48
51
  [![PyPI](https://img.shields.io/pypi/v/fastquadtree.svg)](https://pypi.org/project/fastquadtree/)
49
52
  [![Python versions](https://img.shields.io/pypi/pyversions/fastquadtree.svg)](https://pypi.org/project/fastquadtree/)
50
53
  [![Downloads](https://static.pepy.tech/personalized-badge/fastquadtree?period=total&units=INTERNATIONAL_SYSTEM&left_color=GRAY&right_color=BLUE&left_text=Total%20Downloads)](https://pepy.tech/projects/fastquadtree)
@@ -64,19 +67,19 @@ Rust-optimized quadtree with a clean Python API
64
67
 
65
68
  ## Why use fastquadtree
66
69
 
67
- - Clean [Python API](https://elan456.github.io/fastquadtree/api/quadtree/) with no external dependencies and modern typing hints
70
+ - Clean [Python API](https://elan456.github.io/fastquadtree/api/quadtree/) with **no external dependencies** and modern typing hints
68
71
  - The fastest quadtree Python package ([>10x faster](https://elan456.github.io/fastquadtree/benchmark/) than pyqtree)
69
72
  - Prebuilt wheels for Windows, macOS, and Linux
70
73
  - Support for [inserting bounding boxes](https://elan456.github.io/fastquadtree/api/rect_quadtree/) or points
71
74
  - Fast KNN and range queries
72
75
  - Optional object tracking for id ↔ object mapping
73
76
  - Fast [serialization](https://elan456.github.io/fastquadtree/benchmark/#serialization-vs-rebuild) to/from bytes
77
+ - Support for multiple data types (f32, f64, i32, i64) for coordinates
74
78
  - [100% test coverage](https://codecov.io/gh/Elan456/fastquadtree) and CI on GitHub Actions
75
79
  - Offers a drop-in [pyqtree shim](https://elan456.github.io/fastquadtree/benchmark/#pyqtree-drop-in-shim-performance-gains) that is 6.567x faster while keeping the same API
76
80
 
77
81
  ----
78
82
 
79
- 👉 **Docs:** https://elan456.github.io/fastquadtree/
80
83
 
81
84
  ## Examples
82
85
  See examples of how fastquadtree can be used in the [runnables](https://elan456.github.io/fastquadtree/runnables/) section.
@@ -0,0 +1,13 @@
1
+ fastquadtree-1.3.0.dist-info/METADATA,sha256=NIDXaSGreQNVvoCiTLKAty1ylz_-PsnQe_ABTWrQ6u4,9747
2
+ fastquadtree-1.3.0.dist-info/WHEEL,sha256=cqfH6P_NujaeOc1olR46J5a7YgoxWJnrr5iZ1_DMqps,129
3
+ fastquadtree-1.3.0.dist-info/licenses/LICENSE,sha256=pRuvcuqIMtEUBMgvP1Bc4fOHydzeuA61c6DQoQ1pb1w,1071
4
+ fastquadtree/__init__.py,sha256=rtkveNz7rScRasTRGu1yEqzeoJfLfreJNxg21orPL-U,195
5
+ fastquadtree/_base_quadtree.py,sha256=BTOvu1FM9oBzEMh2JTzfeJiPrrjtmWKU1JJS1DfR7UE,15925
6
+ fastquadtree/_item.py,sha256=EDS3nJHdVtjDsuTqTZKGTZH8iWJIQ-TKxLXqvMScNPA,2405
7
+ fastquadtree/_native.abi3.so,sha256=oGDIRMYxQJFk9Uu-6z4MlsWrrdSSQZJwFqUD1ESbOH0,729512
8
+ fastquadtree/_obj_store.py,sha256=HeYFGUPYhvxBzL7Js0g0jsIxflpZS6RsXNk50rGeNlA,6522
9
+ fastquadtree/point_quadtree.py,sha256=zpvd9EJUcT2soMP89yQJgpaht9-vz7DG5tDqaad8GEc,6181
10
+ fastquadtree/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
+ fastquadtree/pyqtree.py,sha256=2Khh1gCPalD4z0gb3EmqtzMoga08E9BkB0j5bwkiRPU,6076
12
+ fastquadtree/rect_quadtree.py,sha256=uVzaRTs-ZEcD1PGlQjfnLP6HWnOkr2zp6elO7sMDwow,4004
13
+ fastquadtree-1.3.0.dist-info/RECORD,,
@@ -1,13 +0,0 @@
1
- fastquadtree-1.2.1.dist-info/METADATA,sha256=IYzvJNOV07j4qtOFQqryt15YjrnuWrSjJpK0NUDe-1E,9614
2
- fastquadtree-1.2.1.dist-info/WHEEL,sha256=cqfH6P_NujaeOc1olR46J5a7YgoxWJnrr5iZ1_DMqps,129
3
- fastquadtree-1.2.1.dist-info/licenses/LICENSE,sha256=pRuvcuqIMtEUBMgvP1Bc4fOHydzeuA61c6DQoQ1pb1w,1071
4
- fastquadtree/__init__.py,sha256=rtkveNz7rScRasTRGu1yEqzeoJfLfreJNxg21orPL-U,195
5
- fastquadtree/_base_quadtree.py,sha256=NhUkMulVa2ItCtx5rEnE_asHY3aGN0XxG6m-AYJk7CE,15091
6
- fastquadtree/_item.py,sha256=EDS3nJHdVtjDsuTqTZKGTZH8iWJIQ-TKxLXqvMScNPA,2405
7
- fastquadtree/_native.abi3.so,sha256=KowjAh4FNt39FRoddwNjgcSWSG1tGRV7McT8WWRO8aE,540600
8
- fastquadtree/_obj_store.py,sha256=HeYFGUPYhvxBzL7Js0g0jsIxflpZS6RsXNk50rGeNlA,6522
9
- fastquadtree/point_quadtree.py,sha256=BM6mxw2pSmAKkOgXnosREfC6WOXCgEYNeQDlvnlEbKQ,5945
10
- fastquadtree/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
- fastquadtree/pyqtree.py,sha256=2Khh1gCPalD4z0gb3EmqtzMoga08E9BkB0j5bwkiRPU,6076
12
- fastquadtree/rect_quadtree.py,sha256=82IygiEmJ4JdA6LBDXq288cs9VfS3LpdJdkjCPcYCKM,3807
13
- fastquadtree-1.2.1.dist-info/RECORD,,