datasette.urls methods will not apply base_url prefix twice, refs #1026

This commit is contained in:
Simon Willison 2020-10-31 12:11:40 -07:00
commit 7a67bc7a56
4 changed files with 70 additions and 17 deletions

View file

@ -1,4 +1,4 @@
from .utils import path_with_format, HASH_LENGTH
from .utils import path_with_format, HASH_LENGTH, PrefixedUrlString
import urllib
@ -7,12 +7,13 @@ class Urls:
self.ds = ds
def path(self, path, format=None):
if path.startswith("/"):
path = path[1:]
path = self.ds.config("base_url") + path
if not isinstance(path, PrefixedUrlString):
if path.startswith("/"):
path = path[1:]
path = self.ds.config("base_url") + path
if format is not None:
path = path_with_format(path=path, format=format)
return path
return PrefixedUrlString(path)
def instance(self, format=None):
return self.path("", format=format)
@ -40,19 +41,19 @@ class Urls:
path = "{}/{}".format(self.database(database), urllib.parse.quote_plus(table))
if format is not None:
path = path_with_format(path=path, format=format)
return path
return PrefixedUrlString(path)
def query(self, database, query, format=None):
path = "{}/{}".format(self.database(database), urllib.parse.quote_plus(query))
if format is not None:
path = path_with_format(path=path, format=format)
return path
return PrefixedUrlString(path)
def row(self, database, table, row_path, format=None):
path = "{}/{}".format(self.table(database, table), row_path)
if format is not None:
path = path_with_format(path=path, format=format)
return path
return PrefixedUrlString(path)
def row_blob(self, database, table, row_path, column):
return self.table(database, table) + "/{}.blob?_blob_column={}".format(

View file

@ -1010,3 +1010,26 @@ async def initial_path_for_datasette(datasette):
else:
path = datasette.urls.instance()
return path
class PrefixedUrlString(str):
def __add__(self, other):
return type(self)(super().__add__(other))
def __getattribute__(self, name):
if name in dir(str):
def method(self, *args, **kwargs):
value = getattr(super(), name)(*args, **kwargs)
if isinstance(value, str):
return type(self)(value)
elif isinstance(value, list):
return [type(self)(i) for i in value]
elif isinstance(value, tuple):
return tuple(type(self)(i) for i in value)
else:
return value
return method.__get__(self)
else:
return super().__getattribute__(name)