kopia lustrzana https://github.com/simonw/datasette
Keyword-only arguments for a bunch of internal methods, refs #1822
rodzic
5f9f567acb
commit
49a11a6042
|
@ -190,6 +190,7 @@ class Datasette:
|
|||
def __init__(
|
||||
self,
|
||||
files=None,
|
||||
*,
|
||||
immutables=None,
|
||||
cache_headers=True,
|
||||
cors=False,
|
||||
|
@ -410,7 +411,7 @@ class Datasette:
|
|||
def unsign(self, signed, namespace="default"):
|
||||
return URLSafeSerializer(self._secret, namespace).loads(signed)
|
||||
|
||||
def get_database(self, name=None, route=None):
|
||||
def get_database(self, name=None, *, route=None):
|
||||
if route is not None:
|
||||
matches = [db for db in self.databases.values() if db.route == route]
|
||||
if not matches:
|
||||
|
@ -421,7 +422,7 @@ class Datasette:
|
|||
name = [key for key in self.databases.keys() if key != "_internal"][0]
|
||||
return self.databases[name]
|
||||
|
||||
def add_database(self, db, name=None, route=None):
|
||||
def add_database(self, db, name=None, *, route=None):
|
||||
new_databases = self.databases.copy()
|
||||
if name is None:
|
||||
# Pick a unique name for this database
|
||||
|
@ -466,7 +467,7 @@ class Datasette:
|
|||
orig[key] = upd_value
|
||||
return orig
|
||||
|
||||
def metadata(self, key=None, database=None, table=None, fallback=True):
|
||||
def metadata(self, key=None, *, database=None, table=None, fallback=True):
|
||||
"""
|
||||
Looks up metadata, cascading backwards from specified level.
|
||||
Returns None if metadata value is not found.
|
||||
|
@ -518,7 +519,7 @@ class Datasette:
|
|||
def _metadata(self):
|
||||
return self.metadata()
|
||||
|
||||
def plugin_config(self, plugin_name, database=None, table=None, fallback=True):
|
||||
def plugin_config(self, plugin_name, *, database=None, table=None, fallback=True):
|
||||
"""Return config for plugin, falling back from specified database/table"""
|
||||
plugins = self.metadata(
|
||||
"plugins", database=database, table=table, fallback=fallback
|
||||
|
@ -714,6 +715,7 @@ class Datasette:
|
|||
db_name,
|
||||
sql,
|
||||
params=None,
|
||||
*,
|
||||
truncate=False,
|
||||
custom_time_limit=None,
|
||||
page_size=None,
|
||||
|
@ -943,7 +945,7 @@ class Datasette:
|
|||
)
|
||||
|
||||
async def render_template(
|
||||
self, templates, context=None, request=None, view_name=None
|
||||
self, templates, context=None, *, request=None, view_name=None
|
||||
):
|
||||
if not self._startup_invoked:
|
||||
raise Exception("render_template() called before await ds.invoke_startup()")
|
||||
|
|
|
@ -118,7 +118,9 @@ class Request:
|
|||
return dict(parse_qsl(body.decode("utf-8"), keep_blank_values=True))
|
||||
|
||||
@classmethod
|
||||
def fake(cls, path_with_query_string, method="GET", scheme="http", url_vars=None):
|
||||
def fake(
|
||||
cls, path_with_query_string, *, method="GET", scheme="http", url_vars=None
|
||||
):
|
||||
"""Useful for constructing Request objects for tests"""
|
||||
path, _, query_string = path_with_query_string.partition("?")
|
||||
scope = {
|
||||
|
@ -204,7 +206,7 @@ class AsgiWriter:
|
|||
)
|
||||
|
||||
|
||||
async def asgi_send_json(send, info, status=200, headers=None):
|
||||
async def asgi_send_json(send, info, *, status=200, headers=None):
|
||||
headers = headers or {}
|
||||
await asgi_send(
|
||||
send,
|
||||
|
@ -215,7 +217,7 @@ async def asgi_send_json(send, info, status=200, headers=None):
|
|||
)
|
||||
|
||||
|
||||
async def asgi_send_html(send, html, status=200, headers=None):
|
||||
async def asgi_send_html(send, html, *, status=200, headers=None):
|
||||
headers = headers or {}
|
||||
await asgi_send(
|
||||
send,
|
||||
|
@ -226,7 +228,7 @@ async def asgi_send_html(send, html, status=200, headers=None):
|
|||
)
|
||||
|
||||
|
||||
async def asgi_send_redirect(send, location, status=302):
|
||||
async def asgi_send_redirect(send, location, *, status=302):
|
||||
await asgi_send(
|
||||
send,
|
||||
"",
|
||||
|
@ -236,12 +238,12 @@ async def asgi_send_redirect(send, location, status=302):
|
|||
)
|
||||
|
||||
|
||||
async def asgi_send(send, content, status, headers=None, content_type="text/plain"):
|
||||
await asgi_start(send, status, headers, content_type)
|
||||
async def asgi_send(send, content, status, *, headers=None, content_type="text/plain"):
|
||||
await asgi_start(send, status=status, headers=headers, content_type=content_type)
|
||||
await send({"type": "http.response.body", "body": content.encode("utf-8")})
|
||||
|
||||
|
||||
async def asgi_start(send, status, headers=None, content_type="text/plain"):
|
||||
async def asgi_start(send, status, *, headers=None, content_type="text/plain"):
|
||||
headers = headers or {}
|
||||
# Remove any existing content-type header
|
||||
headers = {k: v for k, v in headers.items() if k.lower() != "content-type"}
|
||||
|
@ -259,7 +261,7 @@ async def asgi_start(send, status, headers=None, content_type="text/plain"):
|
|||
|
||||
|
||||
async def asgi_send_file(
|
||||
send, filepath, filename=None, content_type=None, chunk_size=4096, headers=None
|
||||
send, filepath, filename=None, *, content_type=None, chunk_size=4096, headers=None
|
||||
):
|
||||
headers = headers or {}
|
||||
if filename:
|
||||
|
@ -270,9 +272,11 @@ async def asgi_send_file(
|
|||
if first:
|
||||
await asgi_start(
|
||||
send,
|
||||
200,
|
||||
headers,
|
||||
content_type or guess_type(str(filepath))[0] or "text/plain",
|
||||
status=200,
|
||||
headers=headers,
|
||||
content_type=content_type
|
||||
or guess_type(str(filepath))[0]
|
||||
or "text/plain",
|
||||
)
|
||||
first = False
|
||||
more_body = True
|
||||
|
@ -284,7 +288,7 @@ async def asgi_send_file(
|
|||
)
|
||||
|
||||
|
||||
def asgi_static(root_path, chunk_size=4096, headers=None, content_type=None):
|
||||
def asgi_static(root_path, *, chunk_size=4096, headers=None, content_type=None):
|
||||
root_path = Path(root_path)
|
||||
|
||||
async def inner_static(request, send):
|
||||
|
@ -292,28 +296,32 @@ def asgi_static(root_path, chunk_size=4096, headers=None, content_type=None):
|
|||
try:
|
||||
full_path = (root_path / path).resolve().absolute()
|
||||
except FileNotFoundError:
|
||||
await asgi_send_html(send, "404: Directory not found", 404)
|
||||
await asgi_send_html(send, "404: Directory not found", status=404)
|
||||
return
|
||||
if full_path.is_dir():
|
||||
await asgi_send_html(send, "403: Directory listing is not allowed", 403)
|
||||
await asgi_send_html(
|
||||
send, "403: Directory listing is not allowed", status=403
|
||||
)
|
||||
return
|
||||
# Ensure full_path is within root_path to avoid weird "../" tricks
|
||||
try:
|
||||
full_path.relative_to(root_path.resolve())
|
||||
except ValueError:
|
||||
await asgi_send_html(send, "404: Path not inside root path", 404)
|
||||
await asgi_send_html(send, "404: Path not inside root path", status=404)
|
||||
return
|
||||
try:
|
||||
await asgi_send_file(send, full_path, chunk_size=chunk_size)
|
||||
except FileNotFoundError:
|
||||
await asgi_send_html(send, "404: File not found", 404)
|
||||
await asgi_send_html(send, "404: File not found", status=404)
|
||||
return
|
||||
|
||||
return inner_static
|
||||
|
||||
|
||||
class Response:
|
||||
def __init__(self, body=None, status=200, headers=None, content_type="text/plain"):
|
||||
def __init__(
|
||||
self, body=None, *, status=200, headers=None, content_type="text/plain"
|
||||
):
|
||||
self.body = body
|
||||
self.status = status
|
||||
self.headers = headers or {}
|
||||
|
@ -346,6 +354,7 @@ class Response:
|
|||
self,
|
||||
key,
|
||||
value="",
|
||||
*,
|
||||
max_age=None,
|
||||
expires=None,
|
||||
path="/",
|
||||
|
@ -374,7 +383,7 @@ class Response:
|
|||
self._set_cookie_headers.append(cookie.output(header="").strip())
|
||||
|
||||
@classmethod
|
||||
def html(cls, body, status=200, headers=None):
|
||||
def html(cls, body, *, status=200, headers=None):
|
||||
return cls(
|
||||
body,
|
||||
status=status,
|
||||
|
@ -383,7 +392,7 @@ class Response:
|
|||
)
|
||||
|
||||
@classmethod
|
||||
def text(cls, body, status=200, headers=None):
|
||||
def text(cls, body, *, status=200, headers=None):
|
||||
return cls(
|
||||
str(body),
|
||||
status=status,
|
||||
|
@ -392,7 +401,7 @@ class Response:
|
|||
)
|
||||
|
||||
@classmethod
|
||||
def json(cls, body, status=200, headers=None, default=None):
|
||||
def json(cls, body, *, status=200, headers=None, default=None):
|
||||
return cls(
|
||||
json.dumps(body, default=default),
|
||||
status=status,
|
||||
|
@ -401,7 +410,7 @@ class Response:
|
|||
)
|
||||
|
||||
@classmethod
|
||||
def redirect(cls, path, status=302, headers=None):
|
||||
def redirect(cls, path, *, status=302, headers=None):
|
||||
headers = headers or {}
|
||||
headers["Location"] = path
|
||||
return cls("", status=status, headers=headers)
|
||||
|
@ -412,6 +421,7 @@ class AsgiFileDownload:
|
|||
self,
|
||||
filepath,
|
||||
filename=None,
|
||||
*,
|
||||
content_type="application/octet-stream",
|
||||
headers=None,
|
||||
):
|
||||
|
|
Ładowanie…
Reference in New Issue