[Git][debian-gis-team/pyosmium][trixie-backports] 9 commits: Bump Standards-Version to 4.7.4, changes: priority.

Bas Couwenberg (@sebastic) gitlab at salsa.debian.org
Wed Oct 21 04:53:57 BST 2026



Bas Couwenberg pushed to branch trixie-backports at Debian GIS Project / pyosmium


Commits:
5d63fe92 by Bas Couwenberg at 2026-04-04T10:19:33+02:00
Bump Standards-Version to 4.7.4, changes: priority.

- - - - -
725b28f8 by Bas Couwenberg at 2026-04-04T11:00:51+02:00
Fix changelog entry.

- - - - -
72fd2f53 by Bas Couwenberg at 2026-04-07T16:57:03+02:00
Require libosmium2-dev 2.23.1 from backports for replication fix.

- - - - -
a05e6942 by Bas Couwenberg at 2026-10-18T17:19:10+02:00
New upstream version 4.3.2
- - - - -
efcd38fc by Bas Couwenberg at 2026-10-18T17:19:16+02:00
Update upstream source from tag 'upstream/4.3.2'

Update to upstream version '4.3.2'
with Debian dir 898b53e64a79328ea2611b101582a38b2604fadc
- - - - -
f5fb6385 by Bas Couwenberg at 2026-10-18T17:19:40+02:00
New upstream release.

- - - - -
9f7ed903 by Bas Couwenberg at 2026-10-18T17:20:28+02:00
Set distribution to unstable.

- - - - -
7b99d4a7 by Bas Couwenberg at 2026-10-21T05:46:56+02:00
Merge tag 'debian/4.3.2-1' into trixie-backports

releasing package pyosmium version 4.3.2-1

- - - - -
88f6673b by Bas Couwenberg at 2026-10-21T05:47:05+02:00
Rebuild for trixie-backports.

- - - - -


19 changed files:

- .github/workflows/build_wheels.yml
- .github/workflows/ci.yml
- CHANGELOG.md
- CMakeLists.txt
- README.md
- cmake/FindOsmium.cmake
- debian/changelog
- debian/control
- docs/man/pyosmium-get-changes.1
- docs/man/pyosmium-up-to-date.1
- lib/merge_input_reader.cc
- lib/osm_base_objects.h
- pyproject.toml
- src/osmium/replication/server.py
- src/osmium/replication/utils.py
- + test/test_constructor_interruption.py
- test/test_merge_input_reader.py
- test/test_replication.py
- test/test_replication_utils.py


Changes:

=====================================
.github/workflows/build_wheels.yml
=====================================
@@ -4,6 +4,8 @@ on:
   push:
     tags:
       - v**
+    paths:
+      - CHANGELOG.md
 
 jobs:
   build_wheels:
@@ -31,19 +33,19 @@ jobs:
         run: python -m pip install cibuildwheel build
 
       - name: Get dependencies via sdist
-        run: python -m build --sdist
+        run: python -m build --sdist -C build-dir=build/sdist
 
       - name: Build wheels
         run: |
           python -m cibuildwheel --output-dir wheelhouse
         shell: bash
         env:
-           CIBW_ENABLE: cpython-freethreading
            CIBW_ARCHS: "native"
            CIBW_SKIP: "*musllinux*"
            CIBW_TEST_REQUIRES: pytest pytest-httpserver
            CIBW_TEST_COMMAND: pytest {project}/test
            CIBW_BUILD_FRONTEND: build
+           CIBW_CONFIG_SETTINGS_WINDOWS: "build-dir=build/{wheel_tag}"
            CIBW_BEFORE_BUILD_LINUX: yum install -y expat-devel zlib-devel bzip2-devel lz4-devel
            CIBW_ENVIRONMENT_MACOS: MACOSX_DEPLOYMENT_TARGET=11.0 SKBUILD_CMAKE_ARGS=-DWITH_LZ4=OFF
            CIBW_BEFORE_BUILD_WINDOWS: vcpkg install bzip2 expat zlib lz4


=====================================
.github/workflows/ci.yml
=====================================
@@ -7,7 +7,7 @@ jobs:
         runs-on: ubuntu-24.04
 
         steps:
-            - uses: actions/checkout at v6
+            - uses: actions/checkout at v7
 
             - name: Install packages
               run: |
@@ -24,7 +24,7 @@ jobs:
               run: mypy src
 
             - name: Set up Python 3.8
-              uses: actions/setup-python at v6
+              uses: actions/setup-python at v7
               with:
                   python-version: 3.8
 
@@ -35,7 +35,7 @@ jobs:
               shell: bash
 
             - name: Set up Python 3.9
-              uses: actions/setup-python at v6
+              uses: actions/setup-python at v7
               with:
                   python-version: 3.9
 
@@ -46,7 +46,7 @@ jobs:
               shell: bash
 
             - name: Set up Python 3.10
-              uses: actions/setup-python at v6
+              uses: actions/setup-python at v7
               with:
                   python-version: "3.10"
 
@@ -57,7 +57,7 @@ jobs:
               shell: bash
 
             - name: Set up Python 3.11
-              uses: actions/setup-python at v6
+              uses: actions/setup-python at v7
               with:
                   python-version: "3.11"
 
