From 1fc75809a6aa17860944b4cc3a4d7175cd53b1f4 Mon Sep 17 00:00:00 2001 From: Simon Willison Date: Sat, 4 Nov 2017 19:13:44 -0700 Subject: [PATCH] Refactored everything into a factory function I now call a factory function to construct the Sanic app: app = app_factory(files) This allows me to pass additional arguments to it, e.g. the files to serve. Also refactored my class-based views to accept jinja as an argument, e.g: app.add_route( TableView.as_view(jinja), '//' ) --- datasite/app.py | 99 +++++++++++++++++++++++++++++-------------------- datasite/cli.py | 3 +- 2 files changed, 61 insertions(+), 41 deletions(-) diff --git a/datasite/app.py b/datasite/app.py index a1f50e32..ac74c534 100644 --- a/datasite/app.py +++ b/datasite/app.py @@ -25,15 +25,6 @@ SQL_TIME_LIMIT_MS = 1000 conns = {} -app = Sanic(__name__) -jinja = SanicJinja2( - app, - loader=FileSystemLoader([ - str(app_root / 'datasite' / 'templates') - ]) -) - - def get_conn(name): if name not in conns: info = ensure_build_metadata()[name] @@ -89,6 +80,9 @@ def ensure_build_metadata(regenerate=False): class BaseView(HTTPMethodView): template = None + def __init__(self, jinja): + self.jinja = jinja + def redirect(self, request, path): if request.query_string: path = '{}?{}'.format( @@ -147,7 +141,7 @@ class BaseView(HTTPMethodView): if callable(extra_template_data) else extra_template_data )} - r = jinja.render( + r = self.jinja.render( self.template, request, **context, @@ -159,32 +153,34 @@ class BaseView(HTTPMethodView): return r -@app.route('/') -async def index(request, sql=None): - databases = [] - for key, info in ensure_build_metadata().items(): - database = { - 'name': key, - 'hash': info['hash'], - 'path': '{}-{}'.format(key, info['hash'][:7]), - 'tables_truncated': sorted( - info['tables'].items(), - key=lambda p: p[1], - reverse=True - )[:5], - 'tables_count': len(info['tables'].items()), - 'tables_more': len(info['tables'].items()) > 5, - 'total_rows': sum(info['tables'].values()), - } - databases.append(database) - return jinja.render( - 'index.html', - request, - databases=databases, - ) +class IndexView(HTTPMethodView): + def __init__(self, jinja): + self.jinja = jinja + + async def get(self, request): + databases = [] + for key, info in ensure_build_metadata().items(): + database = { + 'name': key, + 'hash': info['hash'], + 'path': '{}-{}'.format(key, info['hash'][:7]), + 'tables_truncated': sorted( + info['tables'].items(), + key=lambda p: p[1], + reverse=True + )[:5], + 'tables_count': len(info['tables'].items()), + 'tables_more': len(info['tables'].items()) > 5, + 'total_rows': sum(info['tables'].values()), + } + databases.append(database) + return self.jinja.render( + 'index.html', + request, + databases=databases, + ) -@app.route('/favicon.ico') async def favicon(request): return response.text('') @@ -286,12 +282,6 @@ class RowView(BaseView): } -app.add_route(DatabaseView.as_view(), '/') -app.add_route(DatabaseDownload.as_view(), '/') -app.add_route(TableView.as_view(), '//') -app.add_route(RowView.as_view(), '///') - - def resolve_db_name(db_name, **kwargs): databases = ensure_build_metadata() hash = None @@ -418,3 +408,32 @@ def sqlite_timelimit(conn, ms): conn.set_progress_handler(handler, 10000) yield conn.set_progress_handler(None, 10000) + + +def app_factory(files): + app = Sanic(__name__) + jinja = SanicJinja2( + app, + loader=FileSystemLoader([ + str(app_root / 'datasite' / 'templates') + ]) + ) + app.add_route(IndexView.as_view(jinja), '/') + app.add_route(favicon, '/favicon.ico') + app.add_route( + DatabaseView.as_view(jinja), + '/' + ) + app.add_route( + DatabaseDownload.as_view(jinja), + '/' + ) + app.add_route( + TableView.as_view(jinja), + '//' + ) + app.add_route( + RowView.as_view(jinja), + '///' + ) + return app diff --git a/datasite/cli.py b/datasite/cli.py index 71f0cab1..fd5a1cf7 100644 --- a/datasite/cli.py +++ b/datasite/cli.py @@ -1,6 +1,6 @@ import click from click_default_group import DefaultGroup -from .app import app, ensure_build_metadata +from .app import app_factory, ensure_build_metadata @click.group(cls=DefaultGroup, default='serve', default_if_no_args=True) @@ -23,4 +23,5 @@ def build(): def serve(files, host, port, debug): """Serve up specified database files with a web UI""" click.echo('Serve! files={} on port {}'.format(files, port)) + app = app_factory(files) app.run(host=host, port=port, debug=debug)