Skip to content

Commit

Permalink
Renamed datasette.config() to .setting(), closes #1107
Browse files Browse the repository at this point in the history
  • Loading branch information
simonw committed Nov 24, 2020
1 parent 5a77f7a commit f2e2bfc
Show file tree
Hide file tree
Showing 10 changed files with 86 additions and 60 deletions.
32 changes: 16 additions & 16 deletions datasette/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -264,15 +264,15 @@ def __init__(
raise StartupError("config.json should be renamed to settings.json")
if config_dir and (config_dir / "settings.json").exists() and not config:
config = json.load((config_dir / "settings.json").open())
self._config = dict(DEFAULT_SETTINGS, **(config or {}))
self._settings = dict(DEFAULT_SETTINGS, **(config or {}))
self.renderers = {} # File extension -> (renderer, can_render) functions
self.version_note = version_note
self.executor = futures.ThreadPoolExecutor(
max_workers=self.config("num_sql_threads")
max_workers=self.setting("num_sql_threads")
)
self.max_returned_rows = self.config("max_returned_rows")
self.sql_time_limit_ms = self.config("sql_time_limit_ms")
self.page_size = self.config("default_page_size")
self.max_returned_rows = self.setting("max_returned_rows")
self.sql_time_limit_ms = self.setting("sql_time_limit_ms")
self.page_size = self.setting("default_page_size")
# Execute plugins in constructor, to ensure they are available
# when the rest of `datasette inspect` executes
if self.plugins_dir:
Expand Down Expand Up @@ -347,12 +347,12 @@ def add_database(self, name, db):
def remove_database(self, name):
self.databases.pop(name)

def config(self, key):
return self._config.get(key, None)
def setting(self, key):
return self._settings.get(key, None)

def config_dict(self):
# Returns a fully resolved config dictionary, useful for templates
return {option.name: self.config(option.name) for option in SETTINGS}
return {option.name: self.setting(option.name) for option in SETTINGS}

def metadata(self, key=None, database=None, table=None, fallback=True):
"""
Expand Down Expand Up @@ -454,8 +454,8 @@ def _prepare_connection(self, conn, database):
conn.enable_load_extension(True)
for extension in self.sqlite_extensions:
conn.execute(f"SELECT load_extension('{extension}')")
if self.config("cache_size_kb"):
conn.execute(f"PRAGMA cache_size=-{self.config('cache_size_kb')}")
if self.setting("cache_size_kb"):
conn.execute(f"PRAGMA cache_size=-{self.setting('cache_size_kb')}")
# pylint: disable=no-member
pm.hook.prepare_connection(conn=conn, database=database, datasette=self)

Expand Down Expand Up @@ -567,7 +567,7 @@ async def expand_foreign_keys(self, database, table, column, values):

def absolute_url(self, request, path):
url = urllib.parse.urljoin(request.url, path)
if url.startswith("http://") and self.config("force_https_urls"):
if url.startswith("http://") and self.setting("force_https_urls"):
url = "https://" + url[len("http://") :]
return url

Expand Down Expand Up @@ -781,12 +781,12 @@ async def menu_links():
"extra_js_urls": await self._asset_urls(
"extra_js_urls", template, context, request, view_name
),
"base_url": self.config("base_url"),
"base_url": self.setting("base_url"),
"csrftoken": request.scope["csrftoken"] if request else lambda: "",
},
**extra_template_vars,
}
if request and request.args.get("_context") and self.config("template_debug"):
if request and request.args.get("_context") and self.setting("template_debug"):
return "<pre>{}</pre>".format(
jinja2.escape(json.dumps(template_context, default=repr, indent=4))
)
Expand Down Expand Up @@ -882,7 +882,7 @@ def add_route(view, regex):
r"/-/plugins(?P<as_format>(\.json)?)$",
)
add_route(
JsonDataView.as_view(self, "settings.json", lambda: self._config),
JsonDataView.as_view(self, "settings.json", lambda: self._settings),
r"/-/settings(?P<as_format>(\.json)?)$",
)
add_route(
Expand Down Expand Up @@ -1001,7 +1001,7 @@ async def __call__(self, scope, receive, send):

async def route_path(self, scope, receive, send, path):
# Strip off base_url if present before routing
base_url = self.ds.config("base_url")
base_url = self.ds.setting("base_url")
if base_url != "/" and path.startswith(base_url):
path = "/" + path[len(base_url) :]
request = Request(scope, receive)
Expand All @@ -1016,7 +1016,7 @@ async def route_path(self, scope, receive, send, path):
scope_modifications = {}
# Apply force_https_urls, if set
if (
self.ds.config("force_https_urls")
self.ds.setting("force_https_urls")
and scope["type"] == "http"
and scope.get("scheme") != "https"
):
Expand Down
22 changes: 11 additions & 11 deletions datasette/facets.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ class ColumnFacet(Facet):
async def suggest(self):
row_count = await self.get_row_count()
columns = await self.get_columns(self.sql, self.params)
facet_size = self.ds.config("default_facet_size")
facet_size = self.ds.setting("default_facet_size")
suggested_facets = []
already_enabled = [c["config"]["simple"] for c in self.get_configs()]
for column in columns:
Expand All @@ -158,7 +158,7 @@ async def suggest(self):
suggested_facet_sql,
self.params,
truncate=False,
custom_time_limit=self.ds.config("facet_suggest_time_limit_ms"),
custom_time_limit=self.ds.setting("facet_suggest_time_limit_ms"),
)
num_distinct_values = len(distinct_values)
if (
Expand Down Expand Up @@ -188,7 +188,7 @@ async def facet_results(self):

qs_pairs = self.get_querystring_pairs()

facet_size = self.ds.config("default_facet_size")
facet_size = self.ds.setting("default_facet_size")
for source_and_config in self.get_configs():
config = source_and_config["config"]
source = source_and_config["source"]
Expand All @@ -208,7 +208,7 @@ async def facet_results(self):
facet_sql,
self.params,
truncate=False,
custom_time_limit=self.ds.config("facet_time_limit_ms"),
custom_time_limit=self.ds.setting("facet_time_limit_ms"),
)
facet_results_values = []
facet_results[column] = {
Expand Down Expand Up @@ -290,7 +290,7 @@ async def suggest(self):
suggested_facet_sql,
self.params,
truncate=False,
custom_time_limit=self.ds.config("facet_suggest_time_limit_ms"),
custom_time_limit=self.ds.setting("facet_suggest_time_limit_ms"),
log_sql_errors=False,
)
types = tuple(r[0] for r in results.rows)
Expand All @@ -305,7 +305,7 @@ async def suggest(self):
),
self.params,
truncate=False,
custom_time_limit=self.ds.config(
custom_time_limit=self.ds.setting(
"facet_suggest_time_limit_ms"
),
log_sql_errors=False,
Expand Down Expand Up @@ -335,7 +335,7 @@ async def facet_results(self):
facet_results = {}
facets_timed_out = []

facet_size = self.ds.config("default_facet_size")
facet_size = self.ds.setting("default_facet_size")
for source_and_config in self.get_configs():
config = source_and_config["config"]
source = source_and_config["source"]
Expand All @@ -354,7 +354,7 @@ async def facet_results(self):
facet_sql,
self.params,
truncate=False,
custom_time_limit=self.ds.config("facet_time_limit_ms"),
custom_time_limit=self.ds.setting("facet_time_limit_ms"),
)
facet_results_values = []
facet_results[column] = {
Expand Down Expand Up @@ -421,7 +421,7 @@ async def suggest(self):
suggested_facet_sql,
self.params,
truncate=False,
custom_time_limit=self.ds.config("facet_suggest_time_limit_ms"),
custom_time_limit=self.ds.setting("facet_suggest_time_limit_ms"),
log_sql_errors=False,
)
values = tuple(r[0] for r in results.rows)
Expand All @@ -446,7 +446,7 @@ async def facet_results(self):
facet_results = {}
facets_timed_out = []
args = dict(self.get_querystring_pairs())
facet_size = self.ds.config("default_facet_size")
facet_size = self.ds.setting("default_facet_size")
for source_and_config in self.get_configs():
config = source_and_config["config"]
source = source_and_config["source"]
Expand All @@ -467,7 +467,7 @@ async def facet_results(self):
facet_sql,
self.params,
truncate=False,
custom_time_limit=self.ds.config("facet_time_limit_ms"),
custom_time_limit=self.ds.setting("facet_time_limit_ms"),
)
facet_results_values = []
facet_results[column] = {
Expand Down
4 changes: 2 additions & 2 deletions datasette/url_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ def path(self, path, format=None):
if not isinstance(path, PrefixedUrlString):
if path.startswith("/"):
path = path[1:]
path = self.ds.config("base_url") + path
path = self.ds.setting("base_url") + path
if format is not None:
path = path_with_format(path=path, format=format)
return PrefixedUrlString(path)
Expand All @@ -29,7 +29,7 @@ def logout(self):

def database(self, database, format=None):
db = self.ds.databases[database]
if self.ds.config("hash_urls") and db.hash:
if self.ds.setting("hash_urls") and db.hash:
path = self.path(f"{database}-{db.hash[:HASH_LENGTH]}", format=format)
else:
path = self.path(database, format=format)
Expand Down
10 changes: 5 additions & 5 deletions datasette/views/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ async def async_table_exists(t):
should_redirect += kwargs["as_db"]

if (
(self.ds.config("hash_urls") or "_hash" in request.args)
(self.ds.setting("hash_urls") or "_hash" in request.args)
and
# Redirect only if database is immutable
not self.ds.databases[name].is_mutable
Expand Down Expand Up @@ -260,7 +260,7 @@ async def as_csv(self, request, database, hash, **kwargs):
stream = request.args.get("_stream")
if stream:
# Some quick sanity checks
if not self.ds.config("allow_csv_stream"):
if not self.ds.setting("allow_csv_stream"):
raise BadRequest("CSV streaming is disabled")
if request.args.get("_next"):
raise BadRequest("_next not allowed for CSV streaming")
Expand Down Expand Up @@ -296,7 +296,7 @@ async def as_csv(self, request, database, hash, **kwargs):

async def stream_fn(r):
nonlocal data
writer = csv.writer(LimitedWriter(r, self.ds.config("max_csv_mb")))
writer = csv.writer(LimitedWriter(r, self.ds.setting("max_csv_mb")))
first = True
next = None
while first or (next and stream):
Expand Down Expand Up @@ -566,9 +566,9 @@ async def view_get(self, request, database, hash, correct_hash_provided, **kwarg
ttl = request.args.get("_ttl", None)
if ttl is None or not ttl.isdigit():
if correct_hash_provided:
ttl = self.ds.config("default_cache_ttl_hashed")
ttl = self.ds.setting("default_cache_ttl_hashed")
else:
ttl = self.ds.config("default_cache_ttl")
ttl = self.ds.setting("default_cache_ttl")

return self.set_response_headers(r, ttl)

Expand Down
4 changes: 2 additions & 2 deletions datasette/views/database.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ async def database_actions():
"show_hidden": request.args.get("_show_hidden"),
"editable": True,
"metadata": metadata,
"allow_download": self.ds.config("allow_download")
"allow_download": self.ds.setting("allow_download")
and not db.is_mutable
and database != ":memory:",
},
Expand All @@ -161,7 +161,7 @@ async def view_get(self, request, database, hash, correct_hash_present, **kwargs
db = self.ds.databases[database]
if db.is_memory:
raise DatasetteError("Cannot download :memory: database", status=404)
if not self.ds.config("allow_download") or db.is_mutable:
if not self.ds.setting("allow_download") or db.is_mutable:
raise Forbidden("Database download is forbidden")
if not db.path:
raise DatasetteError("Cannot download database", status=404)
Expand Down
10 changes: 5 additions & 5 deletions datasette/views/table.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ async def display_columns_and_rows(
}

cell_rows = []
base_url = self.ds.config("base_url")
base_url = self.ds.setting("base_url")
for row in rows:
cells = []
# Unless we are a view, the first column is a link - either to the rowid
Expand Down Expand Up @@ -654,7 +654,7 @@ async def data(
pass

# facets support
if not self.ds.config("allow_facet") and any(
if not self.ds.setting("allow_facet") and any(
arg.startswith("_facet") for arg in request.args
):
raise BadRequest("_facet= is not allowed")
Expand Down Expand Up @@ -772,8 +772,8 @@ async def data(
suggested_facets = []

if (
self.ds.config("suggest_facets")
and self.ds.config("allow_facet")
self.ds.setting("suggest_facets")
and self.ds.setting("allow_facet")
and not _next
):
for facet in facet_instances:
Expand Down Expand Up @@ -801,7 +801,7 @@ async def extra_template():
results.description,
rows,
link_column=not is_view,
truncate_cells=self.ds.config("truncate_cells_html"),
truncate_cells=self.ds.setting("truncate_cells_html"),
)
metadata = (
(self.ds.metadata("databases") or {})
Expand Down
16 changes: 15 additions & 1 deletion docs/internals.rst
Original file line number Diff line number Diff line change
Expand Up @@ -350,7 +350,21 @@ Returns the absolute URL for the given path, including the protocol and host. Fo
absolute_url = datasette.absolute_url(request, "/dbname/table.json")
# Would return "http://localhost:8001/dbname/table.json"
The current request object is used to determine the hostname and protocol that should be used for the returned URL. The :ref:`settings_force_https_urls` configuration setting is taken into account.
The current request object is used to determine the hostname and protocol that should be used for the returned URL. The :ref:`setting_force_https_urls` configuration setting is taken into account.

.setting(key)
-------------

``key`` - string
The name of the setting, e.g. ``base_url``.

Returns the configured value for the specified :ref:`setting <settings>`. This can be a string, boolean or integer depending on the requested setting.

For example:

.. code-block:: python
downloads_are_allowed = datasette.setting("allow_download")
.. _internals_datasette_client:

Expand Down
12 changes: 12 additions & 0 deletions tests/test_internals_datasette.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,15 @@ def test_sign_unsign(datasette, value, namespace):
assert value == datasette.unsign(signed, *extra_args)
with pytest.raises(BadSignature):
datasette.unsign(signed[:-1] + ("!" if signed[-1] != "!" else ":"))


@pytest.mark.parametrize(
"setting,expected",
(
("base_url", "/"),
("max_csv_mb", 100),
("allow_csv_stream", True),
),
)
def test_datasette_setting(datasette, setting, expected):
assert datasette.setting(setting) == expected
12 changes: 6 additions & 6 deletions tests/test_internals_datasette_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,10 @@ async def test_client_methods(datasette, method, path, expected_status):
@pytest.mark.asyncio
@pytest.mark.parametrize("prefix", [None, "/prefix/"])
async def test_client_post(datasette, prefix):
original_base_url = datasette._config["base_url"]
original_base_url = datasette._settings["base_url"]
try:
if prefix is not None:
datasette._config["base_url"] = prefix
datasette._settings["base_url"] = prefix
response = await datasette.client.post(
"/-/messages",
data={
Expand All @@ -48,20 +48,20 @@ async def test_client_post(datasette, prefix):
assert response.status_code == 302
assert "ds_messages" in response.cookies
finally:
datasette._config["base_url"] = original_base_url
datasette._settings["base_url"] = original_base_url


@pytest.mark.asyncio
@pytest.mark.parametrize(
"prefix,expected_path", [(None, "/asgi-scope"), ("/prefix/", "/prefix/asgi-scope")]
)
async def test_client_path(datasette, prefix, expected_path):
original_base_url = datasette._config["base_url"]
original_base_url = datasette._settings["base_url"]
try:
if prefix is not None:
datasette._config["base_url"] = prefix
datasette._settings["base_url"] = prefix
response = await datasette.client.get("/asgi-scope")
path = response.json()["path"]
assert path == expected_path
finally:
datasette._config["base_url"] = original_base_url
datasette._settings["base_url"] = original_base_url
Loading

0 comments on commit f2e2bfc

Please sign in to comment.