@@ -68,7 +68,7 @@ jobs:
               shell: bash
 
             - name: Set up Python 3.12
-              uses: actions/setup-python at v6
+              uses: actions/setup-python at v7
               with:
                   python-version: "3.12"
 
@@ -79,7 +79,7 @@ jobs:
               shell: bash
 
             - name: Set up Python 3.13
-              uses: actions/setup-python at v6
+              uses: actions/setup-python at v7
               with:
                   python-version: "3.13"
 
@@ -90,10 +90,9 @@ jobs:
               shell: bash
 
             - name: Set up Python 3.14
-              uses: actions/setup-python at v6
+              uses: actions/setup-python at v7
               with:
                   python-version: "3.14"
-                  allow-prereleases: true
 
             - name: Build package 3.14
               run: |
@@ -101,6 +100,18 @@ jobs:
                 python -m build
               shell: bash
 
+            - name: Set up Python 3.15
+              uses: actions/setup-python at v7
+              with:
+                  python-version: "3.15"
+                  allow-prereleases: true
+
+            - name: Build package 3.15
+              run: |
+                pip install build wheel
+                python -m build
+              shell: bash
+
             - name: Upload Artifact
               uses: actions/upload-artifact at v7
               with:
@@ -111,7 +122,7 @@ jobs:
         runs-on: ubuntu-24.04
 
         steps:
-            - uses: actions/checkout at v6
+            - uses: actions/checkout at v7
 
             - name: Install packages
               run: |
@@ -122,7 +133,7 @@ jobs:
                 pipx install flake8
 
             - name: Set up Python 3.13t
-              uses: actions/setup-python at v6
+              uses: actions/setup-python at v7
               with:
                   python-version: "3.13t"
 
@@ -133,7 +144,7 @@ jobs:
               shell: bash
 
             - name: Set up Python 3.14t
-              uses: actions/setup-python at v6
+              uses: actions/setup-python at v7
               with:
                   python-version: "3.14t"
                   allow-prereleases: true
@@ -161,10 +172,10 @@ jobs:
                 python-version: [3.8, 3.9, "3.10", "3.11", "3.12", "3.13"]
 
         steps:
-            - uses: actions/checkout at v6
+            - uses: actions/checkout at v7
 
             - name: Set up Python ${{ matrix.python-version }}
-              uses: actions/setup-python at v6
+              uses: actions/setup-python at v7
               with:
                   python-version: ${{ matrix.python-version }}
                   allow-prereleases: true
@@ -196,13 +207,18 @@ jobs:
         runs-on: ubuntu-24.04
         needs: build-default
 
+        strategy:
+            fail-fast: false
+            matrix:
+                python-version: ["14", "15"]
+
         steps:
-            - uses: actions/checkout at v6
+            - uses: actions/checkout at v7
 
-            - name: Set up Python 3.14
-              uses: actions/setup-python at v6
+            - name: Set up Python 3.${{ matrix.python-version }}
+              uses: actions/setup-python at v7
               with:
-                  python-version: 3.14
+                  python-version: 3.${{ matrix.python-version }}
                   allow-prereleases: true
 
             - uses: actions/download-artifact at v8
@@ -213,7 +229,7 @@ jobs:
               run: |
                 pip install virtualenv
                 virtualenv osmium-test
-                WHEEL=`ls osmium*314-*.whl`
+                WHEEL=`ls osmium*3${{ matrix.python-version }}-*.whl`
                 ./osmium-test/bin/pip install ${WHEEL}
                 ./osmium-test/bin/pip install pytest pytest-httpserver pytest-run-parallel
               shell: bash
@@ -237,10 +253,10 @@ jobs:
                 python-version: ["3.13t", "3.14t"]
 
         steps:
-            - uses: actions/checkout at v6
+            - uses: actions/checkout at v7
 
             - name: Set up Python ${{ matrix.python-version }}
-              uses: actions/setup-python at v6
+              uses: actions/setup-python at v7
               with:
                   python-version: ${{ matrix.python-version }}
                   allow-prereleases: true
@@ -316,7 +332,7 @@ jobs:
             CXX: ${{ matrix.cxx }}
 
         steps:
-            - uses: actions/checkout at v6
+            - uses: actions/checkout at v7
 
             - name: Clean up build environment
               run: |
@@ -337,7 +353,7 @@ jobs:
               shell: bash
               if: ${{ matrix.flavour == 'macos' }}
 
-            - uses: actions/setup-python at v6
+            - uses: actions/setup-python at v7
               with:
                   python-version: "${{ matrix.python }}"
                   allow-prereleases: true
@@ -394,9 +410,9 @@ jobs:
             VCPKG_DEFAULT_BINARY_CACHE: C:/vcpkg_binary_cache
 
         steps:
-            - uses: actions/checkout at v6
+            - uses: actions/checkout at v7
 
-            - uses: actions/cache at v5
+            - uses: actions/cache at v6
               with:
                   path: |
                     C:/vcpkg_binary_cache
@@ -407,97 +423,110 @@ jobs:
               shell: bash
 
             - name: Install packages
-              run: vcpkg install bzip2:x64-windows expat:x64-windows zlib:x64-windows lz4:x86-windows
+              run: vcpkg install bzip2 expat zlib lz4
               shell: bash
 
             - name: Set up Python 3.8
