mirror of
https://github.com/simonw/datasette.git
synced 2025-12-10 16:51:24 +01:00
Started work on cli, which also meant adding setup.py
I'm using click, and click recommends using a setup.py - so I've added one of those. I also refactored code into a new datasite package. It's not quite deploying to now properly at the moment though - I seem to have messed up the path handling a bit. Also snuck in a new template for the "Row" view. Refs #40
This commit is contained in:
parent
2a9799bae6
commit
1592fd0419
15 changed files with 602 additions and 523 deletions
|
|
@ -1,7 +1,7 @@
|
||||||
FROM python:3
|
FROM python:3
|
||||||
COPY . /app
|
COPY . /app
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
RUN pip install -r requirements.txt
|
RUN pip install .
|
||||||
RUN python app.py --build
|
RUN datasite build
|
||||||
EXPOSE 8006
|
EXPOSE 8006
|
||||||
CMD ["python", "app.py"]
|
CMD ["datasite", "serve", "--port", "8006"]
|
||||||
|
|
|
||||||
0
datasite/__init__.py
Normal file
0
datasite/__init__.py
Normal file
|
|
@ -3,6 +3,8 @@ from sanic import response
|
||||||
from sanic.exceptions import NotFound
|
from sanic.exceptions import NotFound
|
||||||
from sanic.views import HTTPMethodView
|
from sanic.views import HTTPMethodView
|
||||||
from sanic_jinja2 import SanicJinja2
|
from sanic_jinja2 import SanicJinja2
|
||||||
|
from jinja2 import FileSystemLoader
|
||||||
|
import click
|
||||||
import sqlite3
|
import sqlite3
|
||||||
from contextlib import contextmanager
|
from contextlib import contextmanager
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
@ -14,7 +16,7 @@ import hashlib
|
||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
|
|
||||||
app_root = Path(__file__).parent
|
app_root = Path(__file__).parent.parent
|
||||||
|
|
||||||
BUILD_METADATA = 'build-metadata.json'
|
BUILD_METADATA = 'build-metadata.json'
|
||||||
DB_GLOBS = ('*.db', '*.sqlite', '*.sqlite3')
|
DB_GLOBS = ('*.db', '*.sqlite', '*.sqlite3')
|
||||||
|
|
@ -25,7 +27,12 @@ conns = {}
|
||||||
|
|
||||||
|
|
||||||
app = Sanic(__name__)
|
app = Sanic(__name__)
|
||||||
jinja = SanicJinja2(app)
|
jinja = SanicJinja2(
|
||||||
|
app,
|
||||||
|
loader=FileSystemLoader([
|
||||||
|
str(app_root / 'datasite' / 'templates')
|
||||||
|
])
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def get_conn(name):
|
def get_conn(name):
|
||||||
|
|
@ -43,10 +50,12 @@ def get_conn(name):
|
||||||
def ensure_build_metadata(regenerate=False):
|
def ensure_build_metadata(regenerate=False):
|
||||||
build_metadata = app_root / BUILD_METADATA
|
build_metadata = app_root / BUILD_METADATA
|
||||||
if build_metadata.exists() and not regenerate:
|
if build_metadata.exists() and not regenerate:
|
||||||
json.loads(build_metadata.read_text())
|
return json.loads(build_metadata.read_text())
|
||||||
|
print('Building metadata... path={}'.format(build_metadata))
|
||||||
metadata = {}
|
metadata = {}
|
||||||
for glob in DB_GLOBS:
|
for glob in DB_GLOBS:
|
||||||
for path in app_root.glob(glob):
|
for path in app_root.glob(glob):
|
||||||
|
print(' globbing, path={}'.format(path))
|
||||||
name = path.stem
|
name = path.stem
|
||||||
if name in metadata:
|
if name in metadata:
|
||||||
raise Exception('Multiple files with same stem %s' % name)
|
raise Exception('Multiple files with same stem %s' % name)
|
||||||
|
|
@ -154,7 +163,7 @@ class BaseView(HTTPMethodView):
|
||||||
@app.route('/')
|
@app.route('/')
|
||||||
async def index(request, sql=None):
|
async def index(request, sql=None):
|
||||||
databases = []
|
databases = []
|
||||||
for key, info in ensure_build_metadata(True).items():
|
for key, info in ensure_build_metadata().items():
|
||||||
database = {
|
database = {
|
||||||
'name': key,
|
'name': key,
|
||||||
'hash': info['hash'],
|
'hash': info['hash'],
|
||||||
|
|
@ -246,7 +255,7 @@ class TableView(BaseView):
|
||||||
|
|
||||||
|
|
||||||
class RowView(BaseView):
|
class RowView(BaseView):
|
||||||
template = 'table.html'
|
template = 'row.html'
|
||||||
|
|
||||||
def data(self, request, name, hash, table, pk_path):
|
def data(self, request, name, hash, table, pk_path):
|
||||||
conn = get_conn(name)
|
conn = get_conn(name)
|
||||||
|
|
@ -409,10 +418,3 @@ def sqlite_timelimit(conn, ms):
|
||||||
conn.set_progress_handler(handler, 10000)
|
conn.set_progress_handler(handler, 10000)
|
||||||
yield
|
yield
|
||||||
conn.set_progress_handler(None, 10000)
|
conn.set_progress_handler(None, 10000)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
if '--build' in sys.argv:
|
|
||||||
ensure_build_metadata(True)
|
|
||||||
else:
|
|
||||||
app.run(host="0.0.0.0", port=8006)
|
|
||||||
24
datasite/cli.py
Normal file
24
datasite/cli.py
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
import click
|
||||||
|
from .app import app, ensure_build_metadata
|
||||||
|
|
||||||
|
@click.group()
|
||||||
|
def cli():
|
||||||
|
"""
|
||||||
|
Datasite!
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
@cli.command()
|
||||||
|
def build():
|
||||||
|
ensure_build_metadata(True)
|
||||||
|
|
||||||
|
|
||||||
|
@cli.command()
|
||||||
|
@click.argument('files', type=click.Path(exists=True), nargs=-1)
|
||||||
|
@click.option('-h', '--host', default='0.0.0.0')
|
||||||
|
@click.option('-p', '--port', default=8001)
|
||||||
|
@click.option('--debug', is_flag=True)
|
||||||
|
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.run(host=host, port=port, debug=debug)
|
||||||
35
datasite/templates/row.html
Normal file
35
datasite/templates/row.html
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
{% extends "base.html" %}
|
||||||
|
|
||||||
|
{% block title %}{{ database }}: {{ table }}{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<h1><a href="/{{ database }}-{{ database_hash }}">{{ database }}</a></h1>
|
||||||
|
|
||||||
|
<h2><a href="/{{ database }}-{{ database_hash }}/{{ table }}">{{ table }}</a></h2>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
td {
|
||||||
|
white-space: pre;
|
||||||
|
vertical-align: top;
|
||||||
|
border-top: 1px solid #666;
|
||||||
|
padding: 2px 4px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
{% if primary_keys and row_link %}<th scope="col">Link</th>{% endif %}
|
||||||
|
{% for column in columns %}<th scope="col">{{ column }}</th>{% endfor %}
|
||||||
|
</tr>
|
||||||
|
{% for row in rows %}
|
||||||
|
<tr>
|
||||||
|
{% if primary_keys and row_link %}
|
||||||
|
<td><a href="/{{ database }}-{{ database_hash }}/{{ table }}/{{ row_link(row) }}">{{ row_link(row) }}</a></td>
|
||||||
|
{% endif %}
|
||||||
|
{% for td in row %}
|
||||||
|
<td>{{ td }}</td>
|
||||||
|
{% endfor %}
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</table>
|
||||||
|
{% if took_ms %}<small>Took {{ took_ms }}</small>{% endif %}
|
||||||
|
{% endblock %}
|
||||||
18
setup.py
Normal file
18
setup.py
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
from setuptools import setup, find_packages
|
||||||
|
|
||||||
|
setup(
|
||||||
|
name='datasite',
|
||||||
|
version='0.1',
|
||||||
|
packages=find_packages(),
|
||||||
|
package_data={'datasite': ['templates/*.html']},
|
||||||
|
include_package_data=True,
|
||||||
|
install_requires=[
|
||||||
|
'click==6.7',
|
||||||
|
'sanic==0.6.0',
|
||||||
|
'sanic-jinja2==0.5.5',
|
||||||
|
],
|
||||||
|
entry_points='''
|
||||||
|
[console_scripts]
|
||||||
|
datasite=datasite.cli:cli
|
||||||
|
''',
|
||||||
|
)
|
||||||
Loading…
Add table
Add a link
Reference in a new issue