source: subversion/applications/rendering/mapnik/generate_xml.py @ 19584

Last change on this file since 19584 was 18879, checked in by ldp, 10 years ago

New script, donated by springmeyer, to set up mapnik with your local settings. See generate_xml.py and README.
Also renamed .example files to .template

File size: 6.4 KB
Line 
1#!/usr/bin/env python
2
3import os
4import re
5import sys
6import glob
7import optparse
8import platform
9import tempfile
10
11__version__ = '0.1.0'
12
13REASONABLE_DEFAULTS = {
14        'epsg':'900913', # default osm2pgsql import srid
15        'world_boundaries':'world_boundaries', # relative path
16        'symbols':'symbols', # relative path
17        'prefix':'planet_osm', # default osm2pgsql table prefix
18        'extent':'-20037508,-19929239,20037508,19929239', # world in merc
19        'inc':'inc/*.template', # search path for inc templates to parse
20        'estimate_extent':'false',   
21        'extent':'-20037508,-19929239,20037508,19929239',   
22        }
23
24def color_text(color, text):
25    if os.name == 'nt':
26        return text
27    return "\033[9%sm%s\033[0m" % (color,text)
28
29class Params:
30    def __init__(self,params,accept_none):
31        self.params = params
32        self.accept_none = accept_none
33        self.missing = []
34   
35    def blend_with_env(self,opts):
36        d = {}
37       
38        for p in self.params:
39            env_var_name = 'MAPNIK_%s' % p.upper()
40
41            # first pull from passed options...
42            if not opts.get(p) is None:
43                d[p] = opts[p]
44
45            # then try to pull from environment settings
46            elif not os.environ.get(env_var_name) is None:
47                d[p] = os.environ[env_var_name]
48
49            # then assign any reasonable default values...
50            elif p in REASONABLE_DEFAULTS.keys():
51                d[p] = REASONABLE_DEFAULTS[p]
52            # if --accept-none is passed then we assume
53            # its a paramater that mapnik likely does not need
54            # and will ignore if it is an empty string (e.g. db values)
55            elif self.accept_none:
56                d[p] = ''
57            else:
58                self.missing.append(p)
59        return d
60
61def serialize(xml,options):
62    try:
63        import mapnik
64    except:
65        sys.exit(color_text(1,'Error: saving xml requires Mapnik python bindings to be installed'))
66    m = mapnik.Map(1,1)
67    if options.from_string:
68        mapnik.load_map_from_string(m,xml,True)
69    else:
70        mapnik.load_map(m,xml,True)
71    if options.output:
72        mapnik.save_map(m,options.output)
73    else:
74        print mapnik.save_map_string(m)
75
76def validate(params,parser):
77    if not os.path.exists(params['world_boundaries']):
78        parser.error("Directory '%s' used for param '%s' not found" % (params['world_boundaries'],'world_boundaries'))
79    supported_srs = [900913,4326]
80    if not int(params['epsg']) in supported_srs:
81        parser.error('Sorry only supported projections are: %s' % supported_srs)
82    if not params['estimate_extent'] == 'false':
83        params['extent'] = ''
84
85# set up parser...
86parser = optparse.OptionParser(usage="""%prog [template xml] [output xml] <parameters>
87
88Full help:
89 $ %prog -h (or --help for possible options)
90
91Read 'osm.xml' and print resulting xml to stdout:
92 $ %prog osm.xml
93
94Read template, save output xml, and pass variables as options
95 $ %prog osm.xml my_osm.xml --dbname spain --user postgres --host ''""", version='%prog ' + __version__)
96
97
98if __name__ == '__main__':
99
100    # custom parse of includes directory if supplied...
101    if '--inc' in sys.argv:
102        idx = sys.argv.index('--inc')
103        if not len(sys.argv) > (idx+1) or '--' in sys.argv[idx+1]:
104            parser.error("--inc argument requires a path to a directory as an argument")
105        else:
106            search_path = os.path.join(sys.argv[idx+1],'*.template')
107    else:
108        search_path = REASONABLE_DEFAULTS['inc']
109   
110    inc_dir = os.path.dirname(search_path)
111    parser.add_option('--inc', dest='inc', help="Includes dir (default: '%s')" % inc_dir )
112   
113    parser.add_option('--accept-none', dest='accept_none', action='store_true', help="Interpret lacking value as unneeded")
114   
115    if not os.path.exists(inc_dir):
116        parser.error("The 'inc' path you gave is bogus!")
117       
118    # get all the includes
119    includes = glob.glob(search_path)
120   
121    if not includes:
122        parser.error("Can't find include templates, please provide search path using '--inc' , currently using '%s'" % search_path)
123
124    p = re.compile('.*%\((\w+)\)s.*')
125   
126    text = ''
127    for xml in includes:
128        text += file(xml,'rb').read()
129   
130    # find all variables in template includes
131    matches = p.findall(text)
132   
133    if not matches:
134        parser.error(color_text(1,"Can't properly parse out variables in include templates.\nMake sure they are all wrapped like '%(variable)s'"))
135   
136    # look ahead and build up --help text...
137    #import pdb;pdb.set_trace()
138    p = Params(matches,accept_none=False)
139    blended = p.blend_with_env({})
140    for var in matches:
141        msg = "(default: '%(" + var + ")s')"
142        if var in blended:
143            default = msg % blended
144        else:
145            default = ''#msg % {var:'None'}
146        parser.add_option('--%s' % var, dest=var,
147            help="Set value of '%s' %s" % (var,default))
148
149    # now, actually run the tool...
150    (options, args) = parser.parse_args()
151    p = Params(matches,options.accept_none)
152    blended = p.blend_with_env(options.__dict__)
153   
154    help_text = "\n\nNote: use --accept-none to pass blank values for other parameters "
155    if p.missing:
156        parser.error(color_text(1,"\nPlease provide the following parameters values (or set as env variables):\n%s" % ''.join([" --%s 'value' " % v for v in p.missing]) + help_text))
157   
158    validate(blended,parser)
159   
160    for xml in includes:
161        template = file(xml,'rb')
162        new_name = xml.replace('.template','')
163        new_file = file(new_name,'wb')
164        try:
165            new_file.write(template.read() % blended)
166        except ValueError, e:
167            parser.error(color_text(1,"\n%s (found in %s)" % (e,xml)))
168        template.close()
169        new_file.close()
170       
171    options.output = None
172    options.from_string = False
173    template_xml = None
174    # accepting XML as stream...
175    if not sys.stdin.isatty():
176        template_xml = sys.stdin.read()
177        options.from_string = True
178        if len(args) > 0:
179            options.output = args[0]
180    elif len(args) == 0:
181        template_xml = None
182        options.output = None
183    else:
184        template_xml = args[0]
185        if len(args) > 1:
186            options.output = args[1]
187
188    if template_xml:
189        serialize(template_xml,options)
190    else:
191        print 'Include files written successfully! Pass the osm.xml file as an argument if you want to serialize a new version or test reading the XML'
Note: See TracBrowser for help on using the repository browser.