-              uses: actions/setup-python at v6
+              uses: actions/setup-python at v7
               with:
                   python-version: 3.8
 
             - name: Build package 3.8
               run: |
                 pip install build wheel
-                python -m build
+                python -m build -C build-dir="$GITHUB_WORKSPACE/build/{state}-{wheel_tag}"
               shell: bash
               env:
                   CMAKE_TOOLCHAIN_FILE: C:/vcpkg/scripts/buildsystems/vcpkg.cmake
 
             - name: Set up Python 3.9
-              uses: actions/setup-python at v6
+              uses: actions/setup-python at v7
               with:
                   python-version: 3.9
 
             - name: Build package 3.9
               run: |
                 pip install build wheel
-                python -m build
+                python -m build -C build-dir="$GITHUB_WORKSPACE/build/{state}-{wheel_tag}"
               shell: bash
               env:
                   CMAKE_TOOLCHAIN_FILE: C:/vcpkg/scripts/buildsystems/vcpkg.cmake
 
             - name: Set up Python 3.10
-              uses: actions/setup-python at v6
+              uses: actions/setup-python at v7
               with:
                   python-version: "3.10"
 
             - name: Build package 3.10
               run: |
                 pip install build wheel
-                python -m build
+                python -m build -C build-dir="$GITHUB_WORKSPACE/build/{state}-{wheel_tag}"
               shell: bash
               env:
                   CMAKE_TOOLCHAIN_FILE: C:/vcpkg/scripts/buildsystems/vcpkg.cmake
 
             - name: Set up Python 3.11
-              uses: actions/setup-python at v6
+              uses: actions/setup-python at v7
               with:
                   python-version: "3.11"
 
             - name: Build package 3.11
               run: |
                 pip install build wheel
-                python -m build
+                python -m build -C build-dir="$GITHUB_WORKSPACE/build/{state}-{wheel_tag}"
               shell: bash
               env:
                   CMAKE_TOOLCHAIN_FILE: C:/vcpkg/scripts/buildsystems/vcpkg.cmake
 
             - name: Set up Python 3.12
-              uses: actions/setup-python at v6
+              uses: actions/setup-python at v7
               with:
                   python-version: "3.12"
 
             - name: Build package 3.12
               run: |
                 pip install build wheel
-                python -m build
+                python -m build -C build-dir="$GITHUB_WORKSPACE/build/{state}-{wheel_tag}"
               shell: bash
               env:
                   CMAKE_TOOLCHAIN_FILE: C:/vcpkg/scripts/buildsystems/vcpkg.cmake
 
             - name: Set up Python 3.13
-              uses: actions/setup-python at v6
+              uses: actions/setup-python at v7
               with:
                   python-version: "3.13"
 
             - name: Build package 3.13
               run: |
                 pip install build wheel
-                python -m build
+                python -m build -C build-dir="$GITHUB_WORKSPACE/build/{state}-{wheel_tag}"
               shell: bash
               env:
                   CMAKE_TOOLCHAIN_FILE: C:/vcpkg/scripts/buildsystems/vcpkg.cmake
 
             - name: Set up Python 3.14
-              uses: actions/setup-python at v6
+              uses: actions/setup-python at v7
               with:
                   python-version: "3.14"
-                  allow-prereleases: true
 
             - name: Build package 3.14
               run: |
                 pip install build wheel
-                python -m build
+                python -m build -C build-dir="$GITHUB_WORKSPACE/build/{state}-{wheel_tag}"
+              shell: bash
+              env:
+                  CMAKE_TOOLCHAIN_FILE: C:/vcpkg/scripts/buildsystems/vcpkg.cmake
+
+            - name: Set up Python 3.15
+              uses: actions/setup-python at v7
+              with:
+                  python-version: "3.15"
+                  allow-prereleases: true
+
+            - name: Build package 3.15
+              run: |
+                pip install build wheel
+                python -m build -C build-dir="$GITHUB_WORKSPACE/build/{state}-{wheel_tag}"
               shell: bash
               env:
                   CMAKE_TOOLCHAIN_FILE: C:/vcpkg/scripts/buildsystems/vcpkg.cmake
@@ -520,9 +549,9 @@ jobs:
             VCPKG_DEFAULT_BINARY_CACHE: C:/vcpkg_binary_cache
 
         steps:
-            - uses: actions/checkout at v6
+            - uses: actions/checkout at v7
 
-            - uses: actions/cache at v5
+            - uses: actions/cache at v6
               with:
                   path: |
                     C:/vcpkg_binary_cache
@@ -534,24 +563,24 @@ jobs:
 
             - name: Install packages
               run: |
-                vcpkg install bzip2:x64-windows expat:x64-windows zlib:x64-windows lz4:x86-windows
+                vcpkg install bzip2 expat zlib lz4
               shell: bash
 
             - name: Set up Python 3.13t
-              uses: actions/setup-python at v6
+              uses: actions/setup-python at v7
               with:
                   python-version: "3.13t"
 
             - name: Build package 3.13t
               run: |
                 pip install build wheel
