-
Notifications
You must be signed in to change notification settings - Fork 0
Defining a custom tilestache provider
Lately I was exploring tilestache with mapnik in a basic setup using docker and docker-compose.
Now it is time to dig a little deeper. In a project we are considering to use tilestache, but we must be able to change some input variables dynamically. Especially
to set the input directory of the datasource is a main objective. tilestache
's custom providers to the rescue!
A custom provider basically sub-classes the provider you are defining in your config, in our case the
ImageProvider
. As the doc string of the provider states:
ImageProvider is known as "mapnik" in TileStache config
A config using mapnik could look like this
...
"grid":
{
"provider":
{
"name": "mapnik",
"mapfile": "/tiles/styles/style_grid.xml"
}
},
...
The ImageProvider
class implementation shows that two arguments are required, the layer
instance and a
mapfile
. The mapfile
variable, however, will not be used until the renderArea
method is executed.
So all we have to do is set the mapfile attribute before the method is called by sub-classing it. In our use case the state information is stored in redis, but I believe you'll get the picture.
import redis
import os
from TileStache.Mapnik import ImageProvider as MapnikProvider
_mapfile_cache = {}
class ShapeProvider(MapnikProvider, object):
def __init__(self, *args, **kwargs):
self.mapfile = None
self.key = None
super(ShapeProvider, self).__init__(*args, **kwargs)
self.redis_client = redis.Redis()
def renderArea(self, *args, **kwargs):
self.set_mapfile()
return super(ShapeProvider, self).renderArea(*args, **kwargs)
def set_mapfile(self):
"""Set the mapfile variable."""
_mapfile = _mapfile_cache.get(self.key)
if not _mapfile:
_mapfile_path = self.redis_client.get('mapfile:%s' % self.key)
_mapfile = os.path.join(
_mapfile_path, 'style_grid.xml'
)
# put it in the local cache dict
_mapfile_cache[self.key] = _mapfile
if _mapfile != self.mapfile:
logger.info("[*] Changed xml_path from {} to {}".format(self.mapfile, _mapfile))
self.mapfile = _mapfile
The config then looks like this:
'grid':
{
"provider":
{
'class': '<your module>.providers.Vector:ShapeProvider',
'kwargs': {
"mapfile": "",
},
},
},
}