[Git][debian-gis-team/python-pyproj][master] 12 commits: Update branch in gbp.conf & Vcs-Git URL.

Bas Couwenberg (@sebastic) gitlab at salsa.debian.org
Thu Sep 21 05:24:35 BST 2023



Bas Couwenberg pushed to branch master at Debian GIS Project / python-pyproj


Commits:
f7fca83c by Bas Couwenberg at 2023-09-19T05:14:36+02:00
Update branch in gbp.conf & Vcs-Git URL.

- - - - -
ea1f356e by Bas Couwenberg at 2023-09-19T05:18:05+02:00
New upstream version 3.6.1~rc0
- - - - -
badbc702 by Bas Couwenberg at 2023-09-19T05:18:07+02:00
Update upstream source from tag 'upstream/3.6.1_rc0'

Update to upstream version '3.6.1~rc0'
with Debian dir d9ef56094a05d2ea963831917a1f257f4233d7c3
- - - - -
d3e8fae6 by Bas Couwenberg at 2023-09-19T05:19:56+02:00
New upstream release candidate.

- - - - -
27b21705 by Bas Couwenberg at 2023-09-19T05:22:30+02:00
Refresh patches.

- - - - -
46a87034 by Bas Couwenberg at 2023-09-19T05:26:08+02:00
Update lintian overrides.

- - - - -
1f124fd7 by Bas Couwenberg at 2023-09-19T05:26:08+02:00
Set distribution to experimental.

- - - - -
ba0afb2b by Bas Couwenberg at 2023-09-21T06:19:35+02:00
Revert "Update branch in gbp.conf & Vcs-Git URL."

This reverts commit f7fca83c46f93cc30c699d628ba0a7e4c360ad03.

- - - - -
4a7f8bcd by Bas Couwenberg at 2023-09-21T06:19:47+02:00
New upstream version 3.6.1
- - - - -
ca3ba08e by Bas Couwenberg at 2023-09-21T06:19:49+02:00
Update upstream source from tag 'upstream/3.6.1'

Update to upstream version '3.6.1'
with Debian dir 0bb640cafef917f7c59911d956b3ff36b6f75030
- - - - -
dcae7d64 by Bas Couwenberg at 2023-09-21T06:20:00+02:00
New upstream release.

- - - - -
2d0b2e41 by Bas Couwenberg at 2023-09-21T06:21:12+02:00
Set distribution to unstable.

- - - - -


30 changed files:

- .all-contributorsrc
- .cirrus.yml
- .github/workflows/build_docs.yaml
- .github/workflows/release.yaml
- .github/workflows/test_proj_latest.yaml
- .github/workflows/tests.yaml
- HOW_TO_RELEASE.md
- README.md
- appveyor.yml
- ci/vcpkg.json
- debian/changelog
- debian/patches/rpath.patch
- debian/python3-pyproj.lintian-overrides
- docs/advanced_examples.rst
- docs/history.rst
- docs/past_versions.rst
- pyproj/__init__.py
- pyproj/_datadir.pxd
- pyproj/_datadir.pyx
- pyproj/_geod.pyx
- pyproj/crs/enums.py
- pyproj/geod.py
- pyproject.toml
- requirements-test.txt
- setup.py
- test/conftest.py
- test/test_datum_shift.py
- test/test_proj.py
- test/test_transformer.py
- test/test_utils.py


Changes:

=====================================
.all-contributorsrc
=====================================
@@ -635,6 +635,33 @@
         "doc",
         "test"
       ]
+    },
+    {
+      "login": "djm93dev",
+      "name": "Daniel McDonald",
+      "avatar_url": "https://avatars.githubusercontent.com/u/101536185?v=4",
+      "profile": "https://github.com/djm93dev",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "cyschneck",
+      "name": "Cora Schneck",
+      "avatar_url": "https://avatars.githubusercontent.com/u/22159116?v=4",
+      "profile": "https://cyschneck.com/",
+      "contributions": [
+        "doc"
+      ]
+    },
+    {
+      "login": "zanejgr",
+      "name": "zanejgr",
+      "avatar_url": "https://avatars.githubusercontent.com/u/14795919?v=4",
+      "profile": "https://github.com/zanejgr",
+      "contributions": [
+        "doc"
+      ]
     }
   ],
   "contributorsPerLine": 7


=====================================
.cirrus.yml
=====================================
@@ -1,6 +1,6 @@
 build_and_store_wheels: &BUILD_AND_STORE_WHEELS
   install_cibuildwheel_script:
-    - python -m pip install cibuildwheel==2.11.2
+    - python -m pip install cibuildwheel==2.16
   run_cibuildwheel_script:
     - cibuildwheel
   wheels_artifacts:
@@ -14,20 +14,20 @@ macos_task:
     image: ghcr.io/cirruslabs/macos-monterey-xcode
   env:
     PATH: /opt/homebrew/opt/python at 3.10/bin:$PATH
-    CIBW_SKIP: "*musllinux*"
+    CIBW_SKIP: "*musllinux* pp*"
     CIBW_ARCHS_MACOS: arm64
     CIBW_ENVIRONMENT_MACOS:
       PROJ_WHEEL=true
       PROJ_NETWORK=ON
-      PROJ_VERSION=9.2.1
+      PROJ_VERSION=9.3.0
       PROJ_DIR=${CIRRUS_WORKING_DIR}/pyproj/proj_dir
       BUILD_PREFIX=${CIRRUS_WORKING_DIR}/build/
       MACOSX_DEPLOYMENT_TARGET=10.9
       CMAKE_OSX_ARCHITECTURES='arm64'
       LDFLAGS="${LDFLAGS} -Wl,-rpath,${CIRRUS_WORKING_DIR}/pyproj/proj_dir/lib"
     CIBW_BEFORE_ALL_MACOS: bash ./ci/proj-compile-wheels.sh
-    CIBW_TEST_REQUIRES: cython pytest oldest-supported-numpy pandas xarray
-    CIBW_BEFORE_TEST: python -m pip install shapely || echo "Shapely install failed"
+    CIBW_TEST_REQUIRES: cython pytest numpy --config-settings=setup-args="-Dallow-noblas=true"
+    CIBW_BEFORE_TEST: python -m pip install shapely pandas xarray || echo "Optional requirements install failed"
     CIBW_TEST_COMMAND: >
       pyproj -v &&
       python -c "import pyproj; pyproj.Proj(init='epsg:4269')"  &&