-                python -m build
+                python -m build -C build-dir="$GITHUB_WORKSPACE/build/{state}-{wheel_tag}"
               shell: bash
               env:
                   CMAKE_TOOLCHAIN_FILE: C:/vcpkg/scripts/buildsystems/vcpkg.cmake
 
             - name: Set up Python 3.14t
-              uses: actions/setup-python at v6
+              uses: actions/setup-python at v7
               with:
                   python-version: "3.14t"
                   allow-prereleases: true
@@ -559,7 +588,7 @@ jobs:
             - name: Build package 3.14t
               run: |
                 pip install build wheel
-                python -m build
+                python -m build -C build-dir="$GITHUB_WORKSPACE/build/{state}-{wheel_tag}"
               shell: bash
               env:
                   CMAKE_TOOLCHAIN_FILE: C:/vcpkg/scripts/buildsystems/vcpkg.cmake
@@ -589,10 +618,10 @@ jobs:
             PYTEST_ADDOPTS: ${{ matrix.test-args }}
 
         steps:
-            - uses: actions/checkout at v6
+            - uses: actions/checkout at v7
 
             - name: Set up Python ${{ matrix.python-version }}
-              uses: actions/setup-python at v6
+              uses: actions/setup-python at v7
               with:
                   python-version: ${{ matrix.python-version }}
                   allow-prereleases: true
@@ -647,10 +676,10 @@ jobs:
             PYTEST_ADDOPTS: ${{ matrix.test-args }}
 
         steps:
-            - uses: actions/checkout at v6
+            - uses: actions/checkout at v7
 
             - name: Set up Python ${{ matrix.python-version }}
-              uses: actions/setup-python at v6
+              uses: actions/setup-python at v7
               with:
                   python-version: ${{ matrix.python-version }}
                   allow-prereleases: true
@@ -668,7 +697,7 @@ jobs:
               shell: bash
               env:
                 PYVER: ${{ matrix.python-version }}
-              if: matrix.python-version != '3.14t'
+              if: matrix.python-version != '3.13t'
 
             - name: Install osmium (without shapely)
               run: |
@@ -680,7 +709,7 @@ jobs:
               shell: bash
               env:
                 PYVER: ${{ matrix.python-version }}
-              if: matrix.python-version == '3.14t'
+              if: matrix.python-version == '3.13t'
 
             - name: Run tests
               run: |


