[Git][debian-gis-team/pykdtree][upstream] New upstream version 1.4.3+ds

Antonio Valentino (@antonio.valentino) gitlab at salsa.debian.org
Sun Aug 10 17:30:47 BST 2025



Antonio Valentino pushed to branch upstream at Debian GIS Project / pykdtree


Commits:
8133f404 by Antonio Valentino at 2025-08-09T08:27:41+00:00
New upstream version 1.4.3+ds
- - - - -


8 changed files:

- .github/workflows/deploy-wheels.yml
- CHANGELOG.md
- README.rst
- + pykdtree/kdtree.pyi
- + pykdtree/py.typed
- + pykdtree/test_stub.py
- pyproject.toml
- setup.py


Changes:

=====================================
.github/workflows/deploy-wheels.yml
=====================================
@@ -33,9 +33,9 @@ jobs:
       fail-fast: false
       matrix:
         include:
-          - os: windows-2019
+          - os: windows-latest
             cibw_archs: "AMD64"
-          - os: windows-2019
+          - os: windows-latest
             cibw_archs: "ARM64"
           - os: macos-13
             cibw_archs: "x86_64"
@@ -54,12 +54,12 @@ jobs:
           git fetch --prune --unshallow
 
       - name: Build wheels
-        uses: pypa/cibuildwheel at v2.22.0
+        uses: pypa/cibuildwheel at v3.1.3
         env:
-          CIBW_SKIP: "cp36-* cp37-* cp38-* pp* *i686 *-musllinux_aarch64"
+          CIBW_SKIP: "cp38-* *i686 *-musllinux_aarch64"
           CIBW_ARCHS: "${{ matrix.cibw_archs }}"
           CIBW_TEST_COMMAND: "pytest -v --pyargs pykdtree"
-          CIBW_TEST_REQUIRES: "pytest"
+          CIBW_TEST_REQUIRES: "pytest mypy"
           CIBW_TEST_SKIP: "*-win_arm64"
           CIBW_BUILD_VERBOSITY: 1
           # we use openmp (libomp) from homebrew which has a current limit of
@@ -90,9 +90,8 @@ jobs:
           path: dist
       - name: Publish package to PyPI
         if: github.event.action == 'published'
-        uses: pypa/gh-action-pypi-publish at v1.12.3
+        uses: pypa/gh-action-pypi-publish at v1.12.4
         with:
           user: ${{ secrets.pypi_username }}
           password: ${{ secrets.pypi_password }}
           skip-existing: true
-