=====================================
.github/workflows/build_docs.yaml
=====================================
@@ -16,7 +16,7 @@ jobs:
     runs-on: ubuntu-latest
 
     steps:
-      - uses: actions/checkout at v3
+      - uses: actions/checkout at v4
         with:
           persist-credentials: false
 


=====================================
.github/workflows/release.yaml
=====================================
@@ -15,14 +15,15 @@ concurrency:
   cancel-in-progress: true
 
 env:
-  PROJ_VERSION: "9.2.1"
+  PROJ_VERSION: "9.3.0"
+  DEBIAN_FRONTEND: noninteractive
 
 jobs:
   make_sdist:
     name: Make sdist
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/checkout at v3
+      - uses: actions/checkout at v4
 
       - name: Setup Conda
         uses: s-weigand/setup-conda at v1
@@ -57,10 +58,10 @@ jobs:
       fail-fast: false
       matrix:
         include:
-        - os: ubuntu-20.04
+        - os: ubuntu-22.04
           arch: x86_64
-        - os: ubuntu-20.04
-          arch: i686
+        # - os: ubuntu-22.04
+        #   arch: i686
         - os: macos-11
           arch: x86_64
           cmake_osx_architectures: x86_64
@@ -70,22 +71,27 @@ jobs:
         # - os: macos-11
         #   arch: universal2
         #   cmake_osx_architectures: "x86_64;arm64"
-        - os: "windows-2019"
+        - os: "windows-2022"
           arch: "auto64"
           triplet: "x64-windows"
           vcpkg_cache: "c:\\vcpkg\\installed"
           vcpkg_logs: "c:\\vcpkg\\buildtrees\\**\\*.log"
-        - os: "windows-2019"
+        - os: "windows-2022"
           arch: "auto32"
           triplet: "x86-windows"
           vcpkg_cache: "c:\\vcpkg\\installed"
           vcpkg_logs: "c:\\vcpkg\\buildtrees\\**\\*.log"
 
     steps:
-      - uses: actions/checkout at v3
+      - uses: actions/checkout at v4
 
       - uses: actions/setup-python at v4
 
+      - name: Setup MSVC (32-bit)
+        if: ${{ matrix.triplet == 'x86-windows' }}
+        uses: bus1/cabuild/action/msdevshell at e22aba57d6e74891d059d66501b6b5aed8123c4d  # v1
+        with:
+          architecture: 'x86'
 
       - name: Cache vcpkg
         if: contains(matrix.os, 'windows')
@@ -111,9 +117,9 @@ jobs:
           cp "$VCPKG_INSTALLATION_ROOT/installed/${{ matrix.triplet }}/share/proj/"* ${GITHUB_WORKSPACE}/pyproj/proj_dir/share/proj/
 
       - name: Build wheels
-        uses: pypa/cibuildwheel at v2.13.0
+        uses: pypa/cibuildwheel at v2.16
         env:
-          CIBW_SKIP: "*musllinux* pp*-win*"
+          CIBW_SKIP: "*musllinux* pp*-win* pp31*"
           CIBW_ARCHS: ${{ matrix.arch }}
           CIBW_ENVIRONMENT_LINUX:
             PROJ_WHEEL=true
@@ -137,8 +143,8 @@ jobs:
           CIBW_REPAIR_WHEEL_COMMAND_WINDOWS: "delvewheel repair --add-path C:/vcpkg/installed/${{ matrix.triplet }}/bin -w {dest_dir} {wheel}"
           CIBW_BEFORE_ALL_LINUX: bash ./ci/proj-compile-wheels.sh
           CIBW_BEFORE_ALL_MACOS: bash ./ci/proj-compile-wheels.sh
-          CIBW_TEST_REQUIRES: cython pytest oldest-supported-numpy pandas xarray
-          CIBW_BEFORE_TEST: python -m pip install shapely || echo "Shapely install failed"
+          CIBW_TEST_REQUIRES: cython pytest numpy --config-settings=setup-args="-Dallow-noblas=true"
+          CIBW_BEFORE_TEST: python -m pip install shapely pandas xarray || echo "Optional requirements install failed"
           CIBW_TEST_COMMAND: >
             pyproj -v &&
             python -c "import pyproj; pyproj.Proj(init='epsg:4269')"  &&


=====================================
.github/workflows/test_proj_latest.yaml
=====================================
@@ -14,6 +14,9 @@ concurrency:
   group: ${{ github.workflow }}-${{ github.head_ref || github.ref }}
   cancel-in-progress: true
 
+env:
+  DEBIAN_FRONTEND: noninteractive
+
 jobs:
   test_proj_latest:
     name: PROJ Latest
@@ -23,7 +26,7 @@ jobs:
       PROJ_DIR: ${{ github.workspace }}/proj_install
       PROJ_DATA: ${{ github.workspace }}/proj_install/share/proj
     steps:
-      - uses: actions/checkout at v3
+      - uses: actions/checkout at v4
       - uses: actions/setup-python at v4
         with:
             python-version: 3.9


=====================================
.github/workflows/tests.yaml
=====================================
@@ -14,12 +14,13 @@ concurrency:
 
 env:
   PYPROJ_FULL_COVERAGE: YES
+  DEBIAN_FRONTEND: noninteractive
 
 jobs:
   linting:
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/checkout at v3
+      - uses: actions/checkout at v4
       - uses: actions/setup-python at v4
         with:
             python-version: 3.9
@@ -39,9 +40,11 @@ jobs:
     strategy:
       fail-fast: false
       matrix:
-        python-version: ['3.9', '3.10', '3.11']
-        proj-version: ['9.2.0']
+        python-version: ['3.9', '3.10', '3.11', '3.12']
+        proj-version: ['9.3.0']
         include:
+          - python-version: '3.9'
+            proj-version: '9.2.1'
           - python-version: '3.9'
             proj-version: '9.1.1'
           - python-version: '3.9'
@@ -49,7 +52,7 @@ jobs:
           - python-version: '3.9'
             proj-version: '9.0.1'
     steps:
-      - uses: actions/checkout at v3
+      - uses: actions/checkout at v4
 
       - name: Update
         run: |
