Permalink
Browse files

Bumped to version 2.6.0 with addition of --style option to cascadenik…

…-compile
  • Loading branch information...
1 parent 6bdd716 commit d13c1a37f545c45d2bad1aa6251527b70f7ae474 @migurski migurski committed Nov 17, 2012
Showing with 56 additions and 15 deletions.
  1. +5 −2 cascadenik-compile.py
  2. +8 −3 cascadenik/__init__.py
  3. +29 −10 cascadenik/compile.py
  4. +14 −0 cascadenik/tests.py
@@ -29,7 +29,7 @@ def main(src_file, dest_file, **kwargs):
mmap = mapnik.Map(1, 1)
# allow [zoom] filters to work
mmap.srs = '+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null'
- load_kwargs = dict([(k, v) for (k, v) in kwargs.items() if k in ('cache_dir', 'scale', 'verbose', 'datasources_cfg')])
+ load_kwargs = dict([(k, v) for (k, v) in kwargs.items() if k in ('cache_dir', 'scale', 'verbose', 'datasources_cfg', 'user_styles')])
cascadenik.load_map(mmap, src_file, dirname(realpath(dest_file)), **load_kwargs)
(handle, tmp_file) = tempfile.mkstemp(suffix='.xml', prefix='cascadenik-mapnik-')
@@ -53,7 +53,7 @@ def main(src_file, dest_file, **kwargs):
parser = optparse.OptionParser(usage="""%prog [options] <mml> <xml>""", version='%prog ' + cascadenik.__version__)
-parser.set_defaults(cache_dir=None, pretty=True, verbose=False, scale=1, datasources_cfg=None)
+parser.set_defaults(cache_dir=None, pretty=True, verbose=False, scale=1, user_styles=[], datasources_cfg=None)
# the actual default for cache_dir is handled in load_map(),
# to ensure that the mkdir behavior is correct.
@@ -70,6 +70,9 @@ def main(src_file, dest_file, **kwargs):
parser.add_option('--2x', dest='scale', action='store_const', const=2,
help='Optionally scale all values (lengths and scale denominators) in output xml by two, suitable for display on high-resolution (e.g. iPhone) screens.')
+parser.add_option('--style', dest='user_styles', action='append',
+ help='Look for additional styles in the named file, which will override anything provided in the MML. Any number of these can be provided.')
+
parser.add_option('-p', '--pretty', dest='pretty',
help='Pretty print the xml output. (default: True)',
action='store_true')
@@ -6,7 +6,7 @@
The code:
https://github.com/mapnik/Cascadenik
"""
-__version__ = '2.5.2'
+__version__ = '2.6.0'
from os import mkdir, chmod
from os.path import isdir, realpath, expanduser, dirname, exists
@@ -39,7 +39,7 @@
__all__ = ['load_map', 'compile', '_compile', 'style', 'stylesheet_declarations']
-def load_map(map, src_file, output_dir, scale=1, cache_dir=None, datasources_cfg=None, verbose=False):
+def load_map(map, src_file, output_dir, scale=1, cache_dir=None, datasources_cfg=None, user_styles=[], verbose=False):
""" Apply a stylesheet source file to a given mapnik Map instance, like mapnik.load_map().
Parameters:
@@ -65,6 +65,11 @@ def load_map(map, src_file, output_dir, scale=1, cache_dir=None, datasources_cfg
datasources_cfg:
...
+ user_styles:
+ A optional list of files or URLs, that override styles defined in
+ the map source. These are evaluated in order, with declarations from
+ later styles overriding those from earlier styles.
+
verbose:
...
"""
@@ -82,4 +87,4 @@ def load_map(map, src_file, output_dir, scale=1, cache_dir=None, datasources_cfg
chmod(cache_dir, 0755)
dirs = Directories(output_dir, realpath(cache_dir), dirname(src_file))
- compile(src_file, dirs, verbose, datasources_cfg=datasources_cfg, scale=scale).to_mapnik(map, dirs)
+ compile(src_file, dirs, verbose, datasources_cfg=datasources_cfg, user_styles=user_styles, scale=scale).to_mapnik(map, dirs)
View
@@ -607,24 +607,38 @@ def is_merc_projection(srs):
return True
-def extract_declarations(map_el, dirs, scale=1):
+def extract_declarations(map_el, dirs, scale=1, user_styles=[]):
""" Given a Map element and directories object, remove and return a complete
list of style declarations from any Stylesheet elements found within.
"""
- declarations = []
+ styles = []
+ #
+ # First, look at all the stylesheets defined in the map itself.
+ #
for stylesheet in map_el.findall('Stylesheet'):
map_el.remove(stylesheet)
- styles, mss_href = fetch_embedded_or_remote_src(stylesheet, dirs)
+ content, mss_href = fetch_embedded_or_remote_src(stylesheet, dirs)
+
+ if content:
+ styles.append((content, mss_href))
+
+ #
+ # Second, look through the user-supplied styles for override rules.
+ #
+ for stylesheet in user_styles:
+ mss_href = urljoin(dirs.source.rstrip('/')+'/', stylesheet)
+ content = urllib.urlopen(mss_href).read().decode(DEFAULT_ENCODING)
- if not styles:
- continue
-
+ styles.append((content, mss_href))
+
+ declarations = []
+
+ for (content, mss_href) in styles:
is_merc = is_merc_projection(map_el.get('srs',''))
- for declaration in stylesheet_declarations(styles, is_merc, scale):
-
+ for declaration in stylesheet_declarations(content, is_merc, scale):
#
# Change the value of each URI relative to the location
# of the containing stylesheet. We generally just have
@@ -1434,7 +1448,7 @@ def localize_file_datasource(file_href, dirs):
else:
return dirs.output_path(path)
-def compile(src, dirs, verbose=False, srs=None, datasources_cfg=None, scale=1):
+def compile(src, dirs, verbose=False, srs=None, datasources_cfg=None, user_styles=[], scale=1):
""" Compile a Cascadenik MML file, returning a cascadenik.output.Map object.
Parameters:
@@ -1462,6 +1476,11 @@ def compile(src, dirs, verbose=False, srs=None, datasources_cfg=None, scale=1):
entities. This is most useful in development, whereby one redefines
individual datasources, connection parameters, and/or local paths.
+ user_styles:
+ A optional list of files or URLs, that override styles defined in
+ the map source. These are evaluated in order, with declarations from
+ later styles overriding those from earlier styles.
+
scale:
Scale value for output map, 2 doubles the size for high-res displays.
"""
@@ -1491,7 +1510,7 @@ def compile(src, dirs, verbose=False, srs=None, datasources_cfg=None, scale=1):
map_el = doc.getroot()
expand_source_declarations(map_el, dirs, datasources_cfg)
- declarations = extract_declarations(map_el, dirs, scale)
+ declarations = extract_declarations(map_el, dirs, scale, user_styles)
# a list of layers and a sequential ID generator
layers, ids = [], (i for i in xrange(1, 999999))
View
@@ -2476,6 +2476,20 @@ def testCompile10(self):
textsym_el = map_el.find('Style').find('Rule').find('TextSymbolizer')
self.assertEqual(fontset_el.get('name'), textsym_el.get('fontset-name'))
+ def testCompile11(self):
+ """
+ """
+ s = """<?xml version="1.0"?>
+ <Map>
+ <Stylesheet>
+ Map { map-bgcolor: #fff; }
+ </Stylesheet>
+ </Map>
+ """
+ map = compile(s, self.dirs, user_styles=['http://cascadenik-sampledata.s3.amazonaws.com/black-bgcolor.css'])
+
+ self.assertEqual(str(map.background), '#000000')
+
class RelativePathTests(unittest.TestCase):
def setUp(self):

0 comments on commit d13c1a3

Please sign in to comment.