Skip to content

Commit

Permalink
Keyword-only arguments for a bunch of internal methods, refs #1822
Browse files Browse the repository at this point in the history
  • Loading branch information
simonw committed Sep 27, 2022
1 parent 5f9f567 commit 49a11a6
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 26 deletions.
12 changes: 7 additions & 5 deletions datasette/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,7 @@ class Datasette:
def __init__(
self,
files=None,
*,
immutables=None,
cache_headers=True,
cors=False,
Expand Down Expand Up @@ -410,7 +411,7 @@ def sign(self, value, namespace="default"):
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:
Expand All @@ -421,7 +422,7 @@ def get_database(self, name=None, route=None):
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
Expand Down Expand Up @@ -466,7 +467,7 @@ def _metadata_recursive_update(self, orig, updated):
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.
Expand Down Expand Up @@ -518,7 +519,7 @@ def metadata(self, key=None, database=None, table=None, fallback=True):
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
Expand Down Expand Up @@ -714,6 +715,7 @@ async def execute(
db_name,
sql,
params=None,
*,
truncate=False,
custom_time_limit=None,
page_size=None,
Expand Down Expand Up @@ -943,7 +945,7 @@ def _register_renderers(self):
)

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()")
Expand Down
52 changes: 31 additions & 21 deletions datasette/utils/asgi.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,9 @@ async def post_vars(self):
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 = {
Expand Down Expand Up @@ -204,7 +206,7 @@ async def write(self, chunk):
)


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,
Expand All @@ -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,
Expand All @@ -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,
"",
Expand All @@ -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"}
Expand All @@ -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:
Expand All @@ -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
Expand All @@ -284,36 +288,40 @@ 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):
path = request.scope["url_route"]["kwargs"]["path"]
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 {}
Expand Down Expand Up @@ -346,6 +354,7 @@ def set_cookie(
self,
key,
value="",
*,
max_age=None,
expires=None,
path="/",
Expand Down Expand Up @@ -374,7 +383,7 @@ def set_cookie(
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,
Expand All @@ -383,7 +392,7 @@ def html(cls, body, status=200, headers=None):
)

@classmethod
def text(cls, body, status=200, headers=None):
def text(cls, body, *, status=200, headers=None):
return cls(
str(body),
status=status,
Expand All @@ -392,7 +401,7 @@ def text(cls, body, status=200, headers=None):
)

@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,
Expand All @@ -401,7 +410,7 @@ def json(cls, body, status=200, headers=None, default=None):
)

@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)
Expand All @@ -412,6 +421,7 @@ def __init__(
self,
filepath,
filename=None,
*,
content_type="application/octet-stream",
headers=None,
):
Expand Down

0 comments on commit 49a11a6

Please sign in to comment.