@@ -135,7 +138,7 @@ jobs:
             python-implementation: python
             proj-version: '9.1.1'
     steps:
-      - uses: actions/checkout at v3
+      - uses: actions/checkout at v4
 
       - name: Setup Conda
         uses: s-weigand/setup-conda at v1
@@ -147,12 +150,18 @@ jobs:
         run: |
           conda config --prepend channels conda-forge
           conda config --set channel_priority strict
-          export INSTALL_DEPS='${{ matrix.python-implementation }}=${{ matrix.python-version }} cython proj=${{ matrix.proj-version }} numpy xarray pandas'
+          export INSTALL_DEPS='${{ matrix.python-implementation }}=${{ matrix.python-version }} cython proj=${{ matrix.proj-version }} numpy'
           if [ "${{ matrix.os }}" = "macos-latest" -a "${{ matrix.python-version }}" = "3.10" ]; then
             sed -i.bak '/shapely/d' requirements-test.txt;
           else
             export INSTALL_DEPS="${INSTALL_DEPS} shapely";
           fi;
+          if [ "${{ matrix.python-implementation }}" = "pypy" ]; then
+            sed -i.bak '/xarray/d' requirements-test.txt;
+            sed -i.bak '/pandas/d' requirements-test.txt;
+          else
+            export INSTALL_DEPS="${INSTALL_DEPS} xarray pandas";
+          fi;
           conda create -n test $INSTALL_DEPS
           source activate test
           python -m pip install -e .


=====================================
HOW_TO_RELEASE.md
=====================================
@@ -22,6 +22,7 @@ The next step is to create a tag with the same name as the version just added. T
 2. Create a draft PR at https://github.com/conda-forge/pyproj-feedstock and verify tests pass.
 3. Check the wheels built at https://github.com/pyproj4/pyproj using GitHub Actions.
 4. Verify Debian builds were successful.
+4. Verify Fedora builds were successful.
 5. Verify the docs build successfully.
 
 ## Phase 2: Make the release
