def __call__(self, environ, start_response): """Main WSGI callable. """ # Translate the request to the filesystem. # ======================================== fspath = translate(self.config.paths.root, environ['PATH_INFO']) if self.config.paths.__ is not None: if fspath.startswith(self.config.paths.__): raise Response(404) # protect magic directory environ['PATH_TRANSLATED'] = fspath # Dispatch to a WSGI app or an aspen handler. # =========================================== app = self.get_app(environ) # 301 if app is not None: # app response = app(environ, start_response) # WSGI else: # handler if not exists(fspath): raise Response(404) check_trailing_slash(environ) fspath = find_default(self.config.defaults, fspath) # 403 environ['PATH_TRANSLATED'] = fspath environ['aspen.website'] = self fp = environ['aspen.fp'] = open(fspath) handler = self.get_handler(fp) fp.seek(0) response = handler.handle(environ, start_response) # WSGI return response
def wsgi(environ, start_response): path = environ['PATH_INFO'] fspath = translate(ROOT, path) if path.endswith('.png') and 'empties' not in path: # let people hit empties directly if they want; why not? # Parse and validate input. # ========================= # URL paths are of the form: # # /<color_scheme>/<zoom>/<x>,<y>.png # # E.g.: # # /classic/3/0,1.png raw = path[:-4] # strip extension try: assert raw.count('/') == 3, "%d /'s" % raw.count('/') foo, color_scheme, zoom, xy = raw.split('/') assert color_scheme in color_schemes, ( "bad color_scheme: " + color_scheme ) assert xy.count(',') == 1, "%d /'s" % xy.count(',') x, y = xy.split(',') assert zoom.isdigit() and x.isdigit() and y.isdigit(), "not digits" zoom = int(zoom) x = int(x) y = int(y) assert 0 <= zoom <= 30, "bad zoom: %d" % zoom except AssertionError, err: log.warn(err.args[0]) start_response('400 Bad Request', [('CONTENT-TYPE','text/plain')]) return ['Bad request.'] # Build and save the file. # ======================== # The tile that is built here will be served by the static handler. color_scheme = color_schemes[color_scheme] tile = backend.Tile(color_scheme, dots, zoom, x, y, fspath) if tile.is_empty(): log.info('serving empty tile %s' % path) fspath = color_scheme.get_empty_fspath(zoom) elif tile.is_stale() or ALWAYS_BUILD: log.info('rebuilding %s' % path) tile.rebuild() tile.save() else: log.info('serving cached tile %s' % path)
def wsgi(environ, start_response): path = environ['PATH_INFO'] fspath = translate(ROOT, path) if path.endswith('.png') and 'empties' not in path: # let people hit empties directly if they want; why not? # Parse and validate input. # ========================= # URL paths are of the form: # # /<color_scheme>/<zoom>/<x>,<y>.png # # E.g.: # # /classic/3/0,1.png raw = path[:-4] # strip extension try: assert raw.count('/') == 3, "%d /'s" % raw.count('/') foo, color_scheme, zoom, xy = raw.split('/') assert color_scheme in color_schemes, ("bad color_scheme: " + color_scheme) assert xy.count(',') == 1, "%d /'s" % xy.count(',') x, y = xy.split(',') assert zoom.isdigit() and x.isdigit() and y.isdigit(), "not digits" zoom = int(zoom) x = int(x) y = int(y) assert 0 <= zoom <= 30, "bad zoom: %d" % zoom except AssertionError, err: log.warn(err.args[0]) start_response('400 Bad Request', [('CONTENT-TYPE', 'text/plain')]) return ['Bad request.'] # Build and save the file. # ======================== # The tile that is built here will be served by the static handler. color_scheme = color_schemes[color_scheme] tile = backend.Tile(color_scheme, dots, zoom, x, y, fspath) if tile.is_empty(): log.info('serving empty tile %s' % path) fspath = color_scheme.get_empty_fspath(zoom) elif tile.is_stale() or ALWAYS_BUILD: log.info('rebuilding %s' % path) tile.rebuild() tile.save() else: log.info('serving cached tile %s' % path)
def wsgi(environ, start_response): path = environ['PATH_INFO'] fspath = translate(ROOT, path) if path.endswith('.png') and 'empties' not in path: # let people hit empties directly if they want; why not? # Parse and validate input. # ========================= # URL paths are of the form: # # /<mapname>/<maptype>/<zoom>/<x>,<y>.png # # E.g.: # # /crime/classic/3/0,1.png raw = path[:-4] # strip extension try: foo, map_name, map_type, zoom, xy = raw.split('/') x, y = xy.split(',') zoom = int(zoom) x = int(x) y = int(y) except AssertionError, err: log.warn(err.args[0]) start_response('400 Bad Request', [('CONTENT-TYPE','text/plain')]) return ['Bad request.'] # Build and save the file. # ======================== # The tile that is built here will be served by the static handler. from base import PostGISTile tile = PostGISTile(map_name, map_type, zoom, x, y, fspath) if tile.is_outrange(): log.info('serving empty tile %s' % path) elif tile.is_stale(): log.info('servering cached tile %s' %path) elif tile.is_empty(): log.info('serving empty tile %s' % path) else: log.info('rebuilding %s' % path) tile.rebuild() tile.save()
def get_app(self, environ): """Given a WSGI environ, return the first matching app. """ app = None test_path = environ['PATH_INFO'] if not test_path.endswith('/'): test_path += '/' for app_urlpath, _app in self.config.apps: if test_path.startswith(app_urlpath): environ['PATH_TRANSLATED'] = translate(self.config.paths.root, app_urlpath) if not isdir(environ['PATH_TRANSLATED']): raise Response(404) if app_urlpath.endswith('/'): check_trailing_slash(environ) app = _app break if app is None: log.debug("No app found for '%s'" % environ['PATH_INFO']) return app
def load_apps(self): """Return a list of (URI path, WSGI application) tuples. """ # Find a config file to parse. # ============================ apps = [] try: if self.paths.__ is None: raise NotImplementedError path = join(self.paths.__, 'etc', 'apps.conf') if not isfile(path): raise NotImplementedError except NotImplementedError: log.info("No apps configured.") return apps # We have a config file; proceed. # =============================== fp = open(path) lineno = 0 urlpaths = [] for line in fp: lineno += 1 original = line # for README.aspen line = clean(line) if not line: # blank line continue else: # specification # Perform basic validation. # ========================= if ' ' not in line: msg = "malformed line (no space): '%s'" % line raise AppsConfError(msg, lineno) urlpath, name = line.split(None, 1) if not urlpath.startswith('/'): msg = "URL path not specified absolutely: '%s'" % urlpath raise AppsConfError(msg, lineno) # Instantiate the app on the filesystem. # ====================================== fspath = utils.translate(self.paths.root, urlpath) if not isdir(fspath): os.makedirs(fspath) log.info("created app directory '%s'" % fspath) readme = join(fspath, 'README.aspen') open(readme, 'w+').write(README_aspen % (lineno, original)) # Determine whether we already have an app for this path. # ======================================================= msg = "URL path is contested: '%s'" % urlpath contested = AppsConfError(msg, lineno) if urlpath in urlpaths: raise contested if urlpath.endswith('/'): if urlpath[:-1] in urlpaths: raise contested elif urlpath + '/' in urlpaths: raise contested urlpaths.append(urlpath) # Load the app, check it, store it. # ================================= obj = colon.colonize(name, fp.name, lineno) if inspect.isclass(obj): obj = obj(self) if not callable(obj): msg = "'%s' is not callable" % name raise AppsConfError(msg, lineno) apps.append((urlpath, obj)) apps.sort() apps.reverse() return apps
def show_flows(environ, start_response): ROOT = aspen.paths.root path = environ["PATH_INFO"] print path fspath = translate(ROOT, path) zoomLevel, bound = path[1:].split("/") zoomLevel = int(float(zoomLevel)) centroid_radius = 0 offset_xy = 0 offset_z = 0 arrow_weight = 0 flow_filename = "" roi_filename = "" flows = None centroid = [] centroid_patches = [] flow_patches = [] cluster_polygons = [] print zoomLevel if 5 <= zoomLevel < 7: centroid_radius = 15000 offset_xy = 25000 offset_z = 2000 arrow_weight = 100000 flows = global_flow_map[1] cluster_polygons = global_roi_map[1] print 1 elif 7 <= zoomLevel < 9: centroid_radius = 1500 offset_xy = 2500 offset_z = 200 arrow_weight = 30000 flows = global_flow_map[10] cluster_polygons = global_roi_map[10] print 2 elif zoomLevel >= 9: centroid_radius = 150 offset_xy = 250 offset_z = 20 arrow_weight = 3000 flows = global_flow_map[19] cluster_polygons = global_roi_map[19] print zoomLevel > 14 dt = datetime.now() print dt.strftime("%d/%m/%y %H:%M:%S") polygons = project_polygon(cluster_polygons) for polygon in polygons: center = shapely.Polygon(polygon).centroid centroid.append([center.x, center.y]) for flow in flows: flow_patches.append( gen_travel_flow(centroid[flow[0]], centroid[flow[1]], flows[flow], m, offset_xy, offset_z, arrow_weight) ) dt = datetime.now() print dt.strftime("%d/%m/%y %H:%M:%S") for i, p in enumerate(centroid): centroid_patches.append(gen_centroid_shape(centroid[i], centroid_radius)) centroid_patches.append(gen_centroid_shape(centroid[i], centroid_radius / 3.0)) centroid[i] = list(m(p[0], p[1], inverse=True)) # write back to http client str_centroids = ";".join("&".join(",".join(str(i) for i in p) for p in polygon) for polygon in centroid_patches) str_clusters = ";".join("&".join(",".join(str(i) for i in p) for p in polygon) for polygon in cluster_polygons) str_flows = ";".join("&".join(",".join(str(i) for i in p) for p in polygon) for polygon in flow_patches) response = "%s|%s|%s" % (str_clusters, str_centroids, str_flows) dt = datetime.now() print dt.strftime("%d/%m/%y %H:%M:%S") start_response("200 OK", [("CONTENT-TYPE", "text/plain")]) return response