def all_features(pid): project = Project.get(Project.id == pid) query = Feature.select().where(Feature.project == project) features = [] for f in query: features.append([f.ref, [f.lat/1e7, f.lon/1e7], f.action]) return app.response_class('features = {}'.format(json.dumps( features, ensure_ascii=False).encode('utf-8')), mimetype='application/javascript')
def export_audit(pid): project = Project.get(Project.id == pid) if not is_admin(get_user(), project): return redirect(url_for('front')) update_audit(project) project.save() return app.response_class( project.audit or '{}', mimetype='application/json', headers={'Content-Disposition': 'attachment;filename=audit_{}.json'.format(project.name)})
def external_audit(pid): project = Project.get(Project.id == pid) if not is_admin(get_user(), project): return redirect(url_for('front')) query = Feature.select().where(Feature.project == project, Feature.audit.is_null(False)) result = {} for feat in query: audit = json.loads(feat.audit or {}) props = json.loads(feat.feature)['properties'] eaudit = {} if 'move' in audit: if audit['move'] == 'osm': if 'were_coords' in props['were_coords']: eaudit['move'] = props['were_coords'] elif isinstance(audit['move'], list) and len(audit['move']) == 2: eaudit['move'] = audit['move'] if 'keep' in audit: keep = {} for k in audit['keep']: orig = None if 'tags_deleted.' + k in props: orig = props['tags_deleted.' + k] elif 'tags_changed.' + k in props: orig = props['tags_changed.' + k] orig = orig[:orig.find(' -> ')] if orig: keep[k] = orig if keep: eaudit['keep'] = keep if audit.get('skip'): if audit.get('comment', '').lower() != 'duplicate': eaudit['skip'] = audit.get('comment', '<no reason>') if eaudit: result[feat.ref] = eaudit return app.response_class( json.dumps(result, ensure_ascii=False, indent=1, sort_keys=True), mimetype='application/json', headers={ 'Content-Disposition': 'attachment;filename=ext_audit_{}.json'.format(project.name) })
def all_features(pid): project = Project.get(Project.id == pid) region = request.args.get('region') if region: query = Feature.select(Feature.ref, Feature.lat, Feature.lon, Feature.action).where( Feature.project == project, Feature.region == region).tuples() features = [] for ref, lat, lon, action in query: features.append([ref, [lat / 1e7, lon / 1e7], action]) features_js = json.dumps(features, ensure_ascii=False) else: if not project.features_js: update_features_cache(project) try: project.save() except OperationalError: # Sometimes wait is too long and MySQL disappears pass features_js = project.features_js return app.response_class('features = {}'.format(features_js), mimetype='application/javascript')
def render(): options = {} variables = {} # bounding box if 'bbox' in request.form: bbox = request.form['bbox'] if re.match('^[0-9.-]+(?:,[0-9.-]+){3}$', bbox): options['bbox'] = ' '.join(bbox.split(',')) # image dimensions mode = request.form.get('dim', 'both') if mode == 'zoom' and 'zoom' in request.form: zoom = request.form['zoom'] if re.match('^\d\d?$', zoom): options['zoom'] = zoom elif 'width' in request.form or 'height' in request.form: dim = '{} {}'.format( request.form.get('width', '0') if mode != 'height' else 0, request.form.get('height', '0') if mode != 'width' else 0) if not re.match('^\d{1,5} \d{1,5}$', dim): return 'Dimensions are incorrect: ' + dim if request.form.get('units', '') == 'px': whkey = 'size-px' else: whkey = 'size' options['ppi'] = '300' options[whkey] = dim if 'margin' in request.form: margin = request.form['margin'] if re.match('^\d\d?$', margin): options['margin'] = margin if mode == 'width' or mode == 'height': options['norotate'] = None # test for size limit size = dim.split(' ') mult = max(int(size[0]), int(size[1])) mult = mult * mult if 'ppi' in options: mult = mult * 16 if mult > 2000 * 2000: return 'Dimensions are too big' # GPX trace (specific to veloroad style) traceFile = None if config.ROUTE and 'trace' in request.files and request.files[ 'trace'].filename: traceFile = tempfile.NamedTemporaryFile('wb+', delete=False) request.files['trace'].save(traceFile) traceFile.close() variables['route'] = traceFile.name if 'fit' in request.form: del options['bbox'] if 'norotate' in options: del options['norotate'] options['fit'] = config.ROUTE if 'drawtrace' in request.form: options['add-layers'] = config.ROUTE # scale bar (specific to veloroad style) if config.SCALE and 'scale' in request.form: scalepos = request.form.get('scalepos', '') if re.match('^[0-9.-]+, *[0-9.-]+$', scalepos): options['add-layers'] = ','.join([ config.ROUTE, config.SCALE ]) if 'add-layers' in options else config.SCALE variables['scale'] = scalepos scalens = re.match('^([1-9])-([1-5][05]?)$', request.form.get('scalens', '5-1')) variables['scalen'] = scalens.group(1) if scalens else 5 variables['scales'] = scalens.group(2) if scalens else 1 # map style, file format and mime type style = request.form.get('style', '') styles = {s[0]: [s[2], s[3]] for s in config.STYLES} if style not in styles: style = config.STYLES[0][0] fmt = request.form.get('format', '') formats = {f[0]: f[2] for f in config.FORMATS} if fmt not in formats: fmt = config.FORMATS[0][0] options['format'] = fmt mime = formats[fmt] # build command line for nik4 outfile, outputName = tempfile.mkstemp() command = ['/usr/bin/env', config.PYTHON, config.NIK4] for k, v in options.items(): command.append('--{}'.format(k)) if v is not None: command.extend(v.split(' ')) command.append(styles[style][0]) command.append(outputName) if styles[style][1]: command.append('--vars') for k, v in variables.items(): command.append('{}={}'.format(k, v)) # check for running nik4 ps = subprocess.Popen('ps -e|grep nik4.py', shell=True, stdout=subprocess.PIPE) psout, _ = ps.communicate() if b'nik4' in psout: if traceFile: os.remove(traceFile.name) return 'Nik4 is running, please try later.' # start nik4 process process = subprocess.Popen(command, stderr=subprocess.PIPE) _, err = process.communicate() code = process.returncode # Remove the temporary trace file if traceFile: os.remove(traceFile.name) if code == 0 and os.stat(outputName).st_size > 0: if fmt == 'svg': # run mapnik-group-text from mapnik_group_text import mapnik_group_text as mgt mgt_opt = {'dmax': 60, 'group': True} mgt.process_stream(open(outputName, 'rb'), outputName, mgt_opt) # run svn-resize if dimensions are known if 'size' in options or 'size-px' in options: from svg_resize import svg_resize as svgr svgr_opt = {} if 'size' in options: d = options['size'].split(' ') suffix = 'mm' else: d = options['size-px'].split(' ') suffix = 'px' if 'norotate' in options or not d[0] or not d[1]: if d[0]: svgr_opt['width'] = d[0] + suffix if d[1]: svgr_opt['height'] = d[1] + suffix else: svgr_opt['longest'] = max(d[0], d[1]) + suffix svgr_opt['shortest'] = min(d[0], d[1]) + suffix if 'margin' in options: svgr_opt['margin'] = options['margin'] svgr_opt['frame'] = True svgr_opt['input'] = outputName svgr.process_stream(svgr_opt) afn = '{}-{}.{}'.format( style, datetime.datetime.now().strftime('%y%m%d-%H%M'), fmt) fp = tempfile.TemporaryFile() with open(outputName, 'rb') as f: shutil.copyfileobj(f, fp) os.remove(outputName) fp.seek(0) return send_file(fp, mimetype=mime, add_etags=False, as_attachment=True, attachment_filename=afn) else: os.remove(outputName) if code > 0: msg = 'Error {} happened.'.format(code) else: msg = 'Resulting file is empty.' msg += '\nCommand line:\n{}\n\nOutput:\n'.format(' '.join(command)) msg += err.decode('utf-8') return app.response_class(msg, mimetype='text/plain')
def robots(): return app.response_class('User-agent: *\nDisallow: /', mimetype='text/plain')
def no_robots(): return app.response_class('User-agent: *\nDisallow: /', mimetype='text/plain')