@@ -40,19 +41,10 @@ Next, go through the history and add release notes (see: [automatically generate
 
 ### The wheels
 
-The wheels are tested with each merge to main. However, the arm64 wheels on linux are still
-built separately. This provides instructions for those wheels:
+Most of the wheels are tested with each merge to main and uploaded to pypi on release in GitHub Actions. However, the arm64 wheels are built separately. This provides instructions for those wheels:
 
-1. Update the PR at https://github.com/pyproj4/pyproj-wheels with the release tag, merge, and download wheels.
-
-### Create the release sdist
-
-1. `python -m pip install build`
-2. `python -m build --sdist`
-
-### Upload to pypi
-
-Upload the wheels and the sdist `tar.gz` for the release to pypi.
+1. linux arm64: Update the PR at https://github.com/pyproj4/pyproj-wheels with the release tag & merge. The wheels will automatically upload to pypi when the CI runs suceed.
+2. macos arm64: Download the release wheel artifacts from the Cirrus CI build and upload manually to pypi.
 
 ### Verify conda-forge build is correct
 


=====================================
README.md
=====================================
@@ -1,4 +1,4 @@
-![Pyproj logo](docs/media/logo.png)
+![Pyproj logo](https://raw.githubusercontent.com/pyproj4/pyproj/main/docs/media/logo.png)
 
 # pyproj
 
@@ -6,7 +6,7 @@ Python interface to [PROJ](http://proj.org) (cartographic projections and coordi
 
 <p align="center">
 <a href="https://gitter.im/pyproj4-pyproj/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge"><img alt="Join the chat at https://gitter.im/pyproj4-pyproj/community" src="https://badges.gitter.im/pyproj4-pyproj/community.svg"></a>
-<a href="#contributors"><img alt="All Contributors" src="https://img.shields.io/badge/all_contributors-60-orange.svg?style=flat-square"></a>
+<a href="#contributors"><img alt="All Contributors" src="https://img.shields.io/badge/all_contributors-63-orange.svg?style=flat-square"></a>
 <a href="https://ci.appveyor.com/project/snowman2/pyproj"><img alt="Appveyor Build Status" src="https://ci.appveyor.com/api/projects/status/v2ypts9j76doa9ey/branch/main?svg=true"></a>
 <a href="https://github.com/pyproj4/pyproj/actions?query=workflow%3ATests"><img alt="GitHub Actions Build Status" src="https://github.com/pyproj4/pyproj/workflows/Tests/badge.svg"></a>
 <a href="https://codecov.io/gh/pyproj4/pyproj"><img alt="Codecov Status" src="https://codecov.io/gh/pyproj4/pyproj/branch/main/graph/badge.svg"></a>
@@ -116,6 +116,9 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
     <td align="center"><a href="https://github.com/dmahr1"><img src="https://avatars.githubusercontent.com/u/8354515?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Dan Mahr</b></sub></a><br /><a href="https://github.com/pyproj4/pyproj/commits?author=dmahr1" title="Code">💻</a> <a href="https://github.com/pyproj4/pyproj/commits?author=dmahr1" title="Documentation">📖</a> <a href="https://github.com/pyproj4/pyproj/commits?author=dmahr1" title="Tests">⚠️</a></td>
     <td align="center"><a href="https://github.com/rhugonnet"><img src="https://avatars.githubusercontent.com/u/28896516?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Romain Hugonnet</b></sub></a><br /><a href="https://github.com/pyproj4/pyproj/commits?author=rhugonnet" title="Code">💻</a> <a href="https://github.com/pyproj4/pyproj/commits?author=rhugonnet" title="Documentation">📖</a> <a href="https://github.com/pyproj4/pyproj/commits?author=rhugonnet" title="Tests">⚠️</a></td>
     <td align="center"><a href="https://javier.jimenezshaw.com/"><img src="https://avatars.githubusercontent.com/u/15678366?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Javier Jimenez Shaw</b></sub></a><br /><a href="https://github.com/pyproj4/pyproj/commits?author=jjimenezshaw" title="Code">💻</a> <a href="https://github.com/pyproj4/pyproj/commits?author=jjimenezshaw" title="Documentation">📖</a> <a href="https://github.com/pyproj4/pyproj/commits?author=jjimenezshaw" title="Tests">⚠️</a></td>
+    <td align="center"><a href="https://github.com/djm93dev"><img src="https://avatars.githubusercontent.com/u/101536185?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Daniel McDonald</b></sub></a><br /><a href="https://github.com/pyproj4/pyproj/commits?author=djm93dev" title="Documentation">📖</a></td>
+    <td align="center"><a href="https://cyschneck.com/"><img src="https://avatars.githubusercontent.com/u/22159116?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Cora Schneck</b></sub></a><br /><a href="https://github.com/pyproj4/pyproj/commits?author=cyschneck" title="Documentation">📖</a></td>
+    <td align="center"><a href="https://github.com/zanejgr"><img src="https://avatars.githubusercontent.com/u/14795919?v=4?s=100" width="100px;" alt=""/><br /><sub><b>zanejgr</b></sub></a><br /><a href="https://github.com/pyproj4/pyproj/commits?author=zanejgr" title="Documentation">📖</a></td>
   </tr>
 </table>
 


=====================================
appveyor.yml
=====================================
@@ -15,7 +15,7 @@ environment:
     # with caching build takes less than 1 minute
     - PYTHON: "C:\\Python39-x64"
       APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
-      PROJSOURCE: 9.2.1
+      PROJSOURCE: 9.3.0
       BUILD_SHARED_LIBS: ON
     # - PYTHON: "C:\\Python39-x64"
     #   APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019


=====================================
ci/vcpkg.json
=====================================
@@ -4,8 +4,8 @@
     "dependencies": [
         {
             "name": "proj",
-            "version>=": "9.2.1"
+            "version>=": "9.3.0"
         }
     ],
-    "builtin-baseline": "ad345ce17a26c56e8829356d9a98048ba0f4433b"
+    "builtin-baseline": "7b5ca09708ae42dba9517d4e0a0c975d087f1061"
 }


=====================================
debian/changelog
=====================================
@@ -1,12 +1,22 @@
-python-pyproj (3.6.0-2) UNRELEASED; urgency=medium
+python-pyproj (3.6.1-1) unstable; urgency=medium
 
+  * New upstream release.
+  * Move from experimental to unstable.
+
+ -- Bas Couwenberg <sebastic at debian.org>  Thu, 21 Sep 2023 06:20:44 +0200
+
+python-pyproj (3.6.1~rc0-1~exp1) experimental; urgency=medium
+
+  * New upstream release candidate.
   * Use autopkgtest-pkg-pybuild testsuite.
   * Enable Salsa CI.
   * Remove generated files in clean target.
     (closes: #1046443)
   * Switch to dh-sequence-*.
+  * Refresh patches.
+  * Update lintian overrides.
 
- -- Bas Couwenberg <sebastic at debian.org>  Sun, 16 Jul 2023 17:03:16 +0200
+ -- Bas Couwenberg <sebastic at debian.org>  Tue, 19 Sep 2023 05:22:32 +0200
 
 python-pyproj (3.6.0-1) unstable; urgency=medium
 


=====================================
debian/patches/rpath.patch
=====================================
@@ -4,7 +4,7 @@ Forwarded: not-needed
 
 --- a/setup.py
 +++ b/setup.py
-@@ -175,9 +175,6 @@ def get_extension_modules():
+@@ -194,9 +194,6 @@ def get_extension_modules():
      ext_options = {
          "include_dirs": include_dirs,
          "library_dirs": library_dirs,


=====================================
debian/python3-pyproj.lintian-overrides
=====================================
@@ -1,3 +1,6 @@
 # Building manpage causes FTBFS: #982698
 no-manual-page *
 
+# False positive
+package-contains-documentation-outside-usr-share-doc [usr/lib/python3/dist-packages/*.dist-info/*]
+


=====================================
docs/advanced_examples.rst
=====================================
@@ -19,12 +19,12 @@ optimize your transformations.
 
 .. code-block:: python
 
-    import numpy as np
+    import numpy
     from pyproj import Transformer, transform
 
     transformer = Transformer.from_crs(2263, 4326)
-    x_coords = np.random.randint(80000, 120000)
-    y_coords = np.random.randint(200000, 250000)
+    x_coords = numpy.random.randint(80000, 120000)
+    y_coords = numpy.random.randint(200000, 250000)
 
 
 Example with :func:`pyproj.transformer.transform`:
@@ -202,7 +202,7 @@ As of version 3.1, these objects are thread-safe:
 - :class:`pyproj.crs.CRS`
 - :class:`pyproj.transformer.Transformer`
 
-If you have pyproj<3.1, you will need to create create the object
+If you have pyproj<3.1, you will need to create the object
 within the thread that uses it.
 
 Here is a simple demonstration:


=====================================
docs/history.rst
=====================================
@@ -1,6 +1,12 @@
 Change Log
 ==========
 
+3.6.1
+------
+- WHL: Wheels contain PROJ 9.3.0 (issue #1327)
+- BUG: Remove pkg_resources from setup.py (issue #1313)
+- BUG: Cython 3 compatibility fixes (issue #1321)
+
 3.6.0
 ------
 - DEP: Minimum supported Python version 3.9 (issue #1111)


=====================================
docs/past_versions.rst
=====================================
@@ -1,6 +1,7 @@
 Documentation Archive
 =====================
 
+- `3.6.0 <https://pyproj4.github.io/pyproj/3.6.0/>`_
 - `3.5.0 <https://pyproj4.github.io/pyproj/3.5.0/>`_
 - `3.4.1 <https://pyproj4.github.io/pyproj/3.4.1/>`_
 - `3.3.1 <https://pyproj4.github.io/pyproj/3.3.1/>`_


=====================================
pyproj/__init__.py
=====================================
@@ -66,7 +66,7 @@ from pyproj.transformer import (  # noqa: F401 pylint: disable=unused-import
     transform,
 )
 
-__version__ = "3.6.0"
+__version__ = "3.6.1"
 __all__ = [
     "Proj",
     "Geod",


=====================================
pyproj/_datadir.pxd
=====================================
@@ -1,7 +1,7 @@
 include "proj.pxi"
 
-cpdef str _get_proj_error()
-cpdef void _clear_proj_error()
+cpdef str _get_proj_error() noexcept
+cpdef void _clear_proj_error() noexcept
 cdef PJ_CONTEXT* PYPROJ_GLOBAL_CONTEXT
 cdef PJ_CONTEXT* pyproj_context_create() except *
 cdef void pyproj_context_destroy(PJ_CONTEXT* context) except *


=====================================
pyproj/_datadir.pyx
=====================================
@@ -6,7 +6,6 @@ from libc.stdlib cimport free, malloc
 
 from pyproj._compat cimport cstrencode
 
-from pyproj.exceptions import DataDirError
 from pyproj.utils import strtobool
 
 # for logging the internal PROJ messages
@@ -79,14 +78,14 @@ def get_user_data_dir(create=False):
     )
 
 
-cpdef str _get_proj_error():
+cpdef str _get_proj_error() noexcept:
     """
     Get the internal PROJ error message. Returns None if no error was set.
     """
     return _INTERNAL_PROJ_ERROR
 
 
-cpdef void _clear_proj_error():
+cpdef void _clear_proj_error() noexcept:
     """
     Clear the internal PROJ error message.
     """
@@ -94,7 +93,7 @@ cpdef void _clear_proj_error():
     _INTERNAL_PROJ_ERROR = None
 
 
-cdef void pyproj_log_function(void *user_data, int level, const char *error_msg) nogil:
+cdef void pyproj_log_function(void *user_data, int level, const char *error_msg) nogil noexcept:
     """
     Log function for catching PROJ errors.
     """


=====================================
pyproj/_geod.pyx
=====================================
@@ -566,7 +566,7 @@ cdef class Geod:
         Returns
         -------
         (float, float):
-            The area (meter^2) and permimeter (meters) of the polygon.
+            The area (meter^2) and perimeter (meters) of the polygon.
 
         """
         cdef PyBuffWriteManager lonbuff = PyBuffWriteManager(lons)


=====================================
pyproj/crs/enums.py
=====================================
@@ -82,7 +82,7 @@ class Ellipsoidal2DCSAxis(BaseEnum):
     """
     .. versionadded:: 2.5.0
 
-    Ellisoidal 2D Coordinate System Axis for creating axis with
+    Ellipsoidal 2D Coordinate System Axis for creating axis with
     with :class:`pyproj.crs.coordinate_system.Ellipsoidal2DCS`
 
     Attributes
@@ -99,7 +99,7 @@ class Ellipsoidal3DCSAxis(BaseEnum):
     """
     .. versionadded:: 2.5.0
 
-    Ellisoidal 3D Coordinate System Axis for creating axis with
+    Ellipsoidal 3D Coordinate System Axis for creating axis with
     with :class:`pyproj.crs.coordinate_system.Ellipsoidal3DCS`
 
     Attributes


=====================================
pyproj/geod.py
=====================================
@@ -969,7 +969,7 @@ class Geod(_Geod):
         Returns
         -------
         (float, float):
-            The geodesic area (meters^2) and permimeter (meters) of the polygon.
+            The geodesic area (meters^2) and perimeter (meters) of the polygon.
         """
         return self._polygon_area_perimeter(
             _copytobuffer(lons)[0], _copytobuffer(lats)[0], radians=radians
@@ -1077,7 +1077,7 @@ class Geod(_Geod):
         Returns
         -------
         (float, float):
-            The geodesic area (meters^2) and permimeter (meters) of the polygon.
+            The geodesic area (meters^2) and perimeter (meters) of the polygon.
         """
         try:
             return self.polygon_area_perimeter(  # type: ignore


=====================================
pyproject.toml
=====================================
@@ -1,5 +1,5 @@
 [build-system]
-requires = ["setuptools>=61.0.0", "wheel", "cython>=0.28.4"]
+requires = ["setuptools>=61.0.0", "wheel", "cython>=3"]
 build-backend = "setuptools.build_meta"
 
 [project]
@@ -32,6 +32,7 @@ classifiers = [
     "Programming Language :: Python :: 3.9",
     "Programming Language :: Python :: 3.10",
     "Programming Language :: Python :: 3.11",
+    "Programming Language :: Python :: 3.12",
     "Programming Language :: Python :: 3 :: Only",
     "Topic :: Scientific/Engineering",
     "Topic :: Scientific/Engineering :: GIS",


=====================================
requirements-test.txt
=====================================
@@ -2,6 +2,6 @@ packaging
 pytest>3.6
 pytest-cov
 numpy
-pandas
-shapely
-xarray
+pandas; python_version<'3.12'
+shapely; python_version<'3.12'
+xarray; python_version<'3.12'


=====================================
setup.py
=====================================
@@ -7,20 +7,39 @@ import sys
 from pathlib import Path
 from typing import Optional
 
-from pkg_resources import parse_version
 from setuptools import Extension, setup
 
-PROJ_MIN_VERSION = parse_version("9.0.0")
+PROJ_MIN_VERSION = (9, 0, 0)
 CURRENT_FILE_PATH = Path(__file__).absolute().parent
 BASE_INTERNAL_PROJ_DIR = Path("proj_dir")
 INTERNAL_PROJ_DIR = CURRENT_FILE_PATH / "pyproj" / BASE_INTERNAL_PROJ_DIR
 PROJ_VERSION_SEARCH = re.compile(r".*Rel\.\s+(?P<version>\d+\.\d+\.\d+).*")
+VERSION_SEARCH = re.compile(r".*(?P<version>\d+\.\d+\.\d+).*")
 
 
-def get_proj_version(proj_dir: Path) -> str:
+def _parse_version(version: str) -> tuple[int, int, int]:
+    """Convert a version string to a tuple of integers."""
+    match = VERSION_SEARCH.search(version)
+    if not match:
+        raise SystemExit(
+            f"PROJ version unable to be determined from {version}. "
+            "Please set the PROJ_VERSION environment variable."
+        )
+    return tuple(
+        int(ver) for ver in match.groupdict()["version"].split(".", maxsplit=2)
+    )
+
+
+def get_proj_version(proj_dir: Path) -> tuple[int, int, int]:
+    """
+    Determine PROJ version.
+
+    Prefer PROJ_VERSION environment variable.
+    If PROJ_VERSION is not set, try to determine the version from the PROJ executable.
+    """
     proj_version = os.environ.get("PROJ_VERSION")
     if proj_version:
-        return proj_version
+        return _parse_version(proj_version)
     proj = proj_dir / "bin" / "proj"
     proj_ver = subprocess.check_output(str(proj), stderr=subprocess.STDOUT).decode(
         "ascii"
@@ -31,15 +50,17 @@ def get_proj_version(proj_dir: Path) -> str:
             "PROJ version unable to be determined. "
             "Please set the PROJ_VERSION environment variable."
         )
-    return match.groupdict()["version"]
+    return _parse_version(match.groupdict()["version"])
 
 
-def check_proj_version(proj_version: str) -> None:
+def check_proj_version(proj_version: tuple[int, int, int]) -> None:
     """checks that the PROJ library meets the minimum version"""
-    if parse_version(proj_version) < PROJ_MIN_VERSION:
+    if proj_version < PROJ_MIN_VERSION:
+        proj_version_str = ".".join(str(ver) for ver in proj_version)
+        min_proj_version_str = ".".join(str(ver) for ver in PROJ_MIN_VERSION)
         raise SystemExit(
-            f"ERROR: Minimum supported PROJ version is {PROJ_MIN_VERSION}, installed "
-            f"version is {proj_version}. For more information see: "
+            f"ERROR: Minimum supported PROJ version is {min_proj_version_str}, "
+            f"installed version is {proj_version_str}. For more information see: "
             "https://pyproj4.github.io/pyproj/stable/installation.html"
         )
 
@@ -154,11 +175,11 @@ def get_extension_modules():
     # make sure cython is available
     try:
         from Cython.Build import cythonize
-    except ImportError:
+    except ImportError as error:
         raise SystemExit(
             "ERROR: Cython.Build.cythonize not found. "
             "Cython is required to build pyproj."
-        )
+        ) from error
 
     # By default we'll try to get options PROJ_DIR or the local version of proj
     proj_dir = get_proj_dir()
@@ -167,9 +188,7 @@ def get_extension_modules():
 
     proj_version = get_proj_version(proj_dir)
     check_proj_version(proj_version)
-    proj_version_major, proj_version_minor, proj_version_patch = parse_version(
-        proj_version
-    ).base_version.split(".")
+    proj_version_major, proj_version_minor, proj_version_patch = proj_version
 
     # setup extension options
     ext_options = {
@@ -197,9 +216,9 @@ def get_extension_modules():
         ],
         quiet=True,
         compile_time_env={
-            "CTE_PROJ_VERSION_MAJOR": int(proj_version_major),
-            "CTE_PROJ_VERSION_MINOR": int(proj_version_minor),
-            "CTE_PROJ_VERSION_PATCH": int(proj_version_patch),
+            "CTE_PROJ_VERSION_MAJOR": proj_version_major,
+            "CTE_PROJ_VERSION_MINOR": proj_version_minor,
+            "CTE_PROJ_VERSION_PATCH": proj_version_patch,
             "CTE_PYTHON_IMPLEMENTATION": platform.python_implementation(),
         },
         **get_cythonize_options(),


=====================================
test/conftest.py
=====================================
@@ -18,6 +18,7 @@ PROJ_GTE_91 = PROJ_LOOSE_VERSION >= version.parse("9.1")
 PROJ_GTE_911 = PROJ_LOOSE_VERSION >= version.parse("9.1.1")
 PROJ_GTE_92 = PROJ_LOOSE_VERSION >= version.parse("9.2.0")
 PROJ_GTE_921 = PROJ_LOOSE_VERSION >= version.parse("9.2.1")
+PROJ_GTE_93 = PROJ_LOOSE_VERSION >= version.parse("9.3.0")
 
 
 def unset_data_dir():


=====================================
test/test_datum_shift.py
=====================================
@@ -51,13 +51,13 @@ def test_shift_utm33_to_wgs84():
     assert_almost_equal((back_lon, back_lat, back_z), (WGS84_lon, WGS84_lat, WGS84_z))
 
 
-def test_shift_wgs84_to_gaussb_no_ellisoidal_height():
+def test_shift_wgs84_to_gaussb_no_ellipsoidal_height():
     with pytest.warns(FutureWarning):
         xgb, ygb, zgb = transform(WGS84_PROJ, GAUSSSB_PROJ, WGS84_lon, WGS84_lat, 0)
     assert_almost_equal((xgb, ygb, zgb), (GB_x, 5055619.899, 0), decimal=2)
 
 
-def test_shift_gaussb_to_wgs84_no_ellisoidal_height():
+def test_shift_gaussb_to_wgs84_no_ellipsoidal_height():
     with pytest.warns(FutureWarning):
         back_lon, back_lat, back_z = transform(GAUSSSB_PROJ, WGS84_PROJ, GB_x, GB_y, 0)
     assert_almost_equal(


=====================================
test/test_proj.py
=====================================
@@ -5,7 +5,7 @@ import sys
 import unittest
 from unittest.mock import patch
 
-import numpy as np
+import numpy
 import pytest
 from numpy.testing import assert_almost_equal
 
@@ -441,11 +441,11 @@ def test_reset_errno():
 @pytest.mark.parametrize("radians", [False, True])
 def test_get_factors__2d_input(radians):
     transformer = Proj(3857)
-    longitude = np.array([[0, 1], [2, 3]])
-    latitude = np.array([[1, 2], [3, 4]])
+    longitude = numpy.array([[0, 1], [2, 3]])
+    latitude = numpy.array([[1, 2], [3, 4]])
     if radians:
-        longitude = np.radians(longitude)
-        latitude = np.radians(latitude)
+        longitude = numpy.radians(longitude)
+        latitude = numpy.radians(latitude)
     factors = transformer.get_factors(
         longitude=longitude, latitude=latitude, radians=radians
     )
@@ -497,22 +497,36 @@ def test_get_factors():
 def test_get_factors__nan_inf():
     transformer = Proj(3857)
     factors = transformer.get_factors(
-        longitude=[0, np.nan, np.inf, 0], latitude=[np.nan, 2, 2, np.inf]
+        longitude=[0, numpy.nan, numpy.inf, 0], latitude=[numpy.nan, 2, 2, numpy.inf]
     )
-    assert_almost_equal(factors.meridional_scale, [np.inf, np.inf, np.inf, np.inf])
-    assert_almost_equal(factors.parallel_scale, [np.inf, np.inf, np.inf, np.inf])
-    assert_almost_equal(factors.areal_scale, [np.inf, np.inf, np.inf, np.inf])
-    assert_almost_equal(factors.angular_distortion, [np.inf, np.inf, np.inf, np.inf])
     assert_almost_equal(
-        factors.meridian_parallel_angle, [np.inf, np.inf, np.inf, np.inf]
+        factors.meridional_scale, [numpy.inf, numpy.inf, numpy.inf, numpy.inf]
     )
-    assert_almost_equal(factors.meridian_convergence, [np.inf, np.inf, np.inf, np.inf])
-    assert_almost_equal(factors.tissot_semimajor, [np.inf, np.inf, np.inf, np.inf])
-    assert_almost_equal(factors.tissot_semiminor, [np.inf, np.inf, np.inf, np.inf])
-    assert_almost_equal(factors.dx_dlam, [np.inf, np.inf, np.inf, np.inf])
-    assert_almost_equal(factors.dx_dphi, [np.inf, np.inf, np.inf, np.inf])
-    assert_almost_equal(factors.dy_dlam, [np.inf, np.inf, np.inf, np.inf])
-    assert_almost_equal(factors.dy_dphi, [np.inf, np.inf, np.inf, np.inf])
+    assert_almost_equal(
+        factors.parallel_scale, [numpy.inf, numpy.inf, numpy.inf, numpy.inf]
+    )
+    assert_almost_equal(
+        factors.areal_scale, [numpy.inf, numpy.inf, numpy.inf, numpy.inf]
+    )
+    assert_almost_equal(
+        factors.angular_distortion, [numpy.inf, numpy.inf, numpy.inf, numpy.inf]
+    )
+    assert_almost_equal(
+        factors.meridian_parallel_angle, [numpy.inf, numpy.inf, numpy.inf, numpy.inf]
+    )
+    assert_almost_equal(
+        factors.meridian_convergence, [numpy.inf, numpy.inf, numpy.inf, numpy.inf]
+    )
+    assert_almost_equal(
+        factors.tissot_semimajor, [numpy.inf, numpy.inf, numpy.inf, numpy.inf]
+    )
+    assert_almost_equal(
+        factors.tissot_semiminor, [numpy.inf, numpy.inf, numpy.inf, numpy.inf]
+    )
+    assert_almost_equal(factors.dx_dlam, [numpy.inf, numpy.inf, numpy.inf, numpy.inf])
+    assert_almost_equal(factors.dx_dphi, [numpy.inf, numpy.inf, numpy.inf, numpy.inf])
+    assert_almost_equal(factors.dy_dlam, [numpy.inf, numpy.inf, numpy.inf, numpy.inf])
+    assert_almost_equal(factors.dy_dphi, [numpy.inf, numpy.inf, numpy.inf, numpy.inf])
 
 
 def test_get_factors__errcheck():
@@ -523,7 +537,7 @@ def test_get_factors__errcheck():
 
 def test_numpy_bool_kwarg_false():
     # Issue 564
-    south = np.array(50) < 0
+    south = numpy.array(50) < 0
     proj = Proj(
         proj="utm", zone=32, ellipsis="WGS84", datum="WGS84", units="m", south=south
     )
@@ -532,7 +546,7 @@ def test_numpy_bool_kwarg_false():
 
 def test_numpy_bool_kwarg_true():
     # Issue 564
-    south = np.array(50) > 0
+    south = numpy.array(50) > 0
     proj = Proj(
         proj="utm", zone=32, ellipsis="WGS84", datum="WGS84", units="m", south=south
     )


=====================================
test/test_transformer.py
=====================================
@@ -9,7 +9,7 @@ from itertools import permutations
 from pathlib import Path
 from unittest.mock import call, patch
 
-import numpy as np
+import numpy
 import pytest
 from numpy.testing import assert_almost_equal, assert_array_equal
 
@@ -22,6 +22,7 @@ from pyproj.transformer import AreaOfInterest, TransformerGroup
 from test.conftest import (
     PROJ_GTE_91,
     PROJ_GTE_92,
+    PROJ_GTE_93,
     grids_available,
     proj_env,
     proj_network_env,
@@ -64,8 +65,8 @@ def test_illegal_transformation():
         xx, yy = pyproj.transform(
             p1, p2, (-180, -180, 180, 180, -180), (-90, 90, 90, -90, -90)
         )
-    assert np.all(np.isinf(xx))
-    assert np.all(np.isinf(yy))
+    assert numpy.all(numpy.isinf(xx))
+    assert numpy.all(numpy.isinf(yy))
     with pytest.warns(FutureWarning), pytest.raises(ProjError):
         pyproj.transform(
             p1, p2, (-180, -180, 180, 180, -180), (-90, 90, 90, -90, -90), errcheck=True
@@ -412,7 +413,7 @@ def test_always_xy__itransform():
         )
 
 
- at pytest.mark.parametrize("empty_array", [(), [], np.array([])])
+ at pytest.mark.parametrize("empty_array", [(), [], numpy.array([])])
 def test_transform_empty_array_xy(empty_array):
     transformer = Transformer.from_crs(2193, 4326)
     assert_array_equal(
@@ -420,7 +421,7 @@ def test_transform_empty_array_xy(empty_array):
     )
 
 
- at pytest.mark.parametrize("empty_array", [(), [], np.array([])])
+ at pytest.mark.parametrize("empty_array", [(), [], numpy.array([])])
 def test_transform_empty_array_xyzt(empty_array):
     transformer = Transformer.from_pipeline("+init=ITRF2008:ITRF2000")
     assert_array_equal(
@@ -540,7 +541,7 @@ def test_repr__conditional():
             "Description: unavailable until proj_trans is called\n"
             "Area of Use:\n- undefined"
         )
-    elif PROJ_GTE_92:
+    elif PROJ_GTE_92 and not PROJ_GTE_93:
         assert trans_repr == (
             "<Unknown Transformer: noop>\n"
             "Description: Transformation from EGM2008 height to WGS 84 "
@@ -555,7 +556,7 @@ def test_repr__conditional():
             "(ballpark vertical transformation, without ellipsoid height "
             "to vertical height correction)\n"
             "Area of Use:\n"
-            "- name: World\n"
+            f"- name: World{'.' if PROJ_GTE_93 else ''}\n"
             "- bounds: (-180.0, -90.0, 180.0, 90.0)"
         )
 
@@ -1205,7 +1206,7 @@ def test_transform_bounds_densify(density, expected):
         "+proj=laea +lat_0=45 +lon_0=-100 +x_0=0 +y_0=0 "
         "+a=6370997 +b=6370997 +units=m +no_defs",
     )
-    assert np.allclose(
+    assert numpy.allclose(
         transformer.transform_bounds(40, -120, 64, -80, densify_pts=density),
         expected,
     )
@@ -1222,7 +1223,15 @@ def test_transform_bounds_densify(density, expected):
     "input_bounds, radians",
     [
         ((-120, 40, -80, 64), False),
-        ((np.radians(-120), np.radians(40), np.radians(-80), np.radians(64)), True),
+        (
+            (
+                numpy.radians(-120),
+                numpy.radians(40),
+                numpy.radians(-80),
+                numpy.radians(64),
+            ),
+            True,
+        ),
     ],
 )
 def test_transform_bounds_densify__xy(density, expected, input_bounds, radians):
@@ -1232,7 +1241,7 @@ def test_transform_bounds_densify__xy(density, expected, input_bounds, radians):
         "+a=6370997 +b=6370997 +units=m +no_defs",
         always_xy=True,
     )
-    assert np.allclose(
+    assert numpy.allclose(
         transformer.transform_bounds(
             *input_bounds, densify_pts=density, radians=radians
         ),
@@ -1459,8 +1468,8 @@ def test_transform_bounds__south_pole__xy():
 
 @pytest.mark.parametrize("inplace", [True, False])
 def test_transform__fortran_order(inplace):
-    lons, lats = np.arange(-180, 180, 20), np.arange(-90, 90, 10)
-    lats, lons = np.meshgrid(lats, lons)
+    lons, lats = numpy.arange(-180, 180, 20), numpy.arange(-90, 90, 10)
+    lats, lons = numpy.meshgrid(lats, lons)
     f_lons, f_lats = lons.copy(order="F"), lats.copy(order="F")
     transformer = Transformer.from_crs(
         "EPSG:4326",
@@ -1519,10 +1528,10 @@ def test_4d_transform__inplace__array__int():
 
 def test_4d_transform__inplace__numpy():
     transformer = Transformer.from_crs(7789, 8401)
-    xarr = np.array([3496737.2679], dtype=np.float64)
-    yarr = np.array([743254.4507], dtype=np.float64)
-    zarr = np.array([5264462.9620], dtype=np.float64)
-    tarr = np.array([2019.0], dtype=np.float64)
+    xarr = numpy.array([3496737.2679], dtype=numpy.float64)
+    yarr = numpy.array([743254.4507], dtype=numpy.float64)
+    zarr = numpy.array([5264462.9620], dtype=numpy.float64)
+    tarr = numpy.array([2019.0], dtype=numpy.float64)
     t_xarr, t_yarr, t_zarr, t_tarr = transformer.transform(
         xx=xarr, yy=yarr, zz=zarr, tt=tarr, inplace=True
     )
@@ -1538,10 +1547,10 @@ def test_4d_transform__inplace__numpy():
 
 def test_4d_transform__inplace__numpy__int():
     transformer = Transformer.from_crs(7789, 8401)
-    xarr = np.array([3496737], dtype=np.int32)
-    yarr = np.array([743254], dtype=np.int32)
-    zarr = np.array([5264462], dtype=np.int32)
-    tarr = np.array([2019], dtype=np.int32)
+    xarr = numpy.array([3496737], dtype=numpy.int32)
+    yarr = numpy.array([743254], dtype=numpy.int32)
+    zarr = numpy.array([5264462], dtype=numpy.int32)
+    tarr = numpy.array([2019], dtype=numpy.int32)
     t_xarr, t_yarr, t_zarr, t_tarr = transformer.transform(
         xx=xarr, yy=yarr, zz=zarr, tt=tarr, inplace=True
     )


=====================================
test/test_utils.py
=====================================
@@ -2,8 +2,6 @@ from array import array
 
 import numpy
 import pytest
-from pandas import Series
-from xarray import DataArray
 
 from pyproj.utils import DataType, _copytobuffer, _copytobuffer_return_scalar
 
@@ -22,7 +20,6 @@ def test__copytobuffer_return_scalar__invalid():
     "in_data, data_type",
     [
         (numpy.array(1), DataType.FLOAT),
-        (DataArray(numpy.array(1)), DataType.FLOAT),
         (1, DataType.FLOAT),
         ([1], DataType.LIST),
         ((1,), DataType.TUPLE),
@@ -32,10 +29,23 @@ def test__copytobuffer(in_data, data_type):
     assert _copytobuffer(in_data) == (array("d", [1]), data_type)
 
 
- at pytest.mark.parametrize(
-    "in_arr", [numpy.array([1]), DataArray(numpy.array([1])), Series(numpy.array([1]))]
-)
-def test__copytobuffer__numpy_array(in_arr):
+def test__copytobuffer__xarray_scalar():
+    xarray = pytest.importorskip("xarray")
+    assert _copytobuffer(xarray.DataArray(numpy.array(1))) == (
+        array("d", [1]),
+        DataType.FLOAT,
+    )
+
+
+ at pytest.mark.parametrize("arr_type", ["numpy", "xarray", "pandas"])
+def test__copytobuffer__array(arr_type):
+    in_arr = numpy.array([1])
+    if arr_type == "xarray":
+        xarray = pytest.importorskip("xarray")
+        in_arr = xarray.DataArray(in_arr)
+    elif arr_type == "pandas":
+        pandas = pytest.importorskip("pandas")
+        in_arr = pandas.Series(in_arr)
     assert _copytobuffer(in_arr) == (
         in_arr.astype("d").__array__(),
         DataType.ARRAY,



View it on GitLab: https://salsa.debian.org/debian-gis-team/python-pyproj/-/compare/29c82c296feeef631cc93f35c0c7a92bbe42bacb...2d0b2e41a9b0956688d433e4cb0cedbae2bcd59f

-- 
View it on GitLab: https://salsa.debian.org/debian-gis-team/python-pyproj/-/compare/29c82c296feeef631cc93f35c0c7a92bbe42bacb...2d0b2e41a9b0956688d433e4cb0cedbae2bcd59f
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/20230921/ee557c6d/attachment-0001.htm>


More information about the Pkg-grass-devel mailing list