Skip to content

Commit 5ab32f0

Browse files
authored
Merge pull request #269 from mapnik/proj6
proj6 + pytest
2 parents 6c0e9b5 + 9045155 commit 5ab32f0

File tree

102 files changed

+3468
-4931
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

102 files changed

+3468
-4931
lines changed

mapnik/__init__.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ def __init__(self, *args, **kwargs):
108108
Box2d.__init__(self, *args, **kwargs)
109109

110110

111-
class _Coord(Coord, _injector()):
111+
class Coord(_mapnik.Coord, _injector()):
112112
"""
113113
Represents a point with two coordinates (either lon/lat or x/y).
114114
@@ -183,7 +183,7 @@ def inverse(self, projection):
183183
return inverse_(self, projection)
184184

185185

186-
class _Box2d(Box2d, _injector()):
186+
class Box2d(_mapnik.Box2d, _injector()):
187187
"""
188188
Represents a spatial envelope (i.e. bounding box).
189189
@@ -238,7 +238,7 @@ def inverse(self, projection):
238238
return inverse_(self, projection)
239239

240240

241-
class _Projection(Projection, _injector()):
241+
class Projection(_mapnik.Projection, _injector()):
242242

243243
def __repr__(self):
244244
return "Projection('%s')" % self.params()
@@ -266,15 +266,15 @@ def inverse(self, obj):
266266
return inverse_(obj, self)
267267

268268

269-
class _Feature(Feature, _injector()):
269+
class Feature(_mapnik.Feature, _injector()):
270270
__geo_interface__ = property(lambda self: json.loads(self.to_geojson()))
271271

272272

273-
class _Geometry(Geometry, _injector()):
273+
class Geometry(_mapnik.Geometry, _injector()):
274274
__geo_interface__ = property(lambda self: json.loads(self.to_geojson()))
275275

276276

277-
class _Datasource(Datasource, _injector()):
277+
class Datasource(_mapnik.Datasource, _injector()):
278278

279279
def featureset(self, fields = None, variables = {}):
280280
query = Query(self.envelope())
@@ -291,13 +291,13 @@ def all_features(self, fields=None, variables={}):
291291
return self.__iter__(fields, variables)
292292

293293

294-
class _Color(Color, _injector()):
294+
class Color(_mapnik.Color, _injector()):
295295

296296
def __repr__(self):
297297
return "Color(R=%d,G=%d,B=%d,A=%d)" % (self.r, self.g, self.b, self.a)
298298

299299

300-
class _SymbolizerBase(SymbolizerBase, _injector()):
300+
class SymbolizerBase(_mapnik.SymbolizerBase, _injector()):
301301
# back compatibility
302302

303303
@property
@@ -804,7 +804,7 @@ def make_it(feat, idx):
804804
return itertools.imap(make_it, features, itertools.count(1))
805805

806806

807-
class _TextSymbolizer(TextSymbolizer, _injector()):
807+
class TextSymbolizer(_mapnik.TextSymbolizer, _injector()):
808808

809809
@property
810810
def name(self):

mapnik/printing/__init__.py

Lines changed: 34 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,9 @@
22

33
"""Mapnik classes to assist in creating printable maps."""
44

5-
from __future__ import absolute_import, print_function
6-
75
import logging
86
import math
9-
10-
from mapnik import Box2d, Coord, Geometry, Layer, Map, Projection, Style, render
7+
from mapnik import Box2d, Coord, Geometry, Layer, Map, Projection, ProjTransform, Style, render
118
from mapnik.printing.conversions import m2pt, m2px
129
from mapnik.printing.formats import pagesizes
1310
from mapnik.printing.scales import any_scale, default_scale, deg_min_sec_scale, sequence_scale
@@ -25,12 +22,12 @@
2522
HAS_PANGOCAIRO_MODULE = False
2623

2724
try:
28-
from PyPDF2 import PdfFileReader, PdfFileWriter
29-
from PyPDF2.generic import (ArrayObject, DecodedStreamObject, DictionaryObject, FloatObject, NameObject,
30-
NumberObject, TextStringObject)
31-
HAS_PYPDF2 = True
25+
from pypdf import PdfReader, PdfWriter
26+
from pypdf.generic import (ArrayObject, DecodedStreamObject, DictionaryObject, FloatObject, NameObject,
27+
NumberObject, TextStringObject)
28+
HAS_PYPDF = True
3229
except ImportError:
33-
HAS_PYPDF2 = False
30+
HAS_PYPDF = False
3431

3532
"""
3633
Style of centering to use with the map.
@@ -90,7 +87,7 @@ def __init__(self,
9087
Args:
9188
pagesize: tuple of page size in meters, see predefined sizes in mapnik.formats module
9289
margin: page margin in meters
93-
box: the box to render the map into. Must be within page area, margin excluded.
90+
box: the box to render the map into. Must be within page area, margin excluded.
9491
This should be a Mapnik Box2d object. Default is the full page without margin.
9592
percent_box: similar to box argument but specified as a percent (0->1) of the full page size.
9693
If both box and percent_box are specified percent_box will be used.
@@ -104,7 +101,7 @@ def __init__(self,
104101
be a value from the mapnik.utils.centering class. The default is to center on the maps constrained
105102
axis. Typically this will be horizontal for portrait pages and vertical for landscape pages.
106103
is_latlon: whether the map is in lat lon degrees or not.
107-
use_ocg_layers: create OCG layers in the PDF, requires PyPDF2
104+
use_ocg_layers: create OCG layers in the PDF, requires pypdf
108105
font_name: the font name used each time text is written (e.g., legend titles, representative fraction, etc.)
109106
"""
110107
self._pagesize = pagesize
@@ -563,7 +560,7 @@ def render_scale(self, m, ctx=None, width=0.05, num_divisions=3, bar_size=8.0, w
563560
564561
Args:
565562
m: the Map object to render the scale for
566-
ctx: A cairo context to render the scale into. If this is None, we create a context and find out
563+
ctx: A cairo context to render the scale into. If this is None, we create a context and find out
567564
the best location for the scale bar
568565
width: the width of area available for rendering the scale bar (in meters)
569566
num_divisions: the number of divisions for the scale bar
@@ -737,7 +734,7 @@ def render_graticule_on_map(self, m, dec_degrees=True, grid_layer_name="Graticul
737734

738735
# renders the vertical graticule axes
739736
self._render_graticule_axes_and_text(
740-
m,
737+
m,
741738
p2,
742739
latlon_bounds,
743740
latlon_buffer,
@@ -1119,7 +1116,7 @@ def convert_pdf_pages_to_layers(self, filename, layer_names=None, reverse_all_bu
11191116
Takes a multi pages PDF as input and converts each page to a layer in a single page PDF.
11201117
11211118
Note:
1122-
requires PyPDF2 to be available
1119+
requires pypdf to be available
11231120
11241121
Args:
11251122
layer_names should be a sequence of the user visible names of the layers, if not given
@@ -1128,17 +1125,17 @@ def convert_pdf_pages_to_layers(self, filename, layer_names=None, reverse_all_bu
11281125
if output_name is not provided a temporary file will be used for the conversion which
11291126
will then be copied back over the source file.
11301127
"""
1131-
if not HAS_PYPDF2:
1132-
raise RuntimeError("PyPDF2 not available; PyPDF2 required to convert pdf pages to layers")
1128+
if not HAS_PYPDF:
1129+
raise RuntimeError("pypdf not available; pypdf required to convert pdf pages to layers")
11331130

11341131
with open(filename, "rb+") as f:
1135-
file_reader = PdfFileReader(f)
1136-
file_writer = PdfFileWriter()
1132+
file_reader = PdfReader(f)
1133+
file_writer = PdfWriter()
11371134

1138-
template_page_size = file_reader.pages[0].mediaBox
1139-
output_pdf = file_writer.addBlankPage(
1140-
width=template_page_size.getWidth(),
1141-
height=template_page_size.getHeight())
1135+
template_page_size = file_reader.pages[0].mediabox
1136+
output_pdf = file_writer.add_blank_page(
1137+
width=template_page_size.width,
1138+
height=template_page_size.height)
11421139

11431140
content_key = NameObject('/Contents')
11441141
output_pdf[content_key] = ArrayObject()
@@ -1149,15 +1146,15 @@ def convert_pdf_pages_to_layers(self, filename, layer_names=None, reverse_all_bu
11491146
(properties, ocgs) = self._make_ocg_layers(file_reader, file_writer, output_pdf, layer_names)
11501147

11511148
properties_key = NameObject('/Properties')
1152-
output_pdf[resource_key][properties_key] = file_writer._addObject(properties)
1149+
output_pdf[resource_key][properties_key] = file_writer._add_object(properties)
11531150

11541151
ocproperties = DictionaryObject()
11551152
ocproperties[NameObject('/OCGs')] = ocgs
11561153

11571154
default_view = self._get_pdf_default_view(ocgs, reverse_all_but_last)
1158-
ocproperties[NameObject('/D')] = file_writer._addObject(default_view)
1155+
ocproperties[NameObject('/D')] = file_writer._add_object(default_view)
11591156

1160-
file_writer._root_object[NameObject('/OCProperties')] = file_writer._addObject(ocproperties)
1157+
file_writer._root_object[NameObject('/OCProperties')] = file_writer._add_object(ocproperties)
11611158

11621159
f.seek(0)
11631160
file_writer.write(f)
@@ -1189,7 +1186,7 @@ def _make_ocg_layers(self, file_reader, file_writer, output_pdf, layer_names=Non
11891186
page[NameObject(
11901187
'/Contents')] = ArrayObject((ocgs_start, page['/Contents'], ocg_end))
11911188

1192-
output_pdf.mergePage(page)
1189+
output_pdf.merge_page(page)
11931190

11941191
ocg = DictionaryObject()
11951192
ocg[NameObject('/Type')] = NameObject('/OCG')
@@ -1199,7 +1196,7 @@ def _make_ocg_layers(self, file_reader, file_writer, output_pdf, layer_names=Non
11991196
else:
12001197
ocg[NameObject('/Name')] = TextStringObject('Layer %d' % (idx + 1))
12011198

1202-
indirect_ocg = file_writer._addObject(ocg)
1199+
indirect_ocg = file_writer._add_object(ocg)
12031200
properties[ocg_name] = indirect_ocg
12041201
ocgs.append(indirect_ocg)
12051202

@@ -1238,20 +1235,20 @@ def add_geospatial_pdf_header(self, m, filename, epsg=None, wkt=None):
12381235
The epsg code or the wkt text of the projection must be provided.
12391236
Must be called *after* the page has had .finish() called.
12401237
"""
1241-
if not HAS_PYPDF2:
1242-
raise RuntimeError("PyPDF2 not available; PyPDF2 required to add geospatial header to PDF")
1238+
if not HAS_PYPDF:
1239+
raise RuntimeError("pypdf not available; pypdf required to add geospatial header to PDF")
12431240

12441241
if not any((epsg,wkt)):
12451242
raise RuntimeError("EPSG or WKT required to add geospatial header to PDF")
12461243

12471244
with open(filename, "rb+") as f:
1248-
file_reader = PdfFileReader(f)
1249-
file_writer = PdfFileWriter()
1245+
file_reader = PdfReader(f)
1246+
file_writer = PdfWriter()
12501247

12511248
# preserve OCProperties at document root if we have one
1252-
if file_reader.trailer['/Root'].has_key(NameObject('/OCProperties')):
1249+
if NameObject('/OCProperties') in file_reader.trailer['/Root']:
12531250
file_writer._root_object[NameObject('/OCProperties')] = file_reader.trailer[
1254-
'/Root'].getObject()[NameObject('/OCProperties')]
1251+
'/Root'].get_object()[NameObject('/OCProperties')]
12551252

12561253
for page in file_reader.pages:
12571254
gcs = DictionaryObject()
@@ -1265,7 +1262,7 @@ def add_geospatial_pdf_header(self, m, filename, epsg=None, wkt=None):
12651262
measure = self._get_pdf_measure(m, gcs)
12661263
page[NameObject('/VP')] = self._get_pdf_vp(measure)
12671264

1268-
file_writer.addPage(page)
1265+
file_writer.add_page(page)
12691266

12701267
f.seek(0)
12711268
file_writer.write(f)
@@ -1318,11 +1315,11 @@ def _get_pdf_gpts(self, m):
13181315
"""
13191316
gpts = ArrayObject()
13201317

1321-
proj = Projection(m.srs)
1318+
tr = ProjTransform(Projection(m.srs), Projection("epsg:4326"))
13221319
env = m.envelope()
1323-
for x in ((env.minx, env.miny), (env.minx, env.maxy),
1320+
for p in ((env.minx, env.miny), (env.minx, env.maxy),
13241321
(env.maxx, env.maxy), (env.maxx, env.miny)):
1325-
latlon_corner = proj.inverse(Coord(*x))
1322+
latlon_corner = tr.forward(Coord(*p))
13261323
# these are in lat,lon order according to the specification
13271324
gpts.append(FloatObject(str(latlon_corner.y)))
13281325
gpts.append(FloatObject(str(latlon_corner.x)))

setup.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
import subprocess
88
import sys
99
import glob
10+
import pkg_resources
11+
1012
from distutils import sysconfig
1113
from ctypes.util import find_library
1214

@@ -230,19 +232,21 @@ def run(self):
230232
if os.environ.get("PYCAIRO", "false") == "true":
231233
try:
232234
extra_comp_args.append('-DHAVE_PYCAIRO')
233-
print("-I%s/include/pycairo".format(sys.exec_prefix))
234-
extra_comp_args.append("-I{0}/include/pycairo".format(sys.exec_prefix))
235+
dist = pkg_resources.get_distribution('pycairo')
236+
print(dist.location)
237+
print("-I%s/cairo/include".format(dist.location))
238+
extra_comp_args.append("-I{0}/cairo/include".format(dist.location))
235239
#extra_comp_args.extend(check_output(["pkg-config", '--cflags', 'pycairo']).strip().split(' '))
236240
#linkflags.extend(check_output(["pkg-config", '--libs', 'pycairo']).strip().split(' '))
237241
except:
238242
raise Exception("Failed to find compiler options for pycairo")
239243

240244
if sys.platform == 'darwin':
241-
extra_comp_args.append('-mmacosx-version-min=10.11')
245+
extra_comp_args.append('-mmacosx-version-min=13.0')
242246
# silence warning coming from boost python macros which
243247
# would is hard to silence via pragma
244248
extra_comp_args.append('-Wno-parentheses-equality')
245-
linkflags.append('-mmacosx-version-min=10.11')
249+
linkflags.append('-mmacosx-version-min=13.0')
246250
else:
247251
linkflags.append('-lrt')
248252
linkflags.append('-Wl,-z,origin')

src/mapnik_enumeration.hpp

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -68,19 +68,17 @@ class enumeration_ :
6868
using namespace boost::python::converter;
6969
return base_type::base::to_python(
7070
registered<native_type>::converters.m_class_object
71-
, static_cast<long>( v ));
71+
, static_cast<long>(native_type(v)));
7272

7373
}
7474
};
7575

7676
void init() {
7777
boost::python::implicitly_convertible<native_type, EnumWrapper>();
7878
boost::python::to_python_converter<EnumWrapper, converter >();
79-
80-
for (unsigned i = 0; i < EnumWrapper::MAX; ++i)
79+
for (auto const& kv : EnumWrapper::lookupMap())
8180
{
82-
// Register the strings already defined for this enum.
83-
base_type::value( EnumWrapper::get_string( i ), native_type( i ) );
81+
base_type::value(kv.second.c_str(), kv.first);
8482
}
8583
}
8684

src/mapnik_gamma_method.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,11 @@ void export_gamma_method()
3636
using namespace boost::python;
3737

3838
mapnik::enumeration_<mapnik::gamma_method_e>("gamma_method")
39-
.value("POWER", mapnik::GAMMA_POWER)
40-
.value("LINEAR",mapnik::GAMMA_LINEAR)
41-
.value("NONE", mapnik::GAMMA_NONE)
42-
.value("THRESHOLD", mapnik::GAMMA_THRESHOLD)
43-
.value("MULTIPLY", mapnik::GAMMA_MULTIPLY)
39+
.value("POWER", mapnik::gamma_method_enum::GAMMA_POWER)
40+
.value("LINEAR",mapnik::gamma_method_enum::GAMMA_LINEAR)
41+
.value("NONE", mapnik::gamma_method_enum::GAMMA_NONE)
42+
.value("THRESHOLD", mapnik::gamma_method_enum::GAMMA_THRESHOLD)
43+
.value("MULTIPLY", mapnik::gamma_method_enum::GAMMA_MULTIPLY)
4444
;
4545

4646
}

src/mapnik_projection.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,8 +106,10 @@ void export_projection ()
106106
.def ("params", make_function(&projection::params,
107107
return_value_policy<copy_const_reference>()),
108108
"Returns the PROJ string for this projection.\n")
109-
.def ("expanded",&projection::expanded,
110-
"normalize PROJ definition by expanding epsg:XXXX syntax\n")
109+
.def ("definition",&projection::definition,
110+
"Return projection definition\n")
111+
.def ("description", &projection::description,
112+
"Returns projection description")
111113
.add_property ("geographic", &projection::is_geographic,
112114
"This property is True if the projection is a geographic projection\n"
113115
"(i.e. it uses lon/lat coordinates)\n")

src/mapnik_raster_colorizer.cpp

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,6 @@ using mapnik::colorizer_stop;
4040
using mapnik::colorizer_stops;
4141
using mapnik::colorizer_mode_enum;
4242
using mapnik::color;
43-
using mapnik::COLORIZER_INHERIT;
44-
using mapnik::COLORIZER_LINEAR;
45-
using mapnik::COLORIZER_DISCRETE;
46-
using mapnik::COLORIZER_EXACT;
47-
4843

4944
namespace {
5045
void add_stop(raster_colorizer_ptr & rc, colorizer_stop & stop)
@@ -196,10 +191,10 @@ void export_raster_colorizer()
196191
;
197192

198193
enum_<colorizer_mode_enum>("ColorizerMode")
199-
.value("COLORIZER_INHERIT", COLORIZER_INHERIT)
200-
.value("COLORIZER_LINEAR", COLORIZER_LINEAR)
201-
.value("COLORIZER_DISCRETE", COLORIZER_DISCRETE)
202-
.value("COLORIZER_EXACT", COLORIZER_EXACT)
194+
.value("COLORIZER_INHERIT", colorizer_mode_enum::COLORIZER_INHERIT)
195+
.value("COLORIZER_LINEAR", colorizer_mode_enum::COLORIZER_LINEAR)
196+
.value("COLORIZER_DISCRETE", colorizer_mode_enum::COLORIZER_DISCRETE)
197+
.value("COLORIZER_EXACT", colorizer_mode_enum::COLORIZER_EXACT)
203198
.export_values()
204199
;
205200

src/mapnik_style.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,8 @@ void export_style()
6969
using namespace boost::python;
7070

7171
mapnik::enumeration_<mapnik::filter_mode_e>("filter_mode")
72-
.value("ALL",mapnik::FILTER_ALL)
73-
.value("FIRST",mapnik::FILTER_FIRST)
72+
.value("ALL",mapnik::filter_mode_enum::FILTER_ALL)
73+
.value("FIRST",mapnik::filter_mode_enum::FILTER_FIRST)
7474
;
7575

7676
class_<rules>("Rules",init<>("default ctor"))

0 commit comments

Comments
 (0)