def get_client(metadata_origins=None, tile_origins=None): from terracotta.server import create_app import terracotta if metadata_origins is not None: terracotta.update_settings(ALLOWED_ORIGINS_METADATA=metadata_origins) if tile_origins is not None: terracotta.update_settings(ALLOWED_ORIGINS_TILES=tile_origins) flask_app = create_app() return flask_app.test_client()
def test_bench_singleband_out_of_bounds(benchmark, benchmark_database): from terracotta.server import create_app from terracotta import update_settings update_settings(DRIVER_PATH=str(benchmark_database)) x, y, z = 0, 0, 20 flask_app = create_app() with flask_app.test_client() as client: rv = benchmark(client.get, f'/singleband/nodata/1/{z}/{x}/{y}.png') assert rv.status_code == 200
def test_bench_rgb_out_of_bounds(benchmark, big_raster_file_nodata, benchmark_database): from terracotta.server import create_app from terracotta import update_settings update_settings(DRIVER_PATH=str(benchmark_database)) x, y, z = 0, 0, 20 flask_app = create_app() with flask_app.test_client() as client: rv = benchmark(client.get, f'/rgb/nodata/{z}/{x}/{y}.png?r=1&g=2&b=3') assert rv.status_code == 200
def test_bench_rgb(benchmark, zoom, resampling, big_raster_file_nodata, benchmark_database): from terracotta.server import create_app from terracotta import update_settings update_settings(DRIVER_PATH=str(benchmark_database), RESAMPLING_METHOD=resampling, REPROJECTION_METHOD=resampling) zoom_level = ZOOM_XYZ[zoom] flask_app = create_app() with flask_app.test_client() as client: if zoom_level is not None: x, y, z = get_xyz(big_raster_file_nodata, zoom_level) rv = benchmark(client.get, f'/rgb/nodata/{z}/{x}/{y}.png?r=1&g=2&b=3') else: rv = benchmark(client.get, '/rgb/nodata/preview.png?r=1&g=2&b=3') assert rv.status_code == 200
def test_bench_singleband(benchmark, zoom, resampling, big_raster_file_nodata, benchmark_database): from terracotta.server import create_app from terracotta import update_settings, get_driver update_settings(DRIVER_PATH=str(benchmark_database), RESAMPLING_METHOD=resampling, REPROJECTION_METHOD=resampling) zoom_level = ZOOM_XYZ[zoom] flask_app = create_app() with flask_app.test_client() as client: if zoom_level is not None: x, y, z = get_xyz(big_raster_file_nodata, zoom_level) rv = benchmark(client.get, f'/singleband/nodata/1/{z}/{x}/{y}.png') else: rv = benchmark(client.get, f'/singleband/nodata/1/preview.png') assert rv.status_code == 200 assert not len(get_driver(str(benchmark_database))._raster_cache)
"""server/app.py Instantiated version of the Flask API. """ from terracotta import get_settings, logs from terracotta.server import create_app settings = get_settings() logs.set_logger(settings.LOGLEVEL, catch_warnings=True) app = create_app(debug=settings.DEBUG, profile=settings.FLASK_PROFILE)
def flask_app(): from terracotta.server import create_app return create_app()
driver = tc.get_driver(DRIVER_PATH) # Create an empty database if it doesn't exist os.makedirs(os.path.dirname(DRIVER_PATH), exist_ok=True) if nuke and os.path.isfile(DRIVER_PATH): os.remove(DRIVER_PATH) if not os.path.isfile(DRIVER_PATH): driver.create(keys=keys, key_descriptions=key_descriptions) # Insert the parameters. with driver.connect(): for entry in [ entry for entry in os.listdir(GEOTIFF_DIR) if entry[-5:] == ".tiff" ]: tiff_path = os.path.join(GEOTIFF_DIR, entry) tiff_dict = { keys[i]: value for i, value in enumerate(entry[:-5].split(".")) } driver.insert(tiff_dict, tiff_path) init_db(keys=["gfs", "parameter"], nuke=True) # Create terracotta server. update_settings(DRIVER_PATH=DRIVER_PATH, REPROJECTION_METHOD="nearest") server = create_app() # Bind custom stuff. point.register(server) if __name__ == '__main__': server.run(port=TC_PORT, host=TC_HOST, threaded=False)
def serve(database: str = None, raster_pattern: RasterPatternType = None, debug: bool = False, profile: bool = False, database_provider: str = None, allow_all_ips: bool = False, port: int = None, rgb_key: str = None) -> None: """Serve rasters through a local Flask development server. Either -d/--database or -r/--raster-pattern must be given. Example: $ terracotta serve -r /path/to/rasters/{name}/{date}_{band}_{}.tif The empty group {} is replaced by a wildcard matching anything (similar to * in glob patterns). This command is a data exploration tool and not meant for production use. Deploy Terracotta as a WSGI or serverless app instead. """ from terracotta import get_driver, update_settings from terracotta.server import create_app if (database is None) == (raster_pattern is None): raise click.UsageError('Either --database or --raster-pattern must be given') if raster_pattern is not None: dbfile = tempfile.NamedTemporaryFile(suffix='.sqlite', delete=False) dbfile.close() keys, raster_files = raster_pattern if rgb_key is not None: if rgb_key not in keys: raise click.BadParameter('RGB key not found in raster pattern') # re-order keys rgb_idx = keys.index(rgb_key) def push_to_last(seq: Sequence[Any], index: int) -> Tuple[Any, ...]: return (*seq[:index], *seq[index + 1:], seq[index]) keys = list(push_to_last(keys, rgb_idx)) raster_files = {push_to_last(k, rgb_idx): v for k, v in raster_files.items()} driver = get_driver(dbfile.name, provider='sqlite') driver.create(keys) with driver.connect(): click.echo('') for key, filepath in tqdm.tqdm(raster_files.items(), desc="Ingesting raster files"): driver.insert(key, filepath, skip_metadata=True) click.echo('') database = dbfile.name update_settings(DRIVER_PATH=database, DRIVER_PROVIDER=database_provider, DEBUG=debug, FLASK_PROFILE=profile) # find suitable port port_range = [port] if port is not None else range(5000, 5100) port = find_open_port(port_range) if port is None: click.echo(f'Could not find open port to bind to (ports tried: {port_range})', err=True) raise click.Abort() host = '0.0.0.0' if allow_all_ips else 'localhost' server_app = create_app(debug=debug, profile=profile) if os.environ.get('TC_TESTING'): return server_app.run(port=port, host=host, threaded=False) # pragma: no cover
def debug_flask_app(): from terracotta.server import create_app return create_app(debug=True)