=====================================
CHANGELOG.md
=====================================
@@ -4,6 +4,23 @@
 All notable changes to this project will be documented in this file.
 This project adheres to [Semantic Versioning](http://semver.org/).
 
+## [4.3.2] - 2026-10-18
+
+### Added
+
+- support for Python 3.15
+
+### Fixed
+
+- MergeInputReader drops objects when IDs collide across OSM types
+- segfault when OSM object constructor is interrupted (thanks @t-miller)
+- bad variable in log output during replication (thanks @xovishnukosuri)
+
+### Changed
+
+- avoid double slashes in replication URLs (thanks @amandasaurus)
+- updated to protozero 1.8.2
+
 ## [4.3.1] - 2026-04-01
 
 ### Fixed


=====================================
CMakeLists.txt
=====================================
@@ -25,7 +25,7 @@ FetchContent_Declare(libosmium
                      GIT_SUBMODULES_RECURSE OFF)
 FetchContent_Declare(protozero
                      GIT_REPOSITORY https://github.com/mapbox/protozero
-                     GIT_TAG 89a55ad2962cca3adbe8383a4b6d9a8411352ef2 # release 1.8.1
+                     GIT_TAG af2f6e274e0a873a00e34d8c9ab99fca76898047 # release 1.8.2
                      SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/contrib/protozero
                      SOURCE_SUBDIR cmake
                      GIT_SUBMODULES_RECURSE OFF)


=====================================
README.md
=====================================
@@ -79,7 +79,7 @@ Create a virtualenv with scikit-build-core and pybind11 preinstalled:
 
 Now compile pyosmium with:
 
-    /tmp/dev-venv/bin/pip --no-build-isolation --config-settings=editable.rebuild=true -Cbuild-dir=/tmp/build -ve.
+    /tmp/dev-venv/bin/pip install --no-build-isolation --config-settings=editable.rebuild=true -Cbuild-dir=/tmp/build -ve.
 
 
 ## Examples


=====================================
cmake/FindOsmium.cmake
=====================================
@@ -30,7 +30,6 @@
 #      pbf        - include libraries needed for PBF input and output
 #      xml        - include libraries needed for XML input and output
 #      io         - include libraries needed for any type of input/output
-#      geos       - include if you want to use any of the GEOS functions
 #      gdal       - include if you want to use any of the OGR functions
 #      lz4        - include support for LZ4 compression of PBF files
 #
@@ -165,22 +164,6 @@ list(APPEND OSMIUM_LIBRARIES
     ${OSMIUM_IO_LIBRARIES}
 )
 
-#----------------------------------------------------------------------
-# Component 'geos'
-if(Osmium_USE_GEOS)
-    find_path(GEOS_INCLUDE_DIR geos/geom.h)
-    find_library(GEOS_LIBRARY NAMES geos)
-
-    list(APPEND OSMIUM_EXTRA_FIND_VARS GEOS_INCLUDE_DIR GEOS_LIBRARY)
-    if(GEOS_INCLUDE_DIR AND GEOS_LIBRARY)
-        SET(GEOS_FOUND 1)
-        list(APPEND OSMIUM_LIBRARIES ${GEOS_LIBRARY})
-        list(APPEND OSMIUM_INCLUDE_DIRS ${GEOS_INCLUDE_DIR})
-    else()
-        message(WARNING "Osmium: GEOS library is required but not found, please install it or configure the paths.")
-    endif()
-endif()
-
 #----------------------------------------------------------------------
 # Component 'gdal' (alias 'ogr')
 if(Osmium_USE_GDAL)
@@ -276,11 +259,7 @@ if(MSVC)
 endif()
 
 if(APPLE AND "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
-# following only available from cmake 2.8.12:
-#   add_compile_options(-stdlib=libc++)
-# so using this instead:
-    add_definitions(-stdlib=libc++)
-    set(LDFLAGS ${LDFLAGS} -stdlib=libc++)
+    add_compile_options(-stdlib=libc++)
 endif()
 
 #----------------------------------------------------------------------


=====================================
debian/changelog
=====================================
@@ -1,3 +1,17 @@
+pyosmium (4.3.2-1~bpo13+1) trixie-backports; urgency=medium
+
+  * Rebuild for trixie-backports.
+
+ -- Bas Couwenberg <sebastic at debian.org>  Wed, 21 Oct 2026 05:47:01 +0200
+
+pyosmium (4.3.2-1) unstable; urgency=medium
+
+  * New upstream release.
+  * Bump Standards-Version to 4.7.4, no changes.
+  * Require libosmium2-dev 2.23.1 for replication fix.
+
+ -- Bas Couwenberg <sebastic at debian.org>  Sun, 18 Oct 2026 17:20:20 +0200
+
 pyosmium (4.3.1-1~bpo13+1) trixie-backports; urgency=medium
 
   * Rebuild for trixie-backports.


=====================================
debian/control
=====================================
@@ -19,7 +19,7 @@ Build-Depends: architecture-is-64-bit,
                python3-scikit-build-core,
                python3-shapely <!nocheck>,
                python3-werkzeug <!nocheck>
-Standards-Version: 4.7.3
+Standards-Version: 4.7.4
 Vcs-Browser: https://salsa.debian.org/debian-gis-team/pyosmium/
 Vcs-Git: https://salsa.debian.org/debian-gis-team/pyosmium.git -b trixie-backports
 Homepage: https://osmcode.org/pyosmium/


=====================================
docs/man/pyosmium-get-changes.1
=====================================
@@ -1,4 +1,4 @@
-.TH PYOSMIUM\-GET\-CHANGES "1" "2026\-04\-01" "pyosmium 4.3.1" "Generated Python Manual"
+.TH PYOSMIUM\-GET\-CHANGES "1" "2026\-10\-18" "pyosmium 4.3.2" "Generated Python Manual"
 .SH NAME
 pyosmium\-get\-changes
 .SH SYNOPSIS


=====================================
docs/man/pyosmium-up-to-date.1
=====================================
@@ -1,4 +1,4 @@
-.TH PYOSMIUM\-UP\-TO\-DATE "1" "2026\-04\-01" "pyosmium 4.3.1" "Generated Python Manual"
+.TH PYOSMIUM\-UP\-TO\-DATE "1" "2026\-10\-18" "pyosmium 4.3.2" "Generated Python Manual"
 .SH NAME
 pyosmium\-up\-to\-date
 .SH SYNOPSIS


=====================================
lib/merge_input_reader.cc
=====================================
@@ -33,6 +33,7 @@ namespace {
     class copy_first_with_id {
         osmium::io::Writer* writer;
         osmium::object_id_type id = 0;
+        osmium::item_type type = osmium::item_type::undefined;
 
     public:
         using iterator_category = std::output_iterator_tag;
@@ -44,11 +45,12 @@ namespace {
         }
 
         void push_back(const osmium::OSMObject& obj) {
-            if (obj.id() != id) {
+            if (obj.id() != id || obj.type() != type) {
                 if (obj.visible()) {
                     (*writer)(obj);
                 }
                 id = obj.id();
+                type = obj.type();
             }
         }
 
@@ -67,7 +69,7 @@ public:
             osmium::item_type prev_type = osmium::item_type::undefined;
             osmium::object_id_type prev_id = 0;
             for (auto &item: objects) {
-                if (item.type() != prev_type || item.id() != prev_id) {
+                if (item.id() != prev_id || item.type() != prev_type) {
                     prev_type = item.type();
                     prev_id = item.id();
                     pyosmium::apply_item(item, handler);


=====================================
lib/osm_base_objects.h
=====================================
@@ -2,7 +2,7 @@
  *
  * This file is part of pyosmium. (https://osmcode.org/pyosmium/)
  *
- * Copyright (C) 2024 Sarah Hoffmann <lonvia at denofr.de> and others.
+ * Copyright (C) 2026 Sarah Hoffmann <lonvia at denofr.de> and others.
  * For a full list of authors see the git log.
  */
 #ifndef PYOSMIUM_OSM_BASE_OBJECTS_HPP
@@ -73,7 +73,6 @@ public:
     pybind11::object get_or_create_python_object()
     {
         if (!m_valid) {
-            m_valid = true;
             if constexpr (std::is_same_v<T, osmium::Node>) {
                 m_pyobj = pybind11::module_::import("osmium.osm.types").attr("Node")(COSMNode{m_obj});
             } else if constexpr (std::is_same_v<T, osmium::Way>) {
@@ -85,6 +84,7 @@ public:
             } else if constexpr (std::is_same_v<T, osmium::Changeset>) {
                 m_pyobj = pybind11::module_::import("osmium.osm.types").attr("Changeset")(COSMChangeset{m_obj});
             }
+            m_valid = true;
         }
 
         return m_pyobj;


=====================================
pyproject.toml
=====================================
@@ -4,7 +4,7 @@ build-backend = "scikit_build_core.build"
 
 [project]
 name = "osmium"
-version = "4.3.1"
+version = "4.3.2"
 description = "Python bindings for libosmium, the data processing library for OSM data"
 requires-python = ">=3.8"
 readme = "README.rst"


=====================================
src/osmium/replication/server.py
=====================================
@@ -2,7 +2,7 @@
 #
 # This file is part of pyosmium. (https://osmcode.org/pyosmium/)
 #
-# Copyright (C) 2025 Sarah Hoffmann <lonvia at denofr.de> and others.
+# Copyright (C) 2026 Sarah Hoffmann <lonvia at denofr.de> and others.
 # For a full list of authors see the git log.
 """ Helper functions to communicate with replication servers.
 """
@@ -64,8 +64,7 @@ class ReplicationServer:
             state. If the replication service serves something other
             than osc.gz files, set the `diff_type` to the given file suffix.
         """
-
-        self.baseurl = url
+        self.baseurl = url.rstrip('/') + '/'
         self.diff_type = diff_type
         self.extra_request_params: Dict[str, Any] = dict(timeout=60, stream=True)
         self.session: Optional[requests.Session] = None
@@ -484,15 +483,15 @@ class ReplicationServer:
             service.
         """
         if seq is None:
-            return self.baseurl + '/state.txt'
+            return self.baseurl + 'state.txt'
 
-        return '%s/%03i/%03i/%03i.state.txt' % \
+        return '%s%03i/%03i/%03i.state.txt' % \
                (self.baseurl, seq / 1000000, (seq % 1000000) / 1000, seq % 1000)
 
     def get_diff_url(self, seq: int) -> str:
         """ Returns the URL to the diff file for the given sequence id.
         """
-        return '%s/%03i/%03i/%03i.%s' % \
+        return '%s%03i/%03i/%03i.%s' % \
                (self.baseurl,
                 seq / 1000000, (seq % 1000000) / 1000, seq % 1000,
                 self.diff_type)


=====================================
src/osmium/replication/utils.py
=====================================
@@ -2,7 +2,7 @@
 #
 # This file is part of pyosmium. (https://osmcode.org/pyosmium/)
 #
-# Copyright (C) 2025 Sarah Hoffmann <lonvia at denofr.de> and others.
+# Copyright (C) 2026 Sarah Hoffmann <lonvia at denofr.de> and others.
 # For a full list of authors see the git log.
 """ Helper functions for change file handling. """
 from typing import NamedTuple, Optional
@@ -57,7 +57,7 @@ def get_replication_header(fname: str) -> ReplicationHeader:
                     LOG.warning("Sequence id '%d' in OSM file header is negative. Ignored.", seq)
                     seq = None
             except ValueError:
-                LOG.warning("Sequence id '%s' in OSM file header is not a number. Ignored.", seq)
+                LOG.warning("Sequence id '%s' in OSM file header is not a number. Ignored.", seqstr)
                 seq = None
         else:
             seq = None


=====================================
test/test_constructor_interruption.py
=====================================
@@ -0,0 +1,54 @@
+# SPDX-License-Identifier: BSD-2-Clause
+#
+# This file is part of pyosmium. (https://osmcode.org/pyosmium/)
+# Copyright (C) 2026 Sarah Hoffmann <lonvia at denofr.de> and others.
+# For a full list of authors see the git log.
+import multiprocessing
+import sys
+
+import pytest
+import osmium
+
+
+def run_interrupted_read(pipe, object_type, opl, exception_type):
+    constructor = object_type.__init__.__code__
+
+    def fail_constructor(frame, event, arg):
+        if event == 'call' and frame.f_code is constructor:
+            sys.settrace(None)
+            raise exception_type('injected constructor failure')
+        return fail_constructor
+
+    sys.settrace(fail_constructor)
+    try:
+        list(osmium.FileProcessor(osmium.io.FileBuffer(opl.encode('utf-8'), 'opl')))
+    except exception_type:
+        sys.settrace(None)
+        pipe.send(str(exception_type))
+    else:
+        pipe.send('constructor was not reached')
+
+
+ at pytest.mark.thread_unsafe
+ at pytest.mark.parametrize('object_type', [osmium.osm.Node, osmium.osm.Way, osmium.osm.Relation])
+ at pytest.mark.parametrize('exception', [KeyboardInterrupt, MemoryError, RuntimeError])
+def test_constructor_exception_does_not_crash_cleanup(to_opl, object_type, exception):
+    data = to_opl("""\
+        n1 x5 y5
+        w1 Nn1,n2
+        r1 Mn1@
+    """)
+
+    parent_conn, child_conn = multiprocessing.Pipe()
+    ctx = multiprocessing.get_context('spawn')
+    p = ctx.Process(target=run_interrupted_read,
+                    args=[child_conn, object_type, data, exception])
+    p.start()
+
+    assert parent_conn.poll(2)
+    assert parent_conn.recv() == str(exception)
+
+    p.join(2)
+
+    assert p.exitcode == 0, f"Segmentation fault ({-p.exitcode})" if p.exitcode < 0 \
+                            else f"Test exited with error {p.exitcode}"


=====================================
test/test_merge_input_reader.py
=====================================
@@ -99,3 +99,79 @@ def test_multibuffer_simplify(adder, tmp_path):
     mir.apply(h, simplify=True)
 
     assert h.data == ['N1/1', 'N2/1', 'W3/2']
+
+
+def test_simplify_same_id_different_object(tmp_path):
+    mir = osmium.MergeInputReader()
+
+    opls = ["""\
+            n1 v1 x1 y1
+            n2 v1 x90 y45
+            w1 v1 Nn1,n2
+            r1 v1 Mw1@
+            """,
+            """\
+            r1 v2 Mw1@ Thello=world
+            """]
+
+    for opl in opls:
+        add_as_file(mir, opl, tmp_path)
+
+    h = ListHandler()
+    mir.apply(h, simplify=True)
+
+    assert h.data == ['N1/1', 'N2/1', 'W1/1', 'R1/2']
+
+
+def test_apply_to_reader_nohistory(test_data, tmp_path):
+    fn = test_data("""\
+            n1 v1 x1 y1
+            n2 v1 x90 y45
+            w1 v1 Nn1,n2
+            r1 v1 Mw1@
+            """)
+
+    outfn = tmp_path / 'outfile_apply_to_reader_nohistory.opl'
+
+    reader = osmium.io.Reader(fn)
+    writer = osmium.io.Writer(outfn)
+
+    mir = osmium.MergeInputReader()
+    add_as_buffer(mir, "r1 v2 Mw1@ Thello=world", tmp_path)
+
+    mir.apply_to_reader(reader, writer, False)
+
+    reader.close()
+    writer.close()
+
+    h = ListHandler()
+    osmium.apply(outfn, h)
+
+    assert h.data == ['N1/1', 'N2/1', 'W1/1', 'R1/2']
+
+
+def test_apply_to_reader_with_history(test_data, tmp_path):
+    fn = test_data("""\
+            n1 v1 x1 y1
+            n2 v1 x90 y45
+            w1 v1 Nn1,n2
+            r1 v1 Mw1@
+            """)
+
+    outfn = tmp_path / 'outfile_apply_to_reader_nohistory.opl'
+
+    reader = osmium.io.Reader(fn)
+    writer = osmium.io.Writer(outfn)
+
+    mir = osmium.MergeInputReader()
+    add_as_buffer(mir, "r1 v2 Mw1@ Thello=world", tmp_path)
+
+    mir.apply_to_reader(reader, writer, True)
+
+    reader.close()
+    writer.close()
+
+    h = ListHandler()
+    osmium.apply(outfn, h)
+
+    assert h.data == ['N1/1', 'N2/1', 'W1/1', 'R1/1', 'R1/2']


=====================================
test/test_replication.py
=====================================
@@ -2,7 +2,7 @@
 #
 # This file is part of pyosmium. (https://osmcode.org/pyosmium/)
 #
-# Copyright (C) 2025 Sarah Hoffmann <lonvia at denofr.de> and others.
+# Copyright (C) 2026 Sarah Hoffmann <lonvia at denofr.de> and others.
 # For a full list of authors see the git log.
 import logging
 import time
@@ -22,30 +22,52 @@ import osmium.replication
 pytestmark = [pytest.mark.thread_unsafe, pytest.mark.iterations(1)]
 
 
- at pytest.mark.parametrize("inp,outp", [
-        (None,      'https://text.org/state.txt'),
-        (1,         'https://text.org/000/000/001.state.txt'),
-        (999,       'https://text.org/000/000/999.state.txt'),
-        (1000,      'https://text.org/000/001/000.state.txt'),
-        (573923,    'https://text.org/000/573/923.state.txt'),
-        (3290012,   'https://text.org/003/290/012.state.txt'),
+ at pytest.mark.parametrize("baseurl,inp,outp", [
+        ("https://text.org",  None,      'https://text.org/state.txt'),
+        ("https://text.org",  1,         'https://text.org/000/000/001.state.txt'),
+        ("https://text.org",  999,       'https://text.org/000/000/999.state.txt'),
+        ("https://text.org",  1000,      'https://text.org/000/001/000.state.txt'),
+        ("https://text.org",  573923,    'https://text.org/000/573/923.state.txt'),
+        ("https://text.org",  3290012,   'https://text.org/003/290/012.state.txt'),
+
+        ("https://text.org/",  None,      'https://text.org/state.txt'),
+        ("https://text.org/",  1,         'https://text.org/000/000/001.state.txt'),
+        ("https://text.org//", None,      'https://text.org/state.txt'),
+        ("https://text.org//", 1,         'https://text.org/000/000/001.state.txt'),
+
+        ("https://text.org/area-updates",    None,
+         'https://text.org/area-updates/state.txt'),
+        ("https://text.org/area-updates",    3290012,
+         'https://text.org/area-updates/003/290/012.state.txt'),
+        ("https://text.org/area-updates/",   None,
+         'https://text.org/area-updates/state.txt'),
+        ("https://text.org/area-updates/",   3290012,
+         'https://text.org/area-updates/003/290/012.state.txt'),
+        ("https://text.org/area-updates//",  None,
+         'https://text.org/area-updates/state.txt'),
+        ("https://text.org/area-updates//",  3290012,
+         'https://text.org/area-updates/003/290/012.state.txt'),
+        ("https://text.org/area-updates///", 3290012,
+         'https://text.org/area-updates/003/290/012.state.txt'),
     ])
-def test_get_state_url(inp, outp):
-    svr = rserv.ReplicationServer("https://text.org")
+def test_get_state_url(baseurl, inp, outp):
+    svr = rserv.ReplicationServer(baseurl)
 
     assert outp == svr.get_state_url(inp)
 
 
- at pytest.mark.parametrize("inp,outp", [
-        (1,         'https://who.is/me//000/000/001.osc.gz'),
-        (500,       'https://who.is/me//000/000/500.osc.gz'),
-        (83750,     'https://who.is/me//000/083/750.osc.gz'),
-        (999999999, 'https://who.is/me//999/999/999.osc.gz'),
+ at pytest.mark.parametrize("baseurl,inp,outp", [
+        ("https://who.is/me/", 1,         'https://who.is/me/000/000/001.osc.gz'),
+        ("https://who.is/me/", 500,       'https://who.is/me/000/000/500.osc.gz'),
+        ("https://who.is/me/", 83750,     'https://who.is/me/000/083/750.osc.gz'),
+        ("https://who.is/me/", 999999999, 'https://who.is/me/999/999/999.osc.gz'),
+
+        ("https://who.is/me",  999999999, 'https://who.is/me/999/999/999.osc.gz'),
     ])
-def test_get_diff_url(inp, outp):
-    svr = rserv.ReplicationServer("https://who.is/me/")
+def test_get_diff_url(baseurl, inp, outp):
+    svr = rserv.ReplicationServer(baseurl)
 
-    assert outp, svr.get_diff_url(inp)
+    assert outp == svr.get_diff_url(inp)
 
 
 @pytest.mark.parametrize("as_string", [True, False])


=====================================
test/test_replication_utils.py
=====================================
@@ -2,8 +2,13 @@
 #
 # This file is part of pyosmium. (https://osmcode.org/pyosmium/)
 #
-# Copyright (C) 2025 Sarah Hoffmann <lonvia at denofr.de> and others.
+# Copyright (C) 2026 Sarah Hoffmann <lonvia at denofr.de> and others.
 # For a full list of authors see the git log.
+import logging
+
+import pytest
+
+import osmium
 import osmium.replication.utils as rutil
 
 from helpers import mkdate
@@ -20,8 +25,28 @@ def test_get_replication_header_empty(tmp_path):
 
 
 def test_get_replication_header_full(test_data_dir):
-    val = rutil.get_replication_header(str(test_data_dir / 'example-test.pbf'))
+    val = rutil.get_replication_header(test_data_dir / 'example-test.pbf')
 
     assert val.url == 'http://download.geofabrik.de/europe/andorra-updates'
     assert val.sequence == 2167
     assert val.timestamp == mkdate(2019, 2, 23, 21, 15, 2)
+
+
+ at pytest.mark.parametrize("inseq, error", [("not-a-number", "OSM file header is not a number"),
+                                          ("-5", "OSM file header is negative")])
+def test_get_replication_header_invalid_sequence(test_data_dir, caplog, monkeypatch,
+                                                 inseq, error):
+    h = osmium.io.Header()
+    h.set("osmosis_replication_base_url", "https://example.com/replication")
+    h.set("osmosis_replication_sequence_number", inseq)
+    h.set("osmosis_replication_timestamp", "2024-01-01T00:00:00Z")
+
+    monkeypatch.setattr(osmium.io.Reader, "header", lambda _: h)
+
+    with caplog.at_level(logging.WARNING, logger='pyosmium'):
+        val = rutil.get_replication_header(test_data_dir / 'example-test.pbf')
+
+    assert val.url == 'https://example.com/replication'
+    assert val.sequence is None
+    assert val.timestamp == mkdate(2024, 1, 1, 0, 0, 0)
+    assert error in caplog.text



View it on GitLab: https://salsa.debian.org/debian-gis-team/pyosmium/-/compare/f63390e45de1443e5c265afa273e5cb27e87d46f...88f6673bc901d6f19a033c01348e3f9dc7e7e611

-- 
View it on GitLab: https://salsa.debian.org/debian-gis-team/pyosmium/-/compare/f63390e45de1443e5c265afa273e5cb27e87d46f...88f6673bc901d6f19a033c01348e3f9dc7e7e611
You're receiving this email because of your account on salsa.debian.org. Manage all notifications: https://salsa.debian.org/-/profile/notifications | Help: https://salsa.debian.org/help


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


More information about the Pkg-grass-devel mailing list