=====================================
CHANGELOG.md
=====================================
@@ -1,3 +1,20 @@
+## Version 1.4.2 (2025/07/04)
+
+### Issues Closed
+
+* [Issue 141](https://github.com/storpipfugl/pykdtree/issues/141) - There will be problems with querying very large arrays
+
+In this release 1 issue was closed.
+
+### Pull Requests Merged
+
+#### Features added
+
+* [PR 145](https://github.com/storpipfugl/pykdtree/pull/145) - Add kdtree.pyi stub files for type hints
+
+In this release 1 pull request was closed.
+
+
 ## Version 1.4.1 (2025/01/29)
 
 ### Issues Closed


=====================================
README.rst
=====================================
@@ -119,6 +119,42 @@ Increasing **leafsize** will reduce the memory overhead and construction time bu
 
 pykdtree accepts data in double precision (numpy.float64) or single precision (numpy.float32) floating point. If data of another type is used an internal copy in double precision is made resulting in a memory overhead. If the kd-tree is constructed on single precision data the query points must be single precision as well.
 
+Free-threading (no GIL) support
+-------------------------------
+
+Pykdtree is compiled with the necessary flags to be run from a free-threaded
+Python interpreter. That is, it can be called without the GIL. Once a
+``KDTree`` is constructed all state is stored internal to the object. Querying
+the ``KDTree`` object can be done from multiple threads simultaneously.
+``pykdtree`` has never acquired the GIL for low-level operations so performance
+improvements are expected to be minimal on a free-threaded interpreter.
+
+Any issues using ``pykdtree`` with free-threading should be filed as a GitHub
+issue.
+
+Multi-threading Gotchas
+-----------------------
+
+If using pykdtree from a multi-worker configuration, for example with the
+``dask`` library, take care to control the number of dask and OpenMP workers.
+On builds of pykdtree with OpenMP support (see "Control OpenMP usage" above),
+OpenMP will default to one worker thread per logical core on your system. Dask
+and libraries like it also tend to default to one worker thread per logical core.
+These libraries can conflict resulting in cases like a dask worker thread
+using pykdtree triggering OpenMP to create its workers. This has the potential of
+creating N * N worker threads which can slow down your system as it tries to
+manage and schedule that many threads.
+
+In situations like this it is recommended to limit OpenMP to 1 or 2 workers by
+defining the environment variable:
+
+.. code-block:: bash
+
+   OMP_NUM_THREADS=1
+
+This essentially shifts the parallelism responsibility to the high-level dask
+library rather than the low-level OpenMP library.
+
 Benchmarks
 ----------
 Comparison with scipy.spatial.cKDTree and libANN. This benchmark is on geospatial 3D data with 10053632 data points and 4276224 query points. The results are indexed relative to the construction time of scipy.spatial.cKDTree. A leafsize of 10 (scipy.spatial.cKDTree default) is used.


=====================================
pykdtree/kdtree.pyi
=====================================
@@ -0,0 +1,93 @@
+# pykdtree, Fast kd-tree implementation with OpenMP-enabled queries
+#
+# Copyright (C) 2013 - present  Esben S. Nielsen
+#
+# This program is free software: you can redistribute it and/or modify it under
+# the terms of the GNU Lesser General Public License as published by the Free
+# Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
+# details.
+#
+# You should have received a copy of the GNU Lesser General Public License along
+# with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+from typing import Any
+import numpy as np
+
+class KDTree:
+    """kd-tree for fast nearest-neighbour lookup.
+    The interface is made to resemble the scipy.spatial kd-tree except
+    only Euclidean distance measure is supported.
+
+    :Parameters:
+    data_pts : numpy array
+        Data points with shape (n , dims)
+    leafsize : int, optional
+        Maximum number of data points in tree leaf
+    """
+
+    @property
+    def data_pts(self) -> np.ndarray:
+        """Data points used to construct the kd-tree."""
+
+    @property
+    def data(self) -> np.ndarray:
+        """Data points used to construct the kd-tree."""
+
+    @property
+    def n(self) -> int:
+        """Number of data points."""
+
+    @property
+    def ndim(self) -> int:
+        """Number of dimensions."""
+
+    @property
+    def leafsize(self) -> int:
+        """Maximum number of data points in tree leaf."""
+
+    def __init__(self, data_pts: np.ndarray, leafsize: int = 16): ...
+    def query(
+        self,
+        query_pts: np.ndarray,
+        k: int = 1,
+        eps: float = 0,
+        distance_upper_bound: float | None = None,
+        sqr_dists: bool = False,
+        mask: np.ndarray | None = None,
+    ):
+        """Query the kd-tree for nearest neighbors
+
+        :Parameters:
+        query_pts : numpy array
+            Query points with shape (m, dims)
+        k : int
+            The number of nearest neighbours to return
+        eps : non-negative float
+            Return approximate nearest neighbours; the k-th returned value
+            is guaranteed to be no further than (1 + eps) times the distance
+            to the real k-th nearest neighbour
+        distance_upper_bound : non-negative float
+            Return only neighbors within this distance.
+            This is used to prune tree searches.
+        sqr_dists : bool, optional
+            Internally pykdtree works with squared distances.
+            Determines if the squared or Euclidean distances are returned.
+        mask : numpy array, optional
+            Array of booleans where neighbors are considered invalid and
+            should not be returned. A mask value of True represents an
+            invalid pixel. Mask should have shape (n,) to match data points.
+            By default all points are considered valid.
+
+        """
+        ...
+
+# These are generated by Cython.
+# Just in here to avoid errors in mypy tests.
+__reduce_cython__: Any
+__setstate_cython__: Any
+__test__: Any


=====================================
pykdtree/py.typed
=====================================


=====================================
pykdtree/test_stub.py
=====================================
@@ -0,0 +1,17 @@
+from pytest import CaptureFixture
+
+
+def test_mypy(capsys: CaptureFixture[str]) -> None:
+    """
+    Run mypy stub tests for pykdtree.
+    This function checks for:
+        - Type consistency in the stubs vs the definitions
+        - Function / property signatures
+        - Missing functions or properties in the stubs
+    """
+    from mypy import stubtest
+
+    code = stubtest.test_stubs(stubtest.parse_options(["pykdtree.kdtree"]))
+    captured = capsys.readouterr()
+
+    assert code == 0, "Mypy stub test failed:\n" + captured.out


=====================================
pyproject.toml
=====================================
@@ -1,3 +1,3 @@
 [build-system]
-requires = ["setuptools", "numpy>=2.0.0rc1,<3", "Cython>=3"]
+requires = ["setuptools", "numpy>=2.0.0,<3", "Cython>=3.1"]
 build-backend = "setuptools.build_meta"


=====================================
setup.py
=====================================
@@ -189,15 +189,15 @@ with open('README.rst', 'r') as readme_file:
 extensions = [
     Extension('pykdtree.kdtree', sources=['pykdtree/kdtree.pyx', 'pykdtree/_kdtree_core.c'],
               include_dirs=[np.get_include()],
-              define_macros=[("NPY_NO_DEPRECATED_API", "NPY_1_7_API_VERSION")],
-              cython_directives={"language_level": "3"},
+              define_macros=[("NPY_NO_DEPRECATED_API", "NPY_1_25_API_VERSION")],
+              cython_directives={"language_level": "3", "freethreading_compatible": True},
               ),
 ]
 
 
 setup(
     name='pykdtree',
-    version='1.4.1',
+    version='1.4.3',
     url="https://github.com/storpipfugl/pykdtree",
     description='Fast kd-tree implementation with OpenMP-enabled queries',
     long_description=readme,
@@ -207,18 +207,21 @@ setup(
     packages=['pykdtree'],
     python_requires='>=3.9',
     install_requires=['numpy'],
-    tests_require=['pytest'],
+    extras_require={
+        'test': ['pytest', 'mypy'],
+    },
     zip_safe=False,
     ext_modules=extensions,
     cmdclass={'build_ext': build_ext_subclass},
+    license="LGPL-3.0-or-later",
+    license_files=["LICENSE.txt"],
     classifiers=[
       'Development Status :: 5 - Production/Stable',
-      ('License :: OSI Approved :: '
-          'GNU Lesser General Public License v3 (LGPLv3)'),
       'Programming Language :: Python',
       'Operating System :: OS Independent',
       'Intended Audience :: Science/Research',
-      'Topic :: Scientific/Engineering'
+      'Topic :: Scientific/Engineering',
+      'Programming Language :: Python :: Free Threading :: 3 - Stable',
       ]
     )
 



View it on GitLab: https://salsa.debian.org/debian-gis-team/pykdtree/-/commit/8133f4047c1df38a2fab1eb50ef36f735b222fa0

-- 
View it on GitLab: https://salsa.debian.org/debian-gis-team/pykdtree/-/commit/8133f4047c1df38a2fab1eb50ef36f735b222fa0
You're receiving this email because of your account on salsa.debian.org.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/pkg-grass-devel/attachments/20250810/18c779ce/attachment-0001.htm>


More information about the Pkg-grass-devel mailing list