Skip to content

Commit bb94304

Browse files
authored
Merge pull request #313 from lonvia/remove-boost-dependency
Replace boost iterator with simple standard C++ iteration
2 parents c123e69 + 8cc9d7b commit bb94304

File tree

8 files changed

+124
-32
lines changed

8 files changed

+124
-32
lines changed

.github/workflows/build_wheels.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,10 @@ jobs:
4444
CIBW_TEST_REQUIRES: pytest pytest-httpserver
4545
CIBW_TEST_COMMAND: pytest {project}/test
4646
CIBW_BUILD_FRONTEND: build
47-
CIBW_BEFORE_BUILD_LINUX: yum install -y expat-devel boost-devel zlib-devel bzip2-devel lz4-devel
48-
CIBW_BEFORE_BUILD_MACOS: brew install boost
47+
CIBW_BEFORE_BUILD_LINUX: yum install -y expat-devel zlib-devel bzip2-devel lz4-devel
48+
CIBW_BEFORE_BUILD_MACOS: brew install
4949
CIBW_ENVIRONMENT_MACOS: MACOSX_DEPLOYMENT_TARGET=11.0 SKBUILD_CMAKE_ARGS=-DWITH_LZ4=OFF
50-
CIBW_BEFORE_BUILD_WINDOWS: vcpkg install bzip2 expat zlib boost-variant boost-iterator lz4
50+
CIBW_BEFORE_BUILD_WINDOWS: vcpkg install bzip2 expat zlib lz4
5151
CIBW_ENVIRONMENT_WINDOWS: 'CMAKE_TOOLCHAIN_FILE="C:/vcpkg/scripts/buildsystems/vcpkg.cmake"'
5252
CIBW_REPAIR_WHEEL_COMMAND_WINDOWS: 'pipx run delvewheel repair --add-path ${{ matrix.vcpkg }}/bin/ --add-path ${{ matrix.vcpkg }}/debug/bin -w {dest_dir} {wheel}'
5353

.github/workflows/ci.yml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ jobs:
1212
- name: Install packages
1313
run: |
1414
sudo apt-get update -y -qq
15-
sudo apt-get install -y -qq libboost-dev libexpat1-dev zlib1g-dev libbz2-dev libproj-dev libgeos-dev liblz4-dev pipx
15+
sudo apt-get install -y -qq libexpat1-dev zlib1g-dev libbz2-dev libproj-dev libgeos-dev liblz4-dev pipx
1616
pipx install mypy
1717
pipx inject mypy types-requests
1818
pipx install flake8
@@ -116,7 +116,7 @@ jobs:
116116
- name: Install packages
117117
run: |
118118
sudo apt-get update -y -qq
119-
sudo apt-get install -y -qq libboost-dev libexpat1-dev zlib1g-dev libbz2-dev libproj-dev libgeos-dev liblz4-dev pipx
119+
sudo apt-get install -y -qq libexpat1-dev zlib1g-dev libbz2-dev libproj-dev libgeos-dev liblz4-dev pipx
120120
pipx install mypy
121121
pipx inject mypy types-requests
122122
pipx install flake8
@@ -329,11 +329,11 @@ jobs:
329329
- name: Install packages
330330
run: |
331331
sudo apt-get update -y -qq
332-
sudo apt-get install -y -qq libboost-dev libexpat1-dev zlib1g-dev libbz2-dev libproj-dev libgeos-dev liblz4-dev virtualenv
332+
sudo apt-get install -y -qq libexpat1-dev zlib1g-dev libbz2-dev libproj-dev libgeos-dev liblz4-dev virtualenv
333333
if: ${{ matrix.flavour == 'linux' }}
334334

335335
- name: Install packages
336-
run: brew install boost geos virtualenv
336+
run: brew install geos virtualenv
337337
shell: bash
338338
if: ${{ matrix.flavour == 'macos' }}
339339

@@ -404,7 +404,7 @@ jobs:
404404
shell: bash
405405

406406
- name: Install packages
407-
run: vcpkg install bzip2:x64-windows expat:x64-windows zlib:x64-windows boost-variant:x64-windows boost-iterator:x64-windows lz4:x86-windows
407+
run: vcpkg install bzip2:x64-windows expat:x64-windows zlib:x64-windows lz4:x86-windows
408408
shell: bash
409409

410410
- name: Set up Python 3.8
@@ -531,7 +531,7 @@ jobs:
531531

532532
- name: Install packages
533533
run: |
534-
vcpkg install bzip2:x64-windows expat:x64-windows zlib:x64-windows boost-variant:x64-windows boost-iterator:x64-windows lz4:x86-windows
534+
vcpkg install bzip2:x64-windows expat:x64-windows zlib:x64-windows lz4:x86-windows
535535
shell: bash
536536

537537
- name: Set up Python 3.13t

CMakeLists.txt

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,6 @@ endif()
6060

6161
message(STATUS "Building in C++${CMAKE_CXX_STANDARD} mode")
6262

63-
find_package(Boost 1.66 REQUIRED COMPONENTS)
64-
include_directories(SYSTEM ${Boost_INCLUDE_DIRS})
65-
6663
# Modules without any Python code and just one source file.
6764
foreach(PYMOD geom index io area)
6865
pybind11_add_module(${PYMOD} lib/${PYMOD}.cc)

README.md

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,7 @@ For other versions, a source wheel is provided. Make sure to install all
2828
external dependencies first. On Debian/Ubuntu-like systems, the following
2929
command installs all required packages:
3030

31-
sudo apt-get install build-essential cmake libboost-dev \
32-
libexpat1-dev zlib1g-dev libbz2-dev
31+
sudo apt-get install build-essential cmake libexpat1-dev zlib1g-dev libbz2-dev
3332

3433

3534
### Installing from source
@@ -45,16 +44,14 @@ pyosmium has the following dependencies:
4544
* [expat](https://libexpat.github.io/)
4645
* [libz](https://www.zlib.net/)
4746
* [libbz2](https://www.sourceware.org/bzip2/)
48-
* [Boost](https://www.boost.org/) variant and iterator >= 1.70
4947
* [Python Requests](https://docs.python-requests.org/)
5048
* [scikit-build-core](https://scikit-build-core.readthedocs.io)
5149
* a C++17-compatible compiler (Clang 13+, GCC 10+ are supported)
5250

5351

5452
### Compiling from Source
5553

56-
Make sure to install the development packages for expat, libz, libbz2
57-
and boost.
54+
Make sure to install the development packages for expat, libz and libbz2.
5855

5956
The appropriate versions for Libosmium and Protozero will be downloaded into
6057
the `contrib` directory when building the source package:

README.rst

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,10 @@ pyosmium can be installed with pip:
1717

1818
The Pypi source package already comes bundled with a matching version of
1919
libosmium, protozero and pybind11. Pyosmium additionally depends on
20-
expat, libz, libbz2 and Boost variant and iterator. You need to install
20+
expat, libz and libbz2. You need to install
2121
development packages for these libraries. On Debian/Ubuntu do::
2222

23-
sudo apt-get install build-essential cmake libboost-dev \
24-
libexpat1-dev zlib1g-dev libbz2-dev
23+
sudo apt-get install build-essential cmake libexpat1-dev zlib1g-dev libbz2-dev
2524

2625

2726
Python >= 3.8 is supported. Pypy is known not to work.

docs/index.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ the following additional dependencies need to be available:
2828
* [expat](https://libexpat.github.io/)
2929
* [libz](https://www.zlib.net/)
3030
* [libbz2](https://www.sourceware.org/bzip2/)
31-
* [Boost](https://www.boost.org/) variant and iterator >= 1.41
3231
* [Python Requests](https://docs.python-requests.org/en/master/)
3332
* a recent C++ compiler (Clang 3.4+, GCC 4.8+)
3433

@@ -41,7 +40,7 @@ of the build process:
4140
On Debian/Ubuntu-like systems, the following command installs all required
4241
packages:
4342

44-
sudo apt-get install python3-dev build-essential cmake libboost-dev \
43+
sudo apt-get install python3-dev build-essential cmake \
4544
libexpat1-dev zlib1g-dev libbz2-dev
4645

4746
Compatible versions of libosmium and protozero are shipped with the source

lib/merge_input_reader.cc

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,13 @@
22
*
33
* This file is part of pyosmium. (https://osmcode.org/pyosmium/)
44
*
5-
* Copyright (C) 2025 Sarah Hoffmann <lonvia@denofr.de> and others.
5+
* Copyright (C) 2026 Sarah Hoffmann <lonvia@denofr.de> and others.
66
* For a full list of authors see the git log.
77
*/
88
#include <pybind11/pybind11.h>
99

1010
#include <vector>
11-
12-
#include <boost/iterator/function_output_iterator.hpp>
11+
#include <iterator>
1312

1413
#include <osmium/osm/object_comparisons.hpp>
1514
#include <osmium/io/any_input.hpp>
@@ -30,20 +29,21 @@ namespace {
3029
/**
3130
* Copy the first OSM object with a given Id to the output. Keep
3231
* track of the Id of each object to do this.
33-
*
34-
* We are using this functor class instead of a simple lambda, because the
35-
* lambda doesn't build on MSVC.
3632
*/
3733
class copy_first_with_id {
3834
osmium::io::Writer* writer;
3935
osmium::object_id_type id = 0;
4036

4137
public:
38+
using iterator_category = std::output_iterator_tag;
39+
using value_type = const osmium::OSMObject;
40+
using reference = const osmium::OSMObject&;
41+
4242
explicit copy_first_with_id(osmium::io::Writer& w) :
4343
writer(&w) {
4444
}
4545

46-
void operator()(const osmium::OSMObject& obj) {
46+
void push_back(const osmium::OSMObject& obj) {
4747
if (obj.id() != id) {
4848
if (obj.visible()) {
4949
(*writer)(obj);
@@ -112,9 +112,8 @@ class MergeInputReader
112112
std::reverse(objects.ptr_begin(), objects.ptr_end());
113113
objects.sort(osmium::object_order_type_id_reverse_version());
114114

115-
auto output_it = boost::make_function_output_iterator(
116-
copy_first_with_id(*writer.get())
117-
);
115+
copy_first_with_id copy_first{*writer.get()};
116+
auto output_it = std::back_inserter(copy_first);
118117

119118
std::set_union(objects.begin(),
120119
objects.end(),

test/test_merge_input_reader.py

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
# SPDX-License-Identifier: BSD-2-Clause
2+
#
3+
# This file is part of pyosmium. (https://osmcode.org/pyosmium/)
4+
#
5+
# Copyright (C) 2026 Sarah Hoffmann <lonvia@denofr.de> and others.
6+
# For a full list of authors see the git log.
7+
from textwrap import dedent
8+
import uuid
9+
10+
import pytest
11+
12+
import osmium
13+
14+
15+
class ListHandler:
16+
def __init__(self):
17+
self.data = []
18+
19+
def node(self, o):
20+
self.data.append(f"N{o.id}/{o.version}")
21+
22+
def way(self, o):
23+
self.data.append(f"W{o.id}/{o.version}")
24+
25+
def relation(self, o):
26+
self.data.append(f"R{o.id}/{o.version}")
27+
28+
def area(self, _):
29+
assert not "Area handler should not be called"
30+
31+
32+
def add_as_buffer(mir, opl, tmp_path):
33+
mir.add_buffer(dedent(opl).encode('utf-8'), format='opl')
34+
35+
36+
def add_as_file(mir, opl, tmp_path):
37+
fn = tmp_path / (str(uuid.uuid4()) + '.opl')
38+
fn.write_text(dedent(opl))
39+
40+
mir.add_file(str(fn))
41+
42+
43+
@pytest.mark.parametrize('adder', [add_as_buffer, add_as_file])
44+
def test_simple_input(adder, tmp_path):
45+
mir = osmium.MergeInputReader()
46+
47+
opl = """\
48+
n1 v1 x1 y1
49+
w3 v34 Nn1
50+
"""
51+
52+
adder(mir, opl, tmp_path)
53+
54+
h = ListHandler()
55+
mir.apply(h)
56+
57+
assert h.data == ['N1/1', 'W3/34']
58+
59+
60+
@pytest.mark.parametrize('adder', [add_as_buffer, add_as_file])
61+
def test_multibuffer_no_simplify(adder, tmp_path):
62+
mir = osmium.MergeInputReader()
63+
64+
opls = ["""\
65+
n1 v1 x1 y1
66+
w3 v2 Nn1
67+
""",
68+
"""\
69+
n2 v1 x1 y1
70+
w3 v1 Nn2
71+
"""]
72+
73+
for opl in opls:
74+
adder(mir, opl, tmp_path)
75+
76+
h = ListHandler()
77+
mir.apply(h, simplify=False)
78+
79+
assert h.data == ['N1/1', 'N2/1', 'W3/1', 'W3/2']
80+
81+
82+
@pytest.mark.parametrize('adder', [add_as_buffer, add_as_file])
83+
def test_multibuffer_simplify(adder, tmp_path):
84+
mir = osmium.MergeInputReader()
85+
86+
opls = ["""\
87+
n1 v1 x1 y1
88+
w3 v2 Nn1
89+
""",
90+
"""\
91+
n2 v1 x1 y1
92+
w3 v1 Nn2
93+
"""]
94+
95+
for opl in opls:
96+
adder(mir, opl, tmp_path)
97+
98+
h = ListHandler()
99+
mir.apply(h, simplify=True)
100+
101+
assert h.data == ['N1/1', 'N2/1', 'W3/2']

0 commit comments

Comments
 (0)