[tilestache] 04/22: Imported Upstream version 1.50.0+ds
Bas Couwenberg
sebastic at debian.org
Thu Oct 27 21:40:29 UTC 2016
This is an automated email from the git hooks/post-receive script.
sebastic pushed a commit to branch master
in repository tilestache.
commit e98046c48ef0a9ab61348202705f81ec8d741b49
Author: Bas Couwenberg <sebastic at xs4all.nl>
Date: Mon Oct 17 08:30:30 2016 +0200
Imported Upstream version 1.50.0+ds
---
PKG-INFO | 2 +-
TileStache/Config.py | 20 ++-
TileStache/Core.py | 25 ++-
.../Providers/DejaVuSansMono-alphanumeric.ttf | Bin 26616 -> 0 bytes
TileStache/Goodies/Providers/MapnikGrid.py | 25 ++-
TileStache/Goodies/Providers/UtfGridComposite.py | 49 +++---
TileStache/Goodies/VecTiles/server.py | 34 +++-
TileStache/Mapnik.py | 29 +++-
TileStache/PixelEffects.py | 172 +++++++++++++++++++++
TileStache/Providers.py | 4 +-
TileStache/Redis.py | 8 +-
TileStache/S3.py | 8 +-
TileStache/VERSION | 2 +-
TileStache/Vector/__init__.py | 2 +-
doc/TileStache.Config.html | 9 +-
doc/TileStache.Core.html | 10 ++
doc/TileStache.Goodies.Providers.MapnikGrid.html | 13 +-
...eStache.Goodies.Providers.UtfGridComposite.html | 4 +-
doc/TileStache.Goodies.VecTiles.server.html | 16 +-
doc/TileStache.Mapnik.html | 17 +-
doc/TileStache.S3.html | 5 +-
doc/TileStache.html | 11 +-
doc/index.html | 23 ++-
scripts/tilestache-list.py | 2 +-
scripts/tilestache-seed.py | 2 +-
setup.cfg | 5 +
setup.py | 12 +-
27 files changed, 429 insertions(+), 80 deletions(-)
diff --git a/PKG-INFO b/PKG-INFO
index cf8cbe7..0ed0267 100644
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,6 +1,6 @@
Metadata-Version: 1.0
Name: TileStache
-Version: 1.49.11
+Version: 1.50.0
Summary: A stylish alternative for caching your map tiles.
Home-page: http://tilestache.org
Author: Michal Migurski
diff --git a/TileStache/Config.py b/TileStache/Config.py
index 456ceae..e241d24 100644
--- a/TileStache/Config.py
+++ b/TileStache/Config.py
@@ -79,6 +79,7 @@ import Core
import Caches
import Providers
import Geography
+import PixelEffects
class Configuration:
""" A complete site configuration, with a collection of Layer objects.
@@ -308,7 +309,7 @@ def _parseConfigfileCache(cache_dict, dirpath):
add_kwargs('host', 'port', 'db')
elif _class is Caches.S3.Cache:
- add_kwargs('bucket', 'access', 'secret', 'use_locks', 'path', 'reduced_redundancy')
+ add_kwargs('bucket', 'access', 'secret', 'use_locks', 'path', 'reduced_redundancy', 'policy')
else:
raise Exception('Unknown cache: %s' % cache_dict['name'])
@@ -422,6 +423,22 @@ def _parseConfigfileLayer(layer_dict, config, dirpath):
png_kwargs = dict([(str(k), v) for (k, v) in layer_dict['png options'].items()])
#
+ # Do pixel effect
+ #
+
+ pixel_effect = None
+
+ if 'pixel effect' in layer_dict:
+ pixel_effect_dict = layer_dict['pixel effect']
+ pixel_effect_name = pixel_effect_dict.get('name')
+ if pixel_effect_name in PixelEffects.all:
+ pixel_effect_kwargs = {}
+ for k, v in pixel_effect_dict.items():
+ if k != 'name':
+ pixel_effect_kwargs[str(k)] = float(v)
+ PixelEffectClass = PixelEffects.all[pixel_effect_name]
+ pixel_effect = PixelEffectClass(**pixel_effect_kwargs)
+ #
# Do the provider
#
@@ -447,6 +464,7 @@ def _parseConfigfileLayer(layer_dict, config, dirpath):
layer.provider = _class(layer, **provider_kwargs)
layer.setSaveOptionsJPEG(**jpeg_kwargs)
layer.setSaveOptionsPNG(**png_kwargs)
+ layer.pixel_effect = pixel_effect
return layer
diff --git a/TileStache/Core.py b/TileStache/Core.py
index c89eee7..416d787 100644
--- a/TileStache/Core.py
+++ b/TileStache/Core.py
@@ -73,6 +73,9 @@ configuration file as a dictionary:
through to PIL: http://effbot.org/imagingbook/format-jpeg.htm.
- "png options" is an optional dictionary of PNG creation options, passed
through to PIL: http://effbot.org/imagingbook/format-png.htm.
+- "pixel effect" is an optional dictionary that defines an effect to be applied
+ for all tiles of this layer. Pixel effect can be any of these: blackwhite,
+ greyscale, desaturate, pixelate, halftone, or blur.
The public-facing URL of a single tile for this layer might look like this:
@@ -93,6 +96,13 @@ Sample PNG creation options:
"palette": "filename.act"
}
+Sample pixel effect:
+
+ {
+ "name": "desaturate",
+ "factor": 0.85
+ }
+
Sample bounds:
{
@@ -334,6 +344,7 @@ class Layer:
self.bitmap_palette = None
self.jpeg_options = {}
self.png_options = {}
+ self.pixel_effect = None
def name(self):
""" Figure out what I'm called, return a name if there is one.
@@ -468,7 +479,7 @@ class Layer:
are mutually exclusive options
"""
if self.bounds and self.bounds.excludes(coord):
- raise NoTileLeftBehind(Image.new('RGB', (self.dim, self.dim), (0x99, 0x99, 0x99)))
+ raise NoTileLeftBehind(Image.new('RGBA', (self.dim, self.dim), (0, 0, 0, 0)))
srs = self.projection.srs
xmin, ymin, xmax, ymax = self.envelope(coord)
@@ -517,6 +528,18 @@ class Layer:
if format.lower() == 'png':
t_index = self.png_options.get('transparency', None)
tile = apply_palette(tile, self.bitmap_palette, t_index)
+
+ if self.pixel_effect:
+ # this is where we apply the pixel effect if there is one
+
+ if pass_through:
+ raise KnownUnknown(
+ 'Cannot apply pixel effect in pass_through mode'
+ )
+
+ # if tile is an image
+ if format.lower() in ('png', 'jpeg', 'tiff', 'bmp', 'gif'):
+ tile = self.pixel_effect.apply(tile)
if self.doMetatile():
# tile will be set again later
diff --git a/TileStache/Goodies/Providers/DejaVuSansMono-alphanumeric.ttf b/TileStache/Goodies/Providers/DejaVuSansMono-alphanumeric.ttf
deleted file mode 100644
index 24b9a7d..0000000
Binary files a/TileStache/Goodies/Providers/DejaVuSansMono-alphanumeric.ttf and /dev/null differ
diff --git a/TileStache/Goodies/Providers/MapnikGrid.py b/TileStache/Goodies/Providers/MapnikGrid.py
index 05c1b22..361596b 100644
--- a/TileStache/Goodies/Providers/MapnikGrid.py
+++ b/TileStache/Goodies/Providers/MapnikGrid.py
@@ -31,9 +31,13 @@ scale: What to divide the tile pixel size by to get the resulting grid size. Usu
buffer: buffer around the queried features, in px, default 0. Use this to prevent problems on tile boundaries.
"""
import json
+from os.path import exists
from TileStache.Core import KnownUnknown
from TileStache.Geography import getProjectionByName
from urlparse import urlparse, urljoin
+from tempfile import mkstemp
+from urllib import urlopen
+import os
try:
import mapnik
@@ -69,8 +73,7 @@ class Provider:
"""
"""
if self.mapnik is None:
- self.mapnik = mapnik.Map(0, 0)
- mapnik.load_map(self.mapnik, str(self.mapfile))
+ self.mapnik = get_mapnikMap(self.mapfile)
# buffer as fraction of tile size
buffer = float(self.buffer) / 256
@@ -121,3 +124,21 @@ class SaveableResponse:
raise KnownUnknown('MapnikGrid only saves .json tiles, not "%s"' % format)
out.write(self.content)
+
+def get_mapnikMap(mapfile):
+ """ Get a new mapnik.Map instance for a mapfile
+ """
+ mmap = mapnik.Map(0, 0)
+
+ if exists(mapfile):
+ mapnik.load_map(mmap, str(mapfile))
+
+ else:
+ handle, filename = mkstemp()
+ os.write(handle, urlopen(mapfile).read())
+ os.close(handle)
+
+ mapnik.load_map(mmap, filename)
+ os.unlink(filename)
+
+ return mmap
diff --git a/TileStache/Goodies/Providers/UtfGridComposite.py b/TileStache/Goodies/Providers/UtfGridComposite.py
index 6f3a16f..480cfe7 100644
--- a/TileStache/Goodies/Providers/UtfGridComposite.py
+++ b/TileStache/Goodies/Providers/UtfGridComposite.py
@@ -40,9 +40,6 @@ class Provider:
def __init__(self, layer, stack, layer_id=None, wrapper=None):
#Set up result storage
- self.resultGrid = []
- self.gridKeys = []
- self.gridData = {}
self.layer = layer
self.stack = stack
@@ -50,10 +47,14 @@ class Provider:
self.wrapper = wrapper
def renderTile(self, width, height, srs, coord):
-
+
+ resultGrid = []
+ gridKeys = []
+ gridData = {}
+
for l in self.stack:
- self.addLayer(l, coord)
- return SaveableResponse(self.writeResult())
+ self.addLayer(resultGrid, gridKeys, gridData, l, coord)
+ return SaveableResponse(self.writeResult(resultGrid, gridKeys, gridData))
def getTypeByExtension(self, extension):
""" Get mime-type and format by file extension.
@@ -64,9 +65,9 @@ class Provider:
return 'text/json', 'JSON'
- def addLayer( self, layerDef, coord ):
+ def addLayer( self, resultGrid, gridKeys, gridData, layerDef, coord ):
- mime, layer = TileStache.getTile(self.layer.config.layers[layerDef['src']], coord, 'JSON')[1]
+ mime, layer = TileStache.getTile(self.layer.config.layers[layerDef['src']], coord, 'JSON')
# raise KnownUnknown(layer)
if layerDef['wrapper'] == None:
layer = json.loads(layer)
@@ -76,19 +77,19 @@ class Provider:
gridSize = len(layer['grid'])
#init resultGrid based on given layers (if required)
- if len(self.resultGrid) == 0:
+ if len(resultGrid) == 0:
for i in xrange(gridSize):
- self.resultGrid.append([])
+ resultGrid.append([])
for j in xrange(gridSize):
- self.resultGrid[i].append(-1)
+ resultGrid[i].append(-1)
keys = layer['keys']
keyRemap = {}
for k in keys:
- if k in self.gridKeys:
+ if k in gridKeys:
for ext in xrange(ord('a'), ord('z')+1):
- if not k+chr(ext) in self.gridKeys:
+ if not k+chr(ext) in gridKeys:
keyRemap[k] = (k+chr(ext))
break
if not k in keyRemap:
@@ -109,19 +110,19 @@ class Provider:
key = keyRemap[keys[idNo]]
if not key in addedKeys:
- self.gridKeys.append(key)
+ gridKeys.append(key)
addedKeys.append(key)
if layerDef['layer_id'] != None and self.layer_id != None: #Add layer name attribute
layer['data'][keys[idNo]][self.layer_id] = layerDef['layer_id']
- self.gridData[key] = layer['data'][keys[idNo]]
+ gridData[key] = layer['data'][keys[idNo]]
- newId = self.gridKeys.index(key)
+ newId = gridKeys.index(key)
- self.resultGrid[x][y] = newId
+ resultGrid[x][y] = newId
- def writeResult( self ):
- gridSize = len(self.resultGrid)
+ def writeResult( self, resultGrid, gridKeys, gridData ):
+ gridSize = len(resultGrid)
finalKeys = []
finalData = {}
@@ -134,7 +135,7 @@ class Provider:
for y in xrange(gridSize):
for x in xrange(gridSize):
- id = self.resultGrid[x][y]
+ id = resultGrid[x][y]
if not id in idToFinalId:
idToFinalId[id] = finalIdCounter
@@ -143,8 +144,8 @@ class Provider:
if id == -1:
finalKeys.append("")
else:
- finalKeys.append(self.gridKeys[id])
- finalData[self.gridKeys[id]] = self.gridData[self.gridKeys[id]]
+ finalKeys.append(gridKeys[id])
+ finalData[gridKeys[id]] = gridData[gridKeys[id]]
finalId = idToFinalId[id]
finalGrid[y] = finalGrid[y] + self.encodeId(finalId)
@@ -158,11 +159,11 @@ class Provider:
result += "], \"data\": { "
first = True
- for entry in self.gridData:
+ for entry in gridData:
if not first:
result += ","
first = False
- result += "\"" + entry + "\": " + json.dumps(self.gridData[entry]) + ""
+ result += "\"" + entry + "\": " + json.dumps(gridData[entry]) + ""
result += "}, \"grid\": ["
diff --git a/TileStache/Goodies/VecTiles/server.py b/TileStache/Goodies/VecTiles/server.py
index c7f90c5..f36bc41 100644
--- a/TileStache/Goodies/VecTiles/server.py
+++ b/TileStache/Goodies/VecTiles/server.py
@@ -99,6 +99,20 @@ class Provider:
]
}
}
+
+ The queries field has an alternate dictionary-like syntax which maps
+ zoom levels to their associated query. Zoom levels for which there is
+ no query may be omitted and are assumed null. This is equivalent to
+ the queries defined above:
+
+ "queries": {
+ "10": "SELECT way AS __geometry__, highway, name FROM planet_osm_line -- zoom 10+ ",
+ "11": "http://example.com/query-z11.pgsql",
+ "12": "query-z12-plus.pgsql"
+ }
+
+ Note that JSON requires keys to be strings, therefore the zoom levels
+ must be enclosed in quotes.
'''
def __init__(self, layer, dbinfo, queries, clip=True, srid=900913, simplify=1.0, simplify_until=16):
'''
@@ -113,12 +127,22 @@ class Provider:
self.simplify = float(simplify)
self.simplify_until = int(simplify_until)
- self.queries = []
self.columns = {}
-
- for query in queries:
+
+ # Each type creates an iterator yielding tuples of:
+ # (zoom level (int), query (string))
+ if isinstance(queries, dict):
+ # Add 1 to include space for zoom level 0
+ n_zooms = max(int(z) for z in queries) + 1
+ queryiter = ((int(z), q) for z, q in queries.iteritems())
+ else: # specified as array
+ n_zooms = len(queries)
+ queryiter = enumerate(queries)
+
+ # For the dict case, unspecified zoom levels are assumed to be null.
+ self.queries = [None] * n_zooms
+ for z, query in queryiter:
if query is None:
- self.queries.append(None)
continue
#
@@ -133,7 +157,7 @@ class Provider:
elif scheme == 'http' and ' ' not in url:
query = urlopen(url).read()
- self.queries.append(query)
+ self.queries[z] = query
def renderTile(self, width, height, srs, coord):
''' Render a single tile, return a Response instance.
diff --git a/TileStache/Mapnik.py b/TileStache/Mapnik.py
index de148f3..76ad779 100644
--- a/TileStache/Mapnik.py
+++ b/TileStache/Mapnik.py
@@ -60,6 +60,13 @@ class ImageProvider:
- fonts (optional)
Local directory path to *.ttf font files.
+
+ - "scale factor" (optional)
+ Scale multiplier used for Mapnik rendering pipeline. Used for
+ supporting retina resolution.
+
+ For more information about the scale factor, see:
+ https://github.com/mapnik/mapnik/wiki/Scale-factor
More information on Mapnik and Mapnik XML:
- http://mapnik.org
@@ -67,7 +74,7 @@ class ImageProvider:
- http://trac.mapnik.org/wiki/XMLConfigReference
"""
- def __init__(self, layer, mapfile, fonts=None):
+ def __init__(self, layer, mapfile, fonts=None, scale_factor=None):
""" Initialize Mapnik provider with layer and mapfile.
XML mapfile keyword arg comes from TileStache config,
@@ -96,6 +103,8 @@ class ImageProvider:
for font in glob(path.rstrip('/') + '/*.ttf'):
engine.register_font(str(font))
+ self.scale_factor = scale_factor
+
@staticmethod
def prepareKeywordArgs(config_dict):
""" Convert configured parameters to keyword args for __init__().
@@ -104,6 +113,9 @@ class ImageProvider:
if 'fonts' in config_dict:
kwargs['fonts'] = config_dict['fonts']
+
+ if 'scale factor' in config_dict:
+ kwargs['scale_factor'] = int(config_dict['scale factor'])
return kwargs
@@ -126,7 +138,12 @@ class ImageProvider:
self.mapnik.zoom_to_box(Box2d(xmin, ymin, xmax, ymax))
img = mapnik.Image(width, height)
- mapnik.render(self.mapnik, img)
+ # Don't even call render with scale factor if it's not
+ # defined. Plays safe with older versions.
+ if self.scale_factor is None:
+ mapnik.render(self.mapnik, img)
+ else:
+ mapnik.render(self.mapnik, img, self.scale_factor)
except:
self.mapnik = None
raise
@@ -181,19 +198,19 @@ class GridProvider:
An empty list will return no field names, while a value of null is
equivalent to all.
- - layer index (optional)
+ - layer_index (optional)
Which layer from the mapfile to render, defaults to 0 (first layer).
- layers (optional)
- Ordered list of (layer index, fields) to combine; if provided
- layers overrides both layer index and fields arguments.
+ Ordered list of (layer_index, fields) to combine; if provided
+ layers overrides both layer_index and fields arguments.
An empty fields list will return no field names, while a value of null
is equivalent to all fields.
- scale (optional)
Scale factor of output raster, defaults to 4 (64x64).
- - layer id key (optional)
+ - layer_id_key (optional)
If set, each item in the 'data' property will have its source mapnik
layer name added, keyed by this value. Useful for distingushing
between data items.
diff --git a/TileStache/PixelEffects.py b/TileStache/PixelEffects.py
new file mode 100644
index 0000000..1b49a68
--- /dev/null
+++ b/TileStache/PixelEffects.py
@@ -0,0 +1,172 @@
+""" Different effects that can be applied to tiles.
+
+Options are:
+
+- blackwhite:
+
+ "effect":
+ {
+ "name": "blackwhite"
+ }
+
+- greyscale:
+
+ "effect":
+ {
+ "name": "greyscale"
+ }
+
+- desaturate:
+ Has an optional parameter "factor" that defines the saturation of the image.
+ Defaults to 0.85.
+
+ "effect":
+ {
+ "name": "desaturate",
+ "factor": 0.85
+ }
+
+- pixelate:
+ Has an optional parameter "reduction" that defines how pixelated the image
+ will be (size of pixel). Defaults to 5.
+
+ "effect":
+ {
+ "name": "pixelate",
+ "factor": 5
+ }
+
+- halftone:
+
+ "effect":
+ {
+ "name": "halftone"
+ }
+
+- blur:
+ Has an optional parameter "radius" that defines the blurriness of an image.
+ Larger radius means more blurry. Defaults to 5.
+
+ "effect":
+ {
+ "name": "blur",
+ "radius": 5
+ }
+"""
+
+from PIL import Image, ImageFilter
+
+
+def put_original_alpha(original_image, new_image):
+ """ Put alpha channel of original image (if any) in the new image.
+ """
+
+ try:
+ alpha_idx = original_image.mode.index('A')
+ alpha_channel = original_image.split()[alpha_idx]
+ new_image.putalpha(alpha_channel)
+ except ValueError:
+ pass
+ return new_image
+
+
+class PixelEffect:
+ """ Base class for all pixel effects.
+ Subclasses must implement method `apply_effect`.
+ """
+
+ def __init__(self):
+ pass
+
+ def apply(self, image):
+ try:
+ image = image.image() # Handle Providers.Verbatim tiles
+ except (AttributeError, TypeError):
+ pass
+ return self.apply_effect(image)
+
+ def apply_effect(self, image):
+ raise NotImplementedError(
+ 'PixelEffect subclasses must implement method `apply_effect`.'
+ )
+
+
+class Blackwhite(PixelEffect):
+ """ Returns a black and white version of the original image.
+ """
+
+ def apply_effect(self, image):
+ new_image = image.convert('1').convert(image.mode)
+ return put_original_alpha(image, new_image)
+
+
+class Greyscale(PixelEffect):
+ """ Returns a grescale version of the original image.
+ """
+
+ def apply_effect(self, image):
+ return image.convert('LA').convert(image.mode)
+
+
+class Desaturate(PixelEffect):
+ """ Returns a desaturated version of the original image.
+ `factor` is a number between 0 and 1, where 1 results in a
+ greyscale image (no color), and 0 results in the original image.
+ """
+
+ def __init__(self, factor=0.85):
+ self.factor = min(max(factor, 0.0), 1.0) # 0.0 <= factor <= 1.0
+
+ def apply_effect(self, image):
+ avg = image.convert('LA').convert(image.mode)
+ return Image.blend(image, avg, self.factor)
+
+
+class Pixelate(PixelEffect):
+ """ Returns a pixelated version of the original image.
+ `reduction` defines how pixelated the image will be (size of pixels).
+ """
+
+ def __init__(self, reduction=5):
+ self.reduction = max(reduction, 1) # 1 <= reduction
+
+ def apply_effect(self, image):
+ tmp_size = (int(image.size[0] / self.reduction),
+ int(image.size[1] / self.reduction))
+ pixelated = image.resize(tmp_size, Image.NEAREST)
+ return pixelated.resize(image.size, Image.NEAREST)
+
+
+class Halftone(PixelEffect):
+ """ Returns a halftone version of the original image.
+ """
+
+ def apply_effect(self, image):
+ cmyk = []
+ for band in image.convert('CMYK').split():
+ cmyk.append(band.convert('1').convert('L'))
+ new_image = Image.merge('CMYK', cmyk).convert(image.mode)
+ return put_original_alpha(image, new_image)
+
+
+class Blur(PixelEffect):
+ """ Returns a blurred version of the original image.
+ `radius` defines the blurriness of an image. Larger radius means more
+ blurry.
+ """
+
+ def __init__(self, radius=5):
+ self.radius = max(radius, 0) # 0 <= radius
+
+ def apply_effect(self, image):
+ return image.filter(ImageFilter.GaussianBlur(self.radius))
+
+
+all = {
+ 'blackwhite': Blackwhite,
+ 'greyscale': Greyscale,
+ 'desaturate': Desaturate,
+ 'pixelate': Pixelate,
+ 'halftone': Halftone,
+ 'blur': Blur,
+}
diff --git a/TileStache/Providers.py b/TileStache/Providers.py
index 0d309e7..1f9c7a1 100644
--- a/TileStache/Providers.py
+++ b/TileStache/Providers.py
@@ -346,8 +346,8 @@ class UrlTemplate:
xmin = sw_point.x
srs = self.source_projection.srs
- mapping = {'width': width, 'height': height, 'srs': srs, 'zoom': zoom}
- mapping.update({'xmin': xmin, 'ymin': ymin, 'xmax': xmax, 'ymax': ymax})
+ mapping = {'width': width, 'height': height, 'srs': srs, 'zoom': zoom,
+ 'xmin': xmin, 'ymin': ymin, 'xmax': xmax, 'ymax': ymax}
href = self.template.safe_substitute(mapping)
req = urllib2.Request(href)
diff --git a/TileStache/Redis.py b/TileStache/Redis.py
index a8a7483..dc3fd94 100644
--- a/TileStache/Redis.py
+++ b/TileStache/Redis.py
@@ -113,4 +113,10 @@ class Cache:
""" Save a cached tile.
"""
key = tile_key(layer, coord, format, self.key_prefix)
- self.conn.set(key, body)
+
+ # note: setting ex=0 will raise an error
+ cache_lifespan = layer.cache_lifespan
+ if cache_lifespan == 0:
+ cache_lifespan = None
+
+ self.conn.set(key, body, ex=cache_lifespan)
diff --git a/TileStache/S3.py b/TileStache/S3.py
index 92a9ebb..6c98ef3 100644
--- a/TileStache/S3.py
+++ b/TileStache/S3.py
@@ -23,6 +23,9 @@ S3 cache parameters:
secret
Optional secret access key for your S3 account.
+ policy
+ Optional S3 ACL policy for uploaded tiles. Default is 'public-read'.
+
use_locks
Optional boolean flag for whether to use the locking feature on S3.
True by default. A good reason to set this to false would be the
@@ -68,11 +71,12 @@ def tile_key(layer, coord, format, path = ''):
class Cache:
"""
"""
- def __init__(self, bucket, access=None, secret=None, use_locks=True, path='', reduced_redundancy=False):
+ def __init__(self, bucket, access=None, secret=None, use_locks=True, path='', reduced_redundancy=False, policy='public-read'):
self.bucket = S3Bucket(S3Connection(access, secret), bucket)
self.use_locks = bool(use_locks)
self.path = path
self.reduced_redundancy = reduced_redundancy
+ self.policy = policy
def lock(self, layer, coord, format):
""" Acquire a cache lock for this tile.
@@ -133,4 +137,4 @@ class Cache:
content_type, encoding = guess_type('example.'+format)
headers = content_type and {'Content-Type': content_type} or {}
- key.set_contents_from_string(body, headers, policy='public-read', reduced_redundancy=self.reduced_redundancy)
+ key.set_contents_from_string(body, headers, policy=self.policy, reduced_redundancy=self.reduced_redundancy)
diff --git a/TileStache/VERSION b/TileStache/VERSION
index 041c636..5a5c721 100644
--- a/TileStache/VERSION
+++ b/TileStache/VERSION
@@ -1 +1 @@
-1.49.11
+1.50.0
diff --git a/TileStache/Vector/__init__.py b/TileStache/Vector/__init__.py
index 6ab0b08..2ff987c 100644
--- a/TileStache/Vector/__init__.py
+++ b/TileStache/Vector/__init__.py
@@ -303,7 +303,7 @@ def _tile_perimeter_geom(coord, projection, padded):
Uses _tile_perimeter().
"""
perimeter = _tile_perimeter(coord, projection, padded)
- wkt = 'POLYGON((%s))' % ', '.join(['%.3f %.3f' % xy for xy in perimeter])
+ wkt = 'POLYGON((%s))' % ', '.join(['%.7f %.7f' % xy for xy in perimeter])
geom = ogr.CreateGeometryFromWkt(wkt)
ref = osr.SpatialReference()
diff --git a/doc/TileStache.Config.html b/doc/TileStache.Config.html
index aebd19a..5232d0c 100644
--- a/doc/TileStache.Config.html
+++ b/doc/TileStache.Config.html
@@ -77,10 +77,11 @@ documentation for TileStache.Providers, TileStache.Core, and
<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="TileStache.Caches.html">TileStache.Caches</a><br>
<a href="TileStache.Core.html">TileStache.Core</a><br>
</td><td width="25%" valign=top><a href="TileStache.Geography.html">TileStache.Geography</a><br>
-<a href="TileStache.Providers.html">TileStache.Providers</a><br>
-</td><td width="25%" valign=top><a href="logging.html">logging</a><br>
-<a href="sys.html">sys</a><br>
-</td><td width="25%" valign=top></td></tr></table></td></tr></table><p>
+<a href="TileStache.PixelEffects.html">TileStache.PixelEffects</a><br>
+</td><td width="25%" valign=top><a href="TileStache.Providers.html">TileStache.Providers</a><br>
+<a href="logging.html">logging</a><br>
+</td><td width="25%" valign=top><a href="sys.html">sys</a><br>
+</td></tr></table></td></tr></table><p>
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
<tr bgcolor="#ee77aa">
<td colspan=3 valign=bottom> <br>
diff --git a/doc/TileStache.Core.html b/doc/TileStache.Core.html
index 717d982..c4c71d5 100644
--- a/doc/TileStache.Core.html
+++ b/doc/TileStache.Core.html
@@ -84,6 +84,9 @@ configuration file as a dictionary:<br>
through to PIL: <a href="http://effbot.org/imagingbook/format-jpeg.htm">http://effbot.org/imagingbook/format-jpeg.htm</a>.<br>
- "png options" is an optional dictionary of PNG creation options, passed<br>
through to PIL: <a href="http://effbot.org/imagingbook/format-png.htm">http://effbot.org/imagingbook/format-png.htm</a>.<br>
+- "pixel effect" is an optional dictionary that defines an effect to be applied<br>
+ for all tiles of this layer. Pixel effect can be any of these: blackwhite,<br>
+ greyscale, desaturate, pixelate, halftone, or blur.<br>
<br>
The public-facing URL of a single tile for this layer might look like this:<br>
<br>
@@ -104,6 +107,13 @@ Sample PNG creation options:<br>
"palette": "filename.act"<br>
}<br>
<br>
+Sample pixel effect:<br>
+ <br>
+ {<br>
+ "name": "desaturate",<br>
+ "factor": 0.85<br>
+ }<br>
+ <br>
Sample bounds:<br>
<br>
{<br>
diff --git a/doc/TileStache.Goodies.Providers.MapnikGrid.html b/doc/TileStache.Goodies.Providers.MapnikGrid.html
index ff762ad..91273e6 100644
--- a/doc/TileStache.Goodies.Providers.MapnikGrid.html
+++ b/doc/TileStache.Goodies.Providers.MapnikGrid.html
@@ -48,7 +48,8 @@ buffer: buffer around the queried features, in&nbs
<tr><td bgcolor="#aa55cc"><tt> </tt></td><td> </td>
<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="json.html">json</a><br>
-</td><td width="25%" valign=top></td><td width="25%" valign=top></td><td width="25%" valign=top></td></tr></table></td></tr></table><p>
+</td><td width="25%" valign=top><a href="os.html">os</a><br>
+</td><td width="25%" valign=top></td><td width="25%" valign=top></td></tr></table></td></tr></table><p>
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
<tr bgcolor="#ee77aa">
<td colspan=3 valign=bottom> <br>
@@ -91,5 +92,13 @@ TileStache.getTile() expects to be able to save&nb
<dl><dt><a name="SaveableResponse-save"><strong>save</strong></a>(self, out, format)</dt></dl>
-</td></tr></table></td></tr></table>
+</td></tr></table></td></tr></table><p>
+<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
+<tr bgcolor="#eeaa77">
+<td colspan=3 valign=bottom> <br>
+<font color="#ffffff" face="helvetica, arial"><big><strong>Functions</strong></big></font></td></tr>
+
+<tr><td bgcolor="#eeaa77"><tt> </tt></td><td> </td>
+<td width="100%"><dl><dt><a name="-get_mapnikMap"><strong>get_mapnikMap</strong></a>(mapfile)</dt><dd><tt>Get a new mapnik.Map instance for a mapfile</tt></dd></dl>
+</td></tr></table>
</body></html>
\ No newline at end of file
diff --git a/doc/TileStache.Goodies.Providers.UtfGridComposite.html b/doc/TileStache.Goodies.Providers.UtfGridComposite.html
index e8cd6b9..4490c72 100644
--- a/doc/TileStache.Goodies.Providers.UtfGridComposite.html
+++ b/doc/TileStache.Goodies.Providers.UtfGridComposite.html
@@ -70,7 +70,7 @@ if layer_id is not set in the layer or&n
<td width="100%">Methods defined here:<br>
<dl><dt><a name="Provider-__init__"><strong>__init__</strong></a>(self, layer, stack, layer_id<font color="#909090">=None</font>, wrapper<font color="#909090">=None</font>)</dt></dl>
-<dl><dt><a name="Provider-addLayer"><strong>addLayer</strong></a>(self, layerDef, coord)</dt></dl>
+<dl><dt><a name="Provider-addLayer"><strong>addLayer</strong></a>(self, resultGrid, gridKeys, gridData, layerDef, coord)</dt></dl>
<dl><dt><a name="Provider-decodeId"><strong>decodeId</strong></a>(self, id)</dt></dl>
@@ -81,7 +81,7 @@ This only accepts "json".</tt></dd></dl>
<dl><dt><a name="Provider-renderTile"><strong>renderTile</strong></a>(self, width, height, srs, coord)</dt></dl>
-<dl><dt><a name="Provider-writeResult"><strong>writeResult</strong></a>(self)</dt></dl>
+<dl><dt><a name="Provider-writeResult"><strong>writeResult</strong></a>(self, resultGrid, gridKeys, gridData)</dt></dl>
</td></tr></table> <p>
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
diff --git a/doc/TileStache.Goodies.VecTiles.server.html b/doc/TileStache.Goodies.VecTiles.server.html
index 9f1199f..3e1c7c5 100644
--- a/doc/TileStache.Goodies.VecTiles.server.html
+++ b/doc/TileStache.Goodies.VecTiles.server.html
@@ -196,7 +196,21 @@ URL containing a query for zoom 11, and
"query-z12-plus.pgsql"<br>
]<br>
}<br>
- }<br> </tt></td></tr>
+ }<br>
+ <br>
+The queries field has an alternate dictionary-like syntax which maps<br>
+zoom levels to their associated query. Zoom levels for which there is<br>
+no query may be omitted and are assumed null. This is equivalent to<br>
+the queries defined above:<br>
+ <br>
+ "queries": {<br>
+ "10": "SELECT way AS __geometry__, highway, name FROM planet_osm_line -- zoom 10+ ",<br>
+ "11": "<a href="http://example.com/query-z11.pgsql">http://example.com/query-z11.pgsql</a>",<br>
+ "12": "query-z12-plus.pgsql"<br>
+ }<br>
+ <br>
+Note that JSON requires keys to be strings, therefore the zoom levels<br>
+must be enclosed in quotes.<br> </tt></td></tr>
<tr><td> </td>
<td width="100%">Methods defined here:<br>
<dl><dt><a name="Provider-__init__"><strong>__init__</strong></a>(self, layer, dbinfo, queries, clip<font color="#909090">=True</font>, srid<font color="#909090">=900913</font>, simplify<font color="#909090">=1.0</font>, simplify_until<font color="#909090">=16</font>)</dt></dl>
diff --git a/doc/TileStache.Mapnik.html b/doc/TileStache.Mapnik.html
index b818411..d1a859d 100644
--- a/doc/TileStache.Mapnik.html
+++ b/doc/TileStache.Mapnik.html
@@ -84,19 +84,19 @@ Arguments:<br>
An empty list will return no field names, while a value of null is<br>
equivalent to all.<br>
<br>
-- layer index (optional)<br>
+- layer_index (optional)<br>
Which layer from the mapfile to render, defaults to 0 (first layer).<br>
<br>
- layers (optional)<br>
- Ordered list of (layer index, fields) to combine; if provided<br>
- layers overrides both layer index and fields arguments.<br>
+ Ordered list of (layer_index, fields) to combine; if provided<br>
+ layers overrides both layer_index and fields arguments.<br>
An empty fields list will return no field names, while a value of null <br>
is equivalent to all fields.<br>
<br>
- scale (optional)<br>
Scale factor of output raster, defaults to 4 (64x64).<br>
<br>
-- layer id key (optional)<br>
+- layer_id_key (optional)<br>
If set, each item in the 'data' property will have its source mapnik<br>
layer name added, keyed by this value. Useful for distingushing<br>
between data items.<br>
@@ -140,13 +140,20 @@ Arguments:<br>
- fonts (optional)<br>
Local directory path to *.ttf font files.<br>
<br>
+- "scale factor" (optional)<br>
+ Scale multiplier used for Mapnik rendering pipeline. Used for<br>
+ supporting retina resolution.<br>
+ <br>
+ For more information about the scale factor, see: <br>
+ https://github.com/mapnik/mapnik/wiki/Scale-factor<br>
+ <br>
More information on Mapnik and Mapnik XML:<br>
- <a href="http://mapnik.org">http://mapnik.org</a><br>
- <a href="http://trac.mapnik.org/wiki/XMLGettingStarted">http://trac.mapnik.org/wiki/XMLGettingStarted</a><br>
- <a href="http://trac.mapnik.org/wiki/XMLConfigReference">http://trac.mapnik.org/wiki/XMLConfigReference</a><br> </tt></td></tr>
<tr><td> </td>
<td width="100%">Methods defined here:<br>
-<dl><dt><a name="ImageProvider-__init__"><strong>__init__</strong></a>(self, layer, mapfile, fonts<font color="#909090">=None</font>)</dt><dd><tt>Initialize Mapnik provider with layer and mapfile.<br>
+<dl><dt><a name="ImageProvider-__init__"><strong>__init__</strong></a>(self, layer, mapfile, fonts<font color="#909090">=None</font>, scale_factor<font color="#909090">=None</font>)</dt><dd><tt>Initialize Mapnik provider with layer and mapfile.<br>
<br>
XML mapfile keyword arg comes from TileStache config,<br>
and is an absolute path by the time it gets here.</tt></dd></dl>
diff --git a/doc/TileStache.S3.html b/doc/TileStache.S3.html
index c016ce2..aae6e87 100644
--- a/doc/TileStache.S3.html
+++ b/doc/TileStache.S3.html
@@ -34,6 +34,9 @@ S3 cache parameters:<br>
secret<br>
Optional secret access key for your S3 account.<br>
<br>
+ policy<br>
+ Optional S3 ACL policy for uploaded tiles. Default is 'public-read'.<br>
+ <br>
use_locks<br>
Optional boolean flag for whether to use the locking feature on S3.<br>
True by default. A good reason to set this to false would be the<br>
@@ -71,7 +74,7 @@ AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY will be use
<tr><td bgcolor="#ffc8d8"><tt> </tt></td><td> </td>
<td width="100%">Methods defined here:<br>
-<dl><dt><a name="Cache-__init__"><strong>__init__</strong></a>(self, bucket, access<font color="#909090">=None</font>, secret<font color="#909090">=None</font>, use_locks<font color="#909090">=True</font>, path<font color="#909090">=''</font>, reduced_redundancy<font color="#909090">=False</font>)</dt></dl>
+<dl><dt><a name="Cache-__init__"><strong>__init__</strong></a>(self, bucket, access<font color="#909090">=None</font>, secret<font color="#909090">=None</font>, use_locks<font color="#909090">=True</font>, path<font color="#909090">=''</font>, reduced_redundancy<font color="#909090">=False</font>, policy<font color="#909090">='public-read'</font>)</dt></dl>
<dl><dt><a name="Cache-lock"><strong>lock</strong></a>(self, layer, coord, format)</dt><dd><tt>Acquire a cache lock for this tile.<br>
<br>
diff --git a/doc/TileStache.html b/doc/TileStache.html
index 0561bf0..df6b847 100644
--- a/doc/TileStache.html
+++ b/doc/TileStache.html
@@ -6,7 +6,7 @@
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
<tr bgcolor="#7799ee">
<td valign=bottom> <br>
-<font color="#ffffff" face="helvetica, arial"> <br><big><big><strong>TileStache</strong></big></big> (version 1.49.11)</font></td
+<font color="#ffffff" face="helvetica, arial"> <br><big><big><strong>TileStache</strong></big></big> (version 1.50.0)</font></td
><td align=right valign=bottom
><font color="#ffffff" face="helvetica, arial"><a href=".">index</a></font></td></tr></table>
<p><tt>A stylish alternative for caching your map tiles.<br>
@@ -33,11 +33,12 @@ Documentation available at <a href="http://tilestache.org/doc/">h
<a href="TileStache.MBTiles.html">MBTiles</a><br>
<a href="TileStache.Mapnik.html">Mapnik</a><br>
<a href="TileStache.Memcache.html">Memcache</a><br>
-</td><td width="25%" valign=top><a href="TileStache.Pixels.html">Pixels</a><br>
+</td><td width="25%" valign=top><a href="TileStache.PixelEffects.html">PixelEffects</a><br>
+<a href="TileStache.Pixels.html">Pixels</a><br>
<a href="TileStache.Providers.html">Providers</a><br>
<a href="TileStache.Redis.html">Redis</a><br>
-<a href="TileStache.S3.html">S3</a><br>
-</td><td width="25%" valign=top><a href="TileStache.Sandwich.html">Sandwich</a><br>
+</td><td width="25%" valign=top><a href="TileStache.S3.html">S3</a><br>
+<a href="TileStache.Sandwich.html">Sandwich</a><br>
<a href="TileStache.Vector.html"><strong>Vector</strong> (package)</a><br>
</td></tr></table></td></tr></table><p>
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
@@ -190,6 +191,6 @@ Fractions of a second may be present if
<font color="#ffffff" face="helvetica, arial"><big><strong>Data</strong></big></font></td></tr>
<tr><td bgcolor="#55aa55"><tt> </tt></td><td> </td>
-<td width="100%"><strong>__version__</strong> = '1.49.11'<br>
+<td width="100%"><strong>__version__</strong> = '1.50.0'<br>
<strong>stdout</strong> = <open file '<stdout>', mode 'w'></td></tr></table>
</body></html>
\ No newline at end of file
diff --git a/doc/index.html b/doc/index.html
index 1472da6..b00319c 100644
--- a/doc/index.html
+++ b/doc/index.html
@@ -76,7 +76,7 @@
</p>
<p>
- <strong>This document covers TileStache version 1.49.11</strong>.
+ <strong>This document covers TileStache version 1.50.0</strong>.
</p>
<p>
@@ -837,7 +837,8 @@ Example layer configuration:
"redirects": …,
"tile height": …,
"jpeg options": …,
- "png options": …
+ "png options": …,
+ "pixel effect": { … }
}
<span class="bg">}
}</span>
@@ -973,6 +974,14 @@ Shared layer parameters:
Valid options include <var>palette</var> (URL or filename), <var>palette256</var>
(boolean) and <var>optimize</var> (boolean).
</dd>
+
+ <dt>pixel effect</dt>
+ <dd>
+ An optional dictionary that defines an effect to be applied for all tiles
+ of this layer. Pixel effect can be any of these: <samp>blackwhite</samp>,
+ <samp>greyscale</samp>, <samp>desaturate</samp>, <samp>pixelate</samp>,
+ <samp>halftone</samp>, or <samp>blur</samp>.
+ </dd>
</dl>
<h3><a id="providers" name="providers">Providers</a> <a href="#providers" class="permalink">¶</a></h3>
@@ -1398,7 +1407,7 @@ Example Mapnik Grid provider configurations:
{
"name": "mapnik grid",
"mapfile": "style.xml",
- "layer index": 1
+ "layer_index": 1
},
<span class="bg">}
"two-grids":
@@ -1433,21 +1442,21 @@ Mapnik Grid provider parameters:
An empty list will return no field names, while a value of <samp>null</samp>
is equivalent to all.
</dd>
- <dt>layer index</dt>
+ <dt>layer_index</dt>
<dd>
Optional layer from the mapfile to render, defaults to <samp>0</samp> (first layer).
</dd>
<dt>layers</dt>
<dd>
- Optional ordered list of (layer index, fields) to combine; if provided
- <var>layers</var> overrides both <var>layer index</var> and <var>fields</var>
+ Optional ordered list of (layer_index, fields) to combine; if provided
+ <var>layers</var> overrides both <var>layer_index</var> and <var>fields</var>
arguments.
</dd>
<dt>scale</dt>
<dd>
Optional scale factor of output raster, defaults to <samp>4</samp> (64×64).
</dd>
- <dt>layer id key</dt>
+ <dt>layer_id_key</dt>
<dd>
Optional. If set, each item in the <samp>"data"</samp> property will have
its source mapnik layer name added, keyed by this value. Useful for
diff --git a/scripts/tilestache-list.py b/scripts/tilestache-list.py
index 71f771c..9488a63 100644
--- a/scripts/tilestache-list.py
+++ b/scripts/tilestache-list.py
@@ -41,7 +41,7 @@ defaults = dict(padding=0, bbox=(37.777, -122.352, 37.839, -122.226))
parser.set_defaults(**defaults)
parser.add_option('-b', '--bbox', dest='bbox',
- help='Bounding box in floating point geographic coordinates: south west north east. Default value is %.3f, %.3f, %.3f, %.3f.' % defaults['bbox'],
+ help='Bounding box in floating point geographic coordinates: south west north east. Default value is %.7f, %.7f, %.7f, %.7f.' % defaults['bbox'],
type='float', nargs=4)
parser.add_option('-p', '--padding', dest='padding',
diff --git a/scripts/tilestache-seed.py b/scripts/tilestache-seed.py
index ca43bc7..d62dfaf 100644
--- a/scripts/tilestache-seed.py
+++ b/scripts/tilestache-seed.py
@@ -54,7 +54,7 @@ parser.add_option('-l', '--layer', dest='layer',
help='Layer name from configuration, typically required.')
parser.add_option('-b', '--bbox', dest='bbox',
- help='Bounding box in floating point geographic coordinates: south west north east. Default value is %.3f, %.3f, %.3f, %.3f.' % defaults['bbox'],
+ help='Bounding box in floating point geographic coordinates: south west north east. Default value is %.7f, %.7f, %.7f, %.7f.' % defaults['bbox'],
type='float', nargs=4)
parser.add_option('-p', '--padding', dest='padding',
diff --git a/setup.cfg b/setup.cfg
new file mode 100644
index 0000000..861a9f5
--- /dev/null
+++ b/setup.cfg
@@ -0,0 +1,5 @@
+[egg_info]
+tag_build =
+tag_date = 0
+tag_svn_revision = 0
+
diff --git a/setup.py b/setup.py
index 963c7da..f4f74fe 100644
--- a/setup.py
+++ b/setup.py
@@ -1,6 +1,10 @@
#!/usr/bin/env python
-from distutils.core import setup
+try:
+ from setuptools import setup
+except ImportError:
+ from distutils.core import setup
+
import pkg_resources
import sys
@@ -19,10 +23,10 @@ def is_installed(name):
requires = ['ModestMaps >=1.3.0','simplejson', 'Werkzeug']
# Soft dependency on PIL or Pillow
-if is_installed('Pillow') or sys.platform == 'win32':
- requires.append('Pillow')
-else:
+if is_installed('PIL'):
requires.append('PIL')
+else:
+ requires.append('Pillow')
setup(name='TileStache',
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-grass/tilestache.git
More information about the Pkg-grass-devel
mailing list