2009-04-16 19:22:38 +02:00
|
|
|
#!/usr/bin/env python
|
2012-10-16 16:30:31 +02:00
|
|
|
# -*- coding: utf-8 -*-
|
2009-04-16 19:22:38 +02:00
|
|
|
|
|
|
|
from nose.plugins.errorclass import ErrorClass, ErrorClassPlugin
|
2015-01-28 01:20:33 +01:00
|
|
|
from nose.tools import assert_almost_equal
|
2009-04-16 19:22:38 +02:00
|
|
|
|
2012-10-16 16:30:31 +02:00
|
|
|
import os, sys, inspect, traceback
|
2012-10-16 17:16:45 +02:00
|
|
|
import mapnik
|
2016-08-02 19:53:24 +02:00
|
|
|
from xml.etree import ElementTree
|
2009-04-13 00:38:46 +02:00
|
|
|
|
|
|
|
def execution_path(filename):
|
|
|
|
return os.path.join(os.path.dirname(sys._getframe(1).f_code.co_filename), filename)
|
2009-04-16 19:22:38 +02:00
|
|
|
|
|
|
|
class Todo(Exception):
|
|
|
|
pass
|
|
|
|
|
|
|
|
class TodoPlugin(ErrorClassPlugin):
|
|
|
|
name = "todo"
|
|
|
|
|
|
|
|
todo = ErrorClass(Todo, label='TODO', isfailure=False)
|
2010-03-16 18:37:25 +01:00
|
|
|
|
2010-03-18 21:05:08 +01:00
|
|
|
def contains_word(word, bytestring_):
|
|
|
|
"""
|
|
|
|
Checks that a bytestring contains a given word. len(bytestring) should be
|
|
|
|
a multiple of len(word).
|
|
|
|
|
|
|
|
>>> contains_word("abcd", "abcd"*5)
|
|
|
|
True
|
|
|
|
|
|
|
|
>>> contains_word("ab", "ba"*5)
|
|
|
|
False
|
|
|
|
|
|
|
|
>>> contains_word("ab", "ab"*5+"a")
|
|
|
|
Traceback (most recent call last):
|
|
|
|
...
|
|
|
|
AssertionError: len(bytestring_) not multiple of len(word)
|
|
|
|
"""
|
|
|
|
n = len(word)
|
|
|
|
assert len(bytestring_)%n == 0, "len(bytestring_) not multiple of len(word)"
|
|
|
|
chunks = [bytestring_[i:i+n] for i in xrange(0, len(bytestring_), n)]
|
|
|
|
return word in chunks
|
2012-10-05 01:39:00 +02:00
|
|
|
|
|
|
|
def pixel2channels(pixel):
|
|
|
|
alpha = (pixel >> 24) & 0xff
|
|
|
|
red = pixel & 0xff
|
|
|
|
green = (pixel >> 8) & 0xff
|
|
|
|
blue = (pixel >> 16) & 0xff
|
|
|
|
return red,green,blue,alpha
|
|
|
|
|
|
|
|
def pixel2rgba(pixel):
|
|
|
|
return 'rgba(%s,%s,%s,%s)' % pixel2channels(pixel)
|
|
|
|
|
|
|
|
def get_unique_colors(im):
|
|
|
|
pixels = []
|
|
|
|
for x in range(im.width()):
|
|
|
|
for y in range(im.height()):
|
|
|
|
pixel = im.get_pixel(x,y)
|
|
|
|
if pixel not in pixels:
|
2016-08-02 19:53:24 +02:00
|
|
|
pixels.append(pixel)
|
2012-10-05 01:39:00 +02:00
|
|
|
pixels = sorted(pixels)
|
|
|
|
return map(pixel2rgba,pixels)
|
2012-10-16 16:30:31 +02:00
|
|
|
|
2013-01-18 22:13:01 +01:00
|
|
|
def run_all(iterable):
|
2012-10-16 16:30:31 +02:00
|
|
|
failed = 0
|
2013-01-18 22:13:01 +01:00
|
|
|
for test in iterable:
|
|
|
|
try:
|
|
|
|
test()
|
|
|
|
sys.stderr.write("\x1b[32m✓ \x1b[m" + test.__name__ + "\x1b[m\n")
|
|
|
|
except:
|
|
|
|
exc_type, exc_value, exc_tb = sys.exc_info()
|
|
|
|
failed += 1
|
|
|
|
sys.stderr.write("\x1b[31m✘ \x1b[m" + test.__name__ + "\x1b[m\n")
|
|
|
|
for mline in traceback.format_exception_only(exc_type, exc_value):
|
|
|
|
for line in mline.rstrip().split("\n"):
|
|
|
|
sys.stderr.write(" \x1b[31m" + line + "\x1b[m\n")
|
|
|
|
sys.stderr.write(" Traceback:\n")
|
|
|
|
for mline in traceback.format_tb(exc_tb):
|
|
|
|
for line in mline.rstrip().split("\n"):
|
2013-06-02 22:41:14 +02:00
|
|
|
if not 'utilities.py' in line and not 'trivial.py' in line and not line.strip() == 'test()':
|
|
|
|
sys.stderr.write(" " + line + "\n")
|
2013-01-18 22:13:01 +01:00
|
|
|
sys.stderr.flush()
|
2012-10-16 16:30:31 +02:00
|
|
|
return failed
|
2012-10-16 17:16:45 +02:00
|
|
|
|
|
|
|
def side_by_side_image(left_im, right_im):
|
|
|
|
width = left_im.width() + 1 + right_im.width()
|
|
|
|
height = max(left_im.height(), right_im.height())
|
|
|
|
im = mapnik.Image(width, height)
|
|
|
|
im.blend(0, 0, left_im, 1.0)
|
|
|
|
im.blend(left_im.width() + 1, 0, right_im, 1.0)
|
|
|
|
return im
|
2015-01-28 01:20:33 +01:00
|
|
|
|
|
|
|
def assert_box2d_almost_equal(a, b, msg=None):
|
|
|
|
msg = msg or ("%r != %r" % (a, b))
|
|
|
|
assert_almost_equal(a.minx, b.minx, msg=msg)
|
|
|
|
assert_almost_equal(a.maxx, b.maxx, msg=msg)
|
|
|
|
assert_almost_equal(a.miny, b.miny, msg=msg)
|
|
|
|
assert_almost_equal(a.maxy, b.maxy, msg=msg)
|
2016-08-02 19:53:24 +02:00
|
|
|
|
|
|
|
def datasources_available(map_file, missing_datasources=None):
|
|
|
|
'''
|
|
|
|
datasources_available
|
|
|
|
|
|
|
|
Determine whether the map file contains only available data source types.
|
|
|
|
|
|
|
|
@param map_file: path of XML map file
|
|
|
|
@type map_file: string
|
|
|
|
|
|
|
|
@param missing_datasources: collection of data source type names. if there
|
|
|
|
are unavailable data sources, and a collection
|
|
|
|
reference is provided, it will be populated with
|
|
|
|
the names of the unavailable data sources
|
|
|
|
@type missing_datasources: collection reference
|
|
|
|
|
|
|
|
@return: True if all referenced data source types are available,
|
|
|
|
otherwise False
|
|
|
|
'''
|
|
|
|
have_inputs = True
|
|
|
|
map_xml = ElementTree.parse(map_file)
|
|
|
|
data_source_type_params = map_xml.findall(".//Datasource/Parameter[@name=\"type\"]")
|
|
|
|
if data_source_type_params is not None and len(data_source_type_params) > 0:
|
|
|
|
for p in data_source_type_params:
|
|
|
|
dstype = p.text
|
|
|
|
if dstype not in mapnik.DatasourceCache.plugin_names():
|
|
|
|
have_inputs = False
|
|
|
|
if missing_datasources is not None:
|
|
|
|
missing_datasources.add(dstype)
|
|
|
|
return have_inputs
|