Skip to content

Commit dc6a194

Browse files
committed
fix: tests
1 parent a7d4e1d commit dc6a194

8 files changed

Lines changed: 1270 additions & 1176 deletions

File tree

build.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import glob
22
import os
33
from subprocess import Popen, PIPE
4-
from distutils import sysconfig
4+
import sysconfig
55

66
Import('env')
77

@@ -10,15 +10,15 @@ def call(cmd, silent=True):
1010
if not stderr:
1111
return stdin.strip()
1212
elif not silent:
13-
print stderr
13+
print(stderr)
1414

1515

1616
prefix = env['PREFIX']
17-
target_path = os.path.normpath(sysconfig.get_python_lib() + os.path.sep + env['MAPNIK_NAME'])
17+
target_path = os.path.normpath(sysconfig.get_path('purelib') + os.path.sep + env['MAPNIK_NAME'])
1818

1919
py_env = env.Clone()
2020

21-
py_env.Append(CPPPATH = sysconfig.get_python_inc())
21+
py_env.Append(CPPPATH = sysconfig.get_path('include'))
2222

2323
py_env.Append(CPPDEFINES = env['LIBMAPNIK_DEFINES'])
2424

@@ -63,12 +63,12 @@ def call(cmd, silent=True):
6363
if not os.path.exists(env['MAPNIK_NAME']):
6464
os.mkdir(env['MAPNIK_NAME'])
6565

66-
file('mapnik/paths.py','w').write(paths % (env['MAPNIK_LIB_DIR']))
66+
open('mapnik/paths.py', 'w', encoding='utf-8').write(paths % (env['MAPNIK_LIB_DIR']))
6767

6868
# force open perms temporarily so that `sudo scons install`
6969
# does not later break simple non-install non-sudo rebuild
7070
try:
71-
os.chmod('mapnik/paths.py',0666)
71+
os.chmod('mapnik/paths.py', 0o666)
7272
except: pass
7373

7474
# install the shared object beside the module directory
@@ -89,7 +89,7 @@ def call(cmd, silent=True):
8989
env.Command( targetp, 'mapnik/paths.py',
9090
[
9191
Copy("$TARGET","$SOURCE"),
92-
Chmod("$TARGET", 0644),
92+
Chmod("$TARGET", 0o644),
9393
])
9494

9595
if 'uninstall' not in COMMAND_LINE_TARGETS:

packaging/mapnik/__init__.py

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -67,19 +67,31 @@ def bootstrap_env():
6767
# In some build/test setups the compiled extension can be imported under the
6868
# top-level name `_mapnik` (e.g. due to sys.path/build output layout) and then
6969
# again as `mapnik._mapnik`. Loading the same pybind11 extension twice in one
70-
# interpreter can raise errors like:
71-
# pybind11::native_enum<...>("CompositeOp") is already registered!
72-
# If a compatible `_mapnik` is already loaded, alias it to the canonical
73-
# `mapnik._mapnik` name before importing symbols.
70+
# interpreter can raise "already registered" errors for pybind11 types/enums.
71+
#
72+
# To avoid a second load, if `_mapnik` is already present, alias it to the
73+
# canonical `mapnik._mapnik` name before importing.
7474
_canonical_ext_name = f"{__name__}._mapnik"
75-
if _canonical_ext_name in sys.modules:
76-
pass
77-
elif "_mapnik" in sys.modules:
78-
_candidate = sys.modules["_mapnik"]
79-
# Heuristic guard: only alias if it looks like our Mapnik extension.
80-
if hasattr(_candidate, "Map") and hasattr(_candidate, "version_string"):
81-
sys.modules[_canonical_ext_name] = _candidate
82-
75+
if _canonical_ext_name not in sys.modules and "_mapnik" in sys.modules:
76+
# If a top-level `_mapnik` was imported first, alias it to the canonical
77+
# `mapnik._mapnik` name so Python reuses the same extension module object
78+
# rather than attempting a second load.
79+
sys.modules[_canonical_ext_name] = sys.modules["_mapnik"]
80+
81+
_prev_err = getattr(sys, "_python_mapnik_ext_import_error", None)
82+
if _prev_err is not None:
83+
# Avoid repeated attempts to load the extension in the same interpreter
84+
# after a failure (which can lead to confusing secondary errors like
85+
# "already registered" from pybind11).
86+
raise ImportError(str(_prev_err)) from None
87+
88+
try:
89+
from . import _mapnik as _ext
90+
except ImportError as e:
91+
setattr(sys, "_python_mapnik_ext_import_error", e)
92+
raise
93+
# Ensure subsequent `import _mapnik` reuses the already-loaded extension.
94+
sys.modules.setdefault("_mapnik", _ext)
8395
from ._mapnik import *
8496

8597
def Shapefile(**keywords):

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,4 +45,4 @@ testpaths = [
4545

4646
[tool.uv]
4747
# Pin uv version for CI/dev consistency (used by astral-sh/setup-uv).
48-
required-version = "==0.9.25"
48+
required-version = ">=0.9.0"

src/mapnik_datasource.cpp

Lines changed: 85 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -31,160 +31,154 @@
3131
#include "create_datasource.hpp"
3232
// stl
3333
#include <vector>
34-
//pybind11
34+
// pybind11
3535
#include <pybind11/pybind11.h>
3636
#include <pybind11/operators.h>
3737
#include <pybind11/stl.h>
3838
#include <pybind11/native_enum.h>
3939

40+
using mapnik::attribute_descriptor;
4041
using mapnik::datasource;
41-
using mapnik::memory_datasource;
4242
using mapnik::layer_descriptor;
43-
using mapnik::attribute_descriptor;
43+
using mapnik::memory_datasource;
4444
using mapnik::parameters;
4545

4646
namespace py = pybind11;
4747

4848
namespace
4949
{
5050

51-
py::dict describe(std::shared_ptr<mapnik::datasource> const& ds)
52-
{
53-
py::dict description;
54-
mapnik::layer_descriptor ld = ds->get_descriptor();
55-
description["type"] = ds->type();
56-
description["name"] = ld.get_name();
57-
description["geometry_type"] = ds->get_geometry_type();
58-
description["encoding"] = ld.get_encoding();
59-
for (auto const& param : ld.get_extra_parameters())
51+
py::dict describe(std::shared_ptr<mapnik::datasource> const &ds)
6052
{
61-
description[py::str(param.first)] = mapnik_param_to_python::convert(param.second);
53+
py::dict description;
54+
mapnik::layer_descriptor ld = ds->get_descriptor();
55+
description["type"] = ds->type();
56+
description["name"] = ld.get_name();
57+
description["geometry_type"] = ds->get_geometry_type();
58+
description["encoding"] = ld.get_encoding();
59+
for (auto const &param : ld.get_extra_parameters())
60+
{
61+
description[py::str(param.first)] = mapnik_param_to_python::convert(param.second);
62+
}
63+
return description;
6264
}
63-
return description;
64-
}
6565

66-
py::list fields(std::shared_ptr<mapnik::datasource> const& ds)
67-
{
68-
py::list flds;
69-
if (ds)
66+
py::list fields(std::shared_ptr<mapnik::datasource> const &ds)
7067
{
71-
layer_descriptor ld = ds->get_descriptor();
72-
std::vector<attribute_descriptor> const& desc_ar = ld.get_descriptors();
73-
std::vector<attribute_descriptor>::const_iterator it = desc_ar.begin();
74-
std::vector<attribute_descriptor>::const_iterator end = desc_ar.end();
75-
for (; it != end; ++it)
68+
py::list flds;
69+
if (ds)
7670
{
77-
flds.append(it->get_name());
71+
layer_descriptor ld = ds->get_descriptor();
72+
std::vector<attribute_descriptor> const &desc_ar = ld.get_descriptors();
73+
std::vector<attribute_descriptor>::const_iterator it = desc_ar.begin();
74+
std::vector<attribute_descriptor>::const_iterator end = desc_ar.end();
75+
for (; it != end; ++it)
76+
{
77+
flds.append(it->get_name());
78+
}
7879
}
80+
return flds;
7981
}
80-
return flds;
81-
}
82-
py::list field_types(std::shared_ptr<mapnik::datasource> const& ds)
83-
{
84-
py::list fld_types;
85-
if (ds)
82+
py::list field_types(std::shared_ptr<mapnik::datasource> const &ds)
8683
{
87-
layer_descriptor ld = ds->get_descriptor();
88-
std::vector<attribute_descriptor> const& desc_ar = ld.get_descriptors();
89-
std::vector<attribute_descriptor>::const_iterator it = desc_ar.begin();
90-
std::vector<attribute_descriptor>::const_iterator end = desc_ar.end();
91-
for (; it != end; ++it)
84+
py::list fld_types;
85+
if (ds)
9286
{
93-
unsigned type = it->get_type();
94-
if (type == mapnik::Integer)
95-
fld_types.append(py::str("int"));
96-
else if (type == mapnik::Float)
97-
fld_types.append(py::str("float"));
98-
else if (type == mapnik::Double)
99-
fld_types.append(py::str("float"));
100-
else if (type == mapnik::String)
101-
fld_types.append(py::str("str"));
102-
else if (type == mapnik::Boolean)
103-
fld_types.append(py::str("bool"));
104-
else if (type == mapnik::Geometry)
105-
fld_types.append(py::str("geometry"));
106-
else if (type == mapnik::Object)
107-
fld_types.append(py::str("object"));
108-
else
109-
fld_types.append(py::str("unknown"));
87+
layer_descriptor ld = ds->get_descriptor();
88+
std::vector<attribute_descriptor> const &desc_ar = ld.get_descriptors();
89+
std::vector<attribute_descriptor>::const_iterator it = desc_ar.begin();
90+
std::vector<attribute_descriptor>::const_iterator end = desc_ar.end();
91+
for (; it != end; ++it)
92+
{
93+
unsigned type = it->get_type();
94+
if (type == mapnik::Integer)
95+
fld_types.append(py::str("int"));
96+
else if (type == mapnik::Float)
97+
fld_types.append(py::str("float"));
98+
else if (type == mapnik::Double)
99+
fld_types.append(py::str("float"));
100+
else if (type == mapnik::String)
101+
fld_types.append(py::str("str"));
102+
else if (type == mapnik::Boolean)
103+
fld_types.append(py::str("bool"));
104+
else if (type == mapnik::Geometry)
105+
fld_types.append(py::str("geometry"));
106+
else if (type == mapnik::Object)
107+
fld_types.append(py::str("object"));
108+
else
109+
fld_types.append(py::str("unknown"));
110+
}
110111
}
112+
return fld_types;
111113
}
112-
return fld_types;
113-
}
114114

115-
py::dict parameters_impl(std::shared_ptr<mapnik::datasource> const& ds)
116-
{
117-
auto const params = ds->params();
118-
py::dict d;
119-
for (auto kv : params)
115+
py::dict parameters_impl(std::shared_ptr<mapnik::datasource> const &ds)
120116
{
121-
d[py::str(kv.first)] = mapnik_param_to_python::convert(kv.second);
117+
auto const params = ds->params();
118+
py::dict d;
119+
for (auto const &kv : params)
120+
{
121+
d[py::str(kv.first)] = mapnik_param_to_python::convert(kv.second);
122+
}
123+
return d;
122124
}
123-
return d;
124-
}
125125

126126
} // namespace
127127

128-
129-
void export_datasource(py::module& m)
128+
void export_datasource(py::module &m)
130129
{
131130
py::native_enum<mapnik::datasource::datasource_t>(m, "DataType", "enum.Enum")
132-
.value("Vector",mapnik::datasource::Vector)
133-
.value("Raster",mapnik::datasource::Raster)
134-
.finalize()
135-
;
131+
.value("Vector", mapnik::datasource::Vector)
132+
.value("Raster", mapnik::datasource::Raster)
133+
.finalize();
136134

137135
py::native_enum<mapnik::datasource_geometry_t>(m, "DataGeometryType", "enum.Enum")
138-
.value("Point",mapnik::datasource_geometry_t::Point)
139-
.value("LineString",mapnik::datasource_geometry_t::LineString)
140-
.value("Polygon",mapnik::datasource_geometry_t::Polygon)
141-
.value("Collection",mapnik::datasource_geometry_t::Collection)
142-
.finalize()
143-
;
136+
.value("Point", mapnik::datasource_geometry_t::Point)
137+
.value("LineString", mapnik::datasource_geometry_t::LineString)
138+
.value("Polygon", mapnik::datasource_geometry_t::Polygon)
139+
.value("Collection", mapnik::datasource_geometry_t::Collection)
140+
.finalize();
144141

145-
py::class_<datasource,std::shared_ptr<datasource>> (m, "Datasource")
146-
.def(py::init([] (py::kwargs const& kwargs) { return create_datasource(kwargs);}))
142+
py::class_<datasource, std::shared_ptr<datasource>>(m, "Datasource")
143+
.def(py::init([](py::kwargs const &kwargs)
144+
{ return create_datasource(kwargs); }))
147145
.def("type", &datasource::type)
148146
.def("geometry_type", &datasource::get_geometry_type)
149147
.def("describe", &describe)
150148
.def("envelope", &datasource::envelope)
151149
.def("features", &datasource::features)
152-
.def("fields" ,&fields)
150+
.def("fields", &fields)
153151
.def("field_types", &field_types)
154152
.def("features_at_point", &datasource::features_at_point, py::arg("coord"), py::arg("tolerance") = 0)
155153
.def("parameters", &parameters_impl,
156154
"The configuration parameters of the data source. "
157155
"These vary depending on the type of data source.")
158156
.def(py::self == py::self)
159-
.def("__iter__",
160-
[](datasource const& ds) {
157+
.def("__iter__", [](datasource const &ds)
158+
{
161159
mapnik::query q(ds.envelope());
162160
layer_descriptor ld = ds.get_descriptor();
163161
std::vector<attribute_descriptor> const& desc_ar = ld.get_descriptors();
164162
for (auto const& desc : desc_ar)
165163
{
166164
q.add_property_name(desc.get_name());
167165
}
168-
return ds.features(q);
169-
},
170-
py::keep_alive<0, 1>())
171-
;
166+
return ds.features(q); }, py::keep_alive<0, 1>());
172167

173-
m.def("CreateDatasource",&create_datasource);
168+
m.def("CreateDatasource", &create_datasource);
174169

175-
py::class_<memory_datasource, datasource, std::shared_ptr<memory_datasource>>
176-
(m, "MemoryDatasource")
177-
.def(py::init([]() {
170+
py::class_<memory_datasource, datasource, std::shared_ptr<memory_datasource>>(m, "MemoryDatasource")
171+
.def(py::init([]()
172+
{
178173
mapnik::parameters p;
179174
p.insert(std::make_pair("type","memory"));
180-
return std::make_shared<memory_datasource>(p);}))
175+
return std::make_shared<memory_datasource>(p); }))
181176
.def("add_feature", &memory_datasource::push,
182177
"Adds a Feature:\n"
183178
">>> ms = MemoryDatasource()\n"
184179
">>> feature = Feature(Context(),1)\n"
185180
">>> ms.add_feature(f)\n")
186-
.def("num_features", &memory_datasource::size)
187-
;
181+
.def("num_features", &memory_datasource::size);
188182

189183
py::implicitly_convertible<memory_datasource, datasource>();
190184
}

0 commit comments

Comments
 (0)