geographika / mappyfile

A pure Python MapFile parser for working with MapServer
MIT License
70 stars 20 forks source link

build up and generate mapfiles from Python dict #51

Open tomkralidis opened 6 years ago

tomkralidis commented 6 years ago

In our of our projects our core workflow is to generate a mapfile based on various system configurations (YAML, JSON, etc.). It would be valuable to have mappyfile be able to save a mapfile from a Python dictionary. Example of possible workflow:

import mappyfile

my_mapfile = {
    'name': 'foo'
}
mappyfile.dumps(my_mapfile)  # to string
mappfile.dump(my_mapfile, '/tmp/foo.map')  # to file
geographika commented 6 years ago

This is possible now, although the type needs to be set for each object - I'm in the middle of documenting a JSONSchema for the full Mapfile dict structure for a MapServer RFC.

import mappyfile
m = {"__type__": "map", "name": "Example", "extent": [0, 0, 100, 100]}
print(mappyfile.dumps(m))

Outputs:

MAP
    NAME "Example"
    EXTENT 0 0 100 100
END
tomkralidis commented 6 years ago

Thanks @geographika. Are there examples of adding layers (and other objects) from dicts as well? Example, add a layer object like:

import mappyfile
m = {"__type__": "map", "name": "Example", "extent": [0, 0, 100, 100]}
m['layers'].append({'name': 'weather alerts', 'type': 'Point'})
geographika commented 6 years ago

There should probably be a docs page with some examples.

In the meantime, anything of which there can be multiples is named in the plural, and is of type list. Each Mapfile class needs its "type" set:

import mappyfile
m = {"__type__": "map", "name": "Example", "extent": [0, 0, 100, 100]}
# create a list of layers
m['layers'] = [{"__type__": "layer", 'name': 'weather alerts', 'type': 'Point'}]
print(mappyfile.dumps(m))

If ordering of objects in the Mapfile is important (and using py2) you can use:

from mappyfile.ordereddict import CaseInsensitiveOrderedDict
m = CaseInsensitiveOrderedDict({"__type__": "map", "name": "Example", "extent": [0, 0, 100, 100]})
# create a list of layers
m['layers'] = [{"__type__": "layer", 'name': 'weather alerts', 'type': 'Point'}]
print(mappyfile.dumps(m))
MAP
    NAME "Example"
    EXTENT 0 0 100 100
    LAYER
        TYPE POINT
        NAME "weather alerts"
    END
END

A draft version of the RFC with full spec/details is at: http://mappyfile.readthedocs.io/en/latest/rfc.html Feedback/comments much appreciated! The latest schema definitions for each class can be found at: https://github.com/geographika/mappyfile/tree/master/mappyfile/schemas