{"html_url": "https://github.com/simonw/datasette/issues/1202#issuecomment-766464136", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1202", "id": 766464136, "node_id": "MDEyOklzc3VlQ29tbWVudDc2NjQ2NDEzNg==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2021-01-25T00:01:02Z", "updated_at": "2021-01-25T00:01:02Z", "author_association": "OWNER", "body": "I'm going to use the existing `.. warning::` pattern for this.", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 792931244, "label": "Documentation convention for marking unstable APIs."}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/1154#issuecomment-766465719", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1154", "id": 766465719, "node_id": "MDEyOklzc3VlQ29tbWVudDc2NjQ2NTcxOQ==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2021-01-25T00:09:22Z", "updated_at": "2021-01-25T00:09:22Z", "author_association": "OWNER", "body": "https://docs.datasette.io/en/latest/internals.html#the-internal-database\r\n\r\n\"Internals_for_plugins_\u2014_Datasette_documentation\"\r\n", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 771208009, "label": "Documentation for new _internal database and tables"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/1191#issuecomment-766466030", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1191", "id": 766466030, "node_id": "MDEyOklzc3VlQ29tbWVudDc2NjQ2NjAzMA==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2021-01-25T00:11:04Z", "updated_at": "2021-01-25T00:11:04Z", "author_association": "OWNER", "body": "I can combine this with #987 - each of these areas of the page can be wrapped in a `
` with a class that matches the name of the plugin hook, that way JavaScript plugins can append their content in the same place as Python plugins.", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 787098345, "label": "Ability for plugins to collaborate when adding extra HTML to blocks in default templates"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/1179#issuecomment-766484257", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1179", "id": 766484257, "node_id": "MDEyOklzc3VlQ29tbWVudDc2NjQ4NDI1Nw==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2021-01-25T01:30:57Z", "updated_at": "2021-01-25T01:30:57Z", "author_association": "OWNER", "body": "The challenge here is figuring out what the original path, without the `.format`, actually was - while taking into account that Datasette has a special case for tables that themselves end in a `.something`.\r\n\r\nThe `path_with_format()` function nearly does what we need here:\r\n\r\nhttps://github.com/simonw/datasette/blob/b6a7b58fa01af0cd5a5e94bd17d686d283a46819/datasette/utils/__init__.py#L710-L729\r\n\r\nIt can be called with `replace_format=\"csv\"` to REMOVE the `.csv` format and replace it with something else.\r\n\r\nProblem is, we want to use it to get rid of the format entirely.\r\n\r\nWe could update `path_with_format()` to accept `format=''` to mean \"remove the format entirely\", but it's a bit messy. It may be better to reconsider the design of `path_with_format()` and related utility functions entirely.", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 780278550, "label": "Make original path available to render hooks"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/1179#issuecomment-766484435", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1179", "id": 766484435, "node_id": "MDEyOklzc3VlQ29tbWVudDc2NjQ4NDQzNQ==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2021-01-25T01:31:36Z", "updated_at": "2021-01-25T01:31:36Z", "author_association": "OWNER", "body": "Relevant existing tests: https://github.com/simonw/datasette/blob/461670a0b87efa953141b449a9a261919864ceb3/tests/test_utils.py#L365-L398", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 780278550, "label": "Make original path available to render hooks"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/983#issuecomment-766484915", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/983", "id": 766484915, "node_id": "MDEyOklzc3VlQ29tbWVudDc2NjQ4NDkxNQ==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2021-01-25T01:33:29Z", "updated_at": "2021-01-25T01:33:29Z", "author_association": "OWNER", "body": "I'm going to ship a version of this in Datasette 0.54 with a warning that the interface should be considered unstable (see #1202) so that we can start trying this out.", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 712260429, "label": "JavaScript plugin hooks mechanism similar to pluggy"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/1167#issuecomment-766487520", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1167", "id": 766487520, "node_id": "MDEyOklzc3VlQ29tbWVudDc2NjQ4NzUyMA==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2021-01-25T01:44:43Z", "updated_at": "2021-01-25T01:44:43Z", "author_association": "OWNER", "body": "Thanks @benpickles, I just merged that in. I'll use it in the documentation.\r\n\r\n # To check code is conformant\r\n npm run prettier -- --check\r\n # To fix it if it isn't\r\n npm run fix\r\n", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 777145954, "label": "Add Prettier to contributing documentation"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/1167#issuecomment-766491566", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1167", "id": 766491566, "node_id": "MDEyOklzc3VlQ29tbWVudDc2NjQ5MTU2Ng==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2021-01-25T02:01:19Z", "updated_at": "2021-01-25T02:01:19Z", "author_association": "OWNER", "body": "New documentation section here (I documented Black as well): https://docs.datasette.io/en/latest/contributing.html#code-formatting", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 777145954, "label": "Add Prettier to contributing documentation"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/1194#issuecomment-766491911", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1194", "id": 766491911, "node_id": "MDEyOklzc3VlQ29tbWVudDc2NjQ5MTkxMQ==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2021-01-25T02:02:15Z", "updated_at": "2021-01-25T02:02:15Z", "author_association": "OWNER", "body": "I'm going to copy across anything starting with an underscore.", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 788447787, "label": "?_size= argument is not persisted by hidden form fields in the table filters"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/1191#issuecomment-766523866", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1191", "id": 766523866, "node_id": "MDEyOklzc3VlQ29tbWVudDc2NjUyMzg2Ng==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2021-01-25T03:58:34Z", "updated_at": "2021-01-25T03:58:34Z", "author_association": "OWNER", "body": "I've got a good prototype working now, but I'm dropping this from the Datasette 0.54 milestone because it requires a bunch of additional work to make sure it is really well tested and documented.", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 787098345, "label": "Ability for plugins to collaborate when adding extra HTML to blocks in default templates"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/1191#issuecomment-766524016", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1191", "id": 766524016, "node_id": "MDEyOklzc3VlQ29tbWVudDc2NjUyNDAxNg==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2021-01-25T03:59:17Z", "updated_at": "2021-01-25T03:59:17Z", "author_association": "OWNER", "body": "More work can happen in the PR: #1204", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 787098345, "label": "Ability for plugins to collaborate when adding extra HTML to blocks in default templates"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/987#issuecomment-766524141", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/987", "id": 766524141, "node_id": "MDEyOklzc3VlQ29tbWVudDc2NjUyNDE0MQ==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2021-01-25T03:59:55Z", "updated_at": "2021-01-25T03:59:55Z", "author_association": "OWNER", "body": "This is joined with #1191 now, which I've bumped from 0.54.", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 712984738, "label": "Documented HTML hooks for JavaScript plugin authors"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/pull/1204#issuecomment-766525337", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1204", "id": 766525337, "node_id": "MDEyOklzc3VlQ29tbWVudDc2NjUyNTMzNw==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2021-01-25T04:04:28Z", "updated_at": "2021-01-25T04:04:28Z", "author_association": "OWNER", "body": "Writing the tests will be a bit tricky since we need to confirm that the `include_table_top(datasette, database, actor, table)` arguments were all passed correctly but the only thing we get back from the plugin is a list of templates. Maybe encode those values into the template names somehow?", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 793002853, "label": "WIP: Plugin includes"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/1195#issuecomment-766534634", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1195", "id": 766534634, "node_id": "MDEyOklzc3VlQ29tbWVudDc2NjUzNDYzNA==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2021-01-25T04:38:30Z", "updated_at": "2021-01-25T04:38:30Z", "author_association": "OWNER", "body": "This has proved surprisingly difficult to implement, due to the weird way the QueryView is actually called. The class itself isn't used like other view classes - instead, the `.data()` methods of both `DatabaseView` and `TableView` dispatch out to `QueryView.data()` when they need to:\r\n\r\nhttps://github.com/simonw/datasette/blob/07e163561592c743e4117f72102fcd350a600909/datasette/views/table.py#L259-L270\r\n\r\nhttps://github.com/simonw/datasette/blob/07e163561592c743e4117f72102fcd350a600909/datasette/views/table.py#L290-L294\r\n\r\nhttps://github.com/simonw/datasette/blob/07e163561592c743e4117f72102fcd350a600909/datasette/views/database.py#L39-L44\r\n\r\nIt turns out this is a bad pattern because it makes changes like this one WAY harder than they should be.\r\n\r\nI think I should clean this up as part of #878.", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 789336592, "label": "view_name = \"query\" for the query page"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/1195#issuecomment-766534748", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1195", "id": 766534748, "node_id": "MDEyOklzc3VlQ29tbWVudDc2NjUzNDc0OA==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2021-01-25T04:38:56Z", "updated_at": "2021-01-25T04:38:56Z", "author_association": "OWNER", "body": "Here's a diff showing how far I got before I abandoned this particular effort:\r\n\r\n```diff\r\ndiff --git a/datasette/views/base.py b/datasette/views/base.py\r\nindex a21b929..04e4aa9 100644\r\n--- a/datasette/views/base.py\r\n+++ b/datasette/views/base.py\r\n@@ -120,7 +120,7 @@ class BaseView:\r\n handler = getattr(self, request.method.lower(), None)\r\n return await handler(request, *args, **kwargs)\r\n \r\n- async def render(self, templates, request, context=None):\r\n+ async def render(self, templates, request, context=None, view_name=None):\r\n context = context or {}\r\n template = self.ds.jinja_env.select_template(templates)\r\n template_context = {\r\n@@ -135,7 +135,7 @@ class BaseView:\r\n }\r\n return Response.html(\r\n await self.ds.render_template(\r\n- template, template_context, request=request, view_name=self.name\r\n+ template, template_context, request=request, view_name=view_name\r\n )\r\n )\r\n \r\n@@ -155,7 +155,7 @@ class BaseView:\r\n \r\n \r\n class DataView(BaseView):\r\n- name = \"\"\r\n+ view_name = \"no-view-name\"\r\n re_named_parameter = re.compile(\":([a-zA-Z0-9_]+)\")\r\n \r\n async def options(self, request, *args, **kwargs):\r\n@@ -414,6 +414,10 @@ class DataView(BaseView):\r\n args[\"table\"] = urllib.parse.unquote_plus(args[\"table\"])\r\n return _format, args\r\n \r\n+ async def get_view_name(self, request, database, hash, **kwargs):\r\n+ # Defaults to self.view_name, but can be over-ridden by subclasses\r\n+ return self.view_name\r\n+\r\n async def view_get(self, request, database, hash, correct_hash_provided, **kwargs):\r\n _format, kwargs = await self.get_format(request, database, kwargs)\r\n \r\n@@ -424,6 +428,8 @@ class DataView(BaseView):\r\n # HTML views default to expanding all foreign key labels\r\n kwargs[\"default_labels\"] = True\r\n \r\n+ view_name = await self.get_view_name(request, database, hash, **kwargs)\r\n+\r\n extra_template_data = {}\r\n start = time.perf_counter()\r\n status_code = 200\r\n@@ -489,7 +495,7 @@ class DataView(BaseView):\r\n database=database,\r\n table=data.get(\"table\"),\r\n request=request,\r\n- view_name=self.name,\r\n+ view_name=view_name,\r\n # These will be deprecated in Datasette 1.0:\r\n args=request.args,\r\n data=data,\r\n@@ -533,7 +539,7 @@ class DataView(BaseView):\r\n database=database,\r\n table=data.get(\"table\"),\r\n request=request,\r\n- view_name=self.name,\r\n+ view_name=view_name,\r\n )\r\n it_can_render = await await_me_maybe(it_can_render)\r\n if it_can_render:\r\n@@ -565,7 +571,7 @@ class DataView(BaseView):\r\n }\r\n if \"metadata\" not in context:\r\n context[\"metadata\"] = self.ds.metadata\r\n- r = await self.render(templates, request=request, context=context)\r\n+ r = await self.render(templates, request=request, context=context, view_name=view_name)\r\n r.status = status_code\r\n \r\n ttl = request.args.get(\"_ttl\", None)\r\ndiff --git a/datasette/views/database.py b/datasette/views/database.py\r\nindex f6fd579..e425213 100644\r\n--- a/datasette/views/database.py\r\n+++ b/datasette/views/database.py\r\n@@ -23,7 +23,11 @@ from .base import DatasetteError, DataView\r\n \r\n \r\n class DatabaseView(DataView):\r\n- name = \"database\"\r\n+ async def get_view_name(self, request, db_name, table_and_format):\r\n+ if request.args.get(\"sql\"):\r\n+ return \"query\"\r\n+ else:\r\n+ return \"database\"\r\n \r\n async def data(self, request, database, hash, default_labels=False, _size=None):\r\n await self.check_permissions(\r\n@@ -145,7 +149,7 @@ class DatabaseView(DataView):\r\n \r\n \r\n class DatabaseDownload(DataView):\r\n- name = \"database_download\"\r\n+ view_name = \"database_download\"\r\n \r\n async def view_get(self, request, database, hash, correct_hash_present, **kwargs):\r\n await self.check_permissions(\r\ndiff --git a/datasette/views/index.py b/datasette/views/index.py\r\nindex b6b8cbe..d750e3d 100644\r\n--- a/datasette/views/index.py\r\n+++ b/datasette/views/index.py\r\n@@ -16,7 +16,7 @@ COUNT_DB_SIZE_LIMIT = 100 * 1024 * 1024\r\n \r\n \r\n class IndexView(BaseView):\r\n- name = \"index\"\r\n+ view_name = \"index\"\r\n \r\n async def get(self, request, as_format):\r\n await self.check_permission(request, \"view-instance\")\r\ndiff --git a/datasette/views/special.py b/datasette/views/special.py\r\nindex 9750dd0..dbd1e00 100644\r\n--- a/datasette/views/special.py\r\n+++ b/datasette/views/special.py\r\n@@ -6,7 +6,7 @@ import secrets\r\n \r\n \r\n class JsonDataView(BaseView):\r\n- name = \"json_data\"\r\n+ view_name = \"json_data\"\r\n \r\n def __init__(self, datasette, filename, data_callback, needs_request=False):\r\n self.ds = datasette\r\n@@ -42,7 +42,7 @@ class JsonDataView(BaseView):\r\n \r\n \r\n class PatternPortfolioView(BaseView):\r\n- name = \"patterns\"\r\n+ view_name = \"patterns\"\r\n \r\n async def get(self, request):\r\n await self.check_permission(request, \"view-instance\")\r\n@@ -50,7 +50,7 @@ class PatternPortfolioView(BaseView):\r\n \r\n \r\n class AuthTokenView(BaseView):\r\n- name = \"auth_token\"\r\n+ view_name = \"auth_token\"\r\n \r\n async def get(self, request):\r\n token = request.args.get(\"token\") or \"\"\r\n@@ -68,7 +68,7 @@ class AuthTokenView(BaseView):\r\n \r\n \r\n class LogoutView(BaseView):\r\n- name = \"logout\"\r\n+ view_name = \"logout\"\r\n \r\n async def get(self, request):\r\n if not request.actor:\r\n@@ -87,7 +87,7 @@ class LogoutView(BaseView):\r\n \r\n \r\n class PermissionsDebugView(BaseView):\r\n- name = \"permissions_debug\"\r\n+ view_name = \"permissions_debug\"\r\n \r\n async def get(self, request):\r\n await self.check_permission(request, \"view-instance\")\r\n@@ -102,7 +102,7 @@ class PermissionsDebugView(BaseView):\r\n \r\n \r\n class AllowDebugView(BaseView):\r\n- name = \"allow_debug\"\r\n+ view_name = \"allow_debug\"\r\n \r\n async def get(self, request):\r\n errors = []\r\n@@ -136,7 +136,7 @@ class AllowDebugView(BaseView):\r\n \r\n \r\n class MessagesDebugView(BaseView):\r\n- name = \"messages_debug\"\r\n+ view_name = \"messages_debug\"\r\n \r\n async def get(self, request):\r\n await self.check_permission(request, \"view-instance\")\r\ndiff --git a/datasette/views/table.py b/datasette/views/table.py\r\nindex 0a3504b..45d298a 100644\r\n--- a/datasette/views/table.py\r\n+++ b/datasette/views/table.py\r\n@@ -257,7 +257,16 @@ class RowTableShared(DataView):\r\n \r\n \r\n class TableView(RowTableShared):\r\n- name = \"table\"\r\n+ view_name = \"table\"\r\n+\r\n+ async def get_view_name(self, request, db_name, table_and_format):\r\n+ canned_query = await self.ds.get_canned_query(\r\n+ db_name, table_and_format, request.actor\r\n+ )\r\n+ if canned_query:\r\n+ return \"query\"\r\n+ else:\r\n+ return \"table\"\r\n \r\n async def post(self, request, db_name, table_and_format):\r\n # Handle POST to a canned query\r\n@@ -923,7 +932,7 @@ async def _sql_params_pks(db, table, pk_values):\r\n \r\n \r\n class RowView(RowTableShared):\r\n- name = \"row\"\r\n+ view_name = \"row\"\r\n \r\n async def data(self, request, database, hash, table, pk_path, default_labels=False):\r\n await self.check_permissions(\r\ndiff --git a/tests/test_plugins.py b/tests/test_plugins.py\r\nindex 715c7c1..7ce2b1b 100644\r\n--- a/tests/test_plugins.py\r\n+++ b/tests/test_plugins.py\r\n@@ -252,7 +252,7 @@ def test_plugin_config_file(app_client):\r\n },\r\n ),\r\n (\r\n- \"/fixtures/\",\r\n+ \"/fixtures\",\r\n {\r\n \"template\": \"database.html\",\r\n \"database\": \"fixtures\",\r\n@@ -285,6 +285,38 @@ def test_plugin_config_file(app_client):\r\n ],\r\n },\r\n ),\r\n+ (\r\n+ \"/fixtures?sql=select+1+as+one\",\r\n+ {\r\n+ \"template\": \"query.html\",\r\n+ \"database\": \"fixtures\",\r\n+ \"table\": None,\r\n+ \"config\": {\"depth\": \"database\"},\r\n+ \"view_name\": \"query\",\r\n+ \"request_path\": \"/fixtures\",\r\n+ \"added\": 15,\r\n+ \"columns\": [\r\n+ \"one\",\r\n+ ],\r\n+ },\r\n+ ),\r\n+ (\r\n+ \"/fixtures/neighborhood_search\",\r\n+ {\r\n+ \"template\": \"query.html\",\r\n+ \"database\": \"fixtures\",\r\n+ \"table\": None,\r\n+ \"config\": {\"depth\": \"database\"},\r\n+ \"view_name\": \"query\",\r\n+ \"request_path\": \"/fixtures/neighborhood_search\",\r\n+ \"added\": 15,\r\n+ \"columns\": [\r\n+ \"neighborhood\",\r\n+ \"name\",\r\n+ \"state\",\r\n+ ],\r\n+ },\r\n+ ),\r\n ],\r\n )\r\n def test_hook_extra_body_script(app_client, path, expected_extra_body_script):\r\n```", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 789336592, "label": "view_name = \"query\" for the query page"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/1195#issuecomment-766535046", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1195", "id": 766535046, "node_id": "MDEyOklzc3VlQ29tbWVudDc2NjUzNTA0Ng==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2021-01-25T04:40:08Z", "updated_at": "2021-01-25T04:40:08Z", "author_association": "OWNER", "body": "Also: should the view name really be the same for both of these pages?\r\n\r\n- https://latest.datasette.io/fixtures?sql=select+*+from+facetable\r\n- https://latest.datasette.io/fixtures/neighborhood_search\r\n\r\nWhere one of them is a canned query and the other is an arbitrary query?", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 789336592, "label": "view_name = \"query\" for the query page"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/983#issuecomment-766536076", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/983", "id": 766536076, "node_id": "MDEyOklzc3VlQ29tbWVudDc2NjUzNjA3Ng==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2021-01-25T04:43:53Z", "updated_at": "2021-01-25T04:43:53Z", "author_association": "OWNER", "body": "... actually not going to include this in 0.54, I need to write a couple of plugins myself using it before I even make it available in preview.", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 712260429, "label": "JavaScript plugin hooks mechanism similar to pluggy"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/1201#issuecomment-766543387", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1201", "id": 766543387, "node_id": "MDEyOklzc3VlQ29tbWVudDc2NjU0MzM4Nw==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2021-01-25T05:07:40Z", "updated_at": "2021-01-25T05:13:29Z", "author_association": "OWNER", "body": "Changes: https://github.com/simonw/datasette/compare/0.53...a5ede3cdd455e2bb1a1fb2f4e1b5a9855caf5179", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 792904595, "label": "Release notes for Datasette 0.54"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/1201#issuecomment-766545442", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1201", "id": 766545442, "node_id": "MDEyOklzc3VlQ29tbWVudDc2NjU0NTQ0Mg==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2021-01-25T05:13:59Z", "updated_at": "2021-01-25T05:13:59Z", "author_association": "OWNER", "body": "The big stuff:\r\n\r\n- Database(memory_name=) for shared in-memory databases, closes #1151 \r\n- The `_internal` database - #1150\r\n- script type=module support, closes #1186 , #1187\r\n- Improved design for the `.add_database()` method 8919f99c2f7f245aca7f94bd53d5ac9d04aa42b5 - which means databases with the same stem can now be opened, #509\r\n- Adopted Prettier #1166 \r\n\r\nSmaller:\r\n\r\n- force_https_urls on for publish cloudrun, refs #1178 \r\n- Fixed bug in example nginx config, refs #1091 \r\n- Shrunk ecosystem docs in favour of datasette.io, closes #1182 \r\n- request.full_path property, closes #1184 \r\n- Better PRAGMA error message, closes #1185 \r\n- publish heroku now uses python-3.8.7 \r\n- Plugin testing documentation on using pytest-httpx Closes #1198\r\n- Contributing docs for Black and Prettier, closes #1167 \r\n- All ?_ parameters now copied to hidden form fields, closes #1194 \r\n- Fixed bug loading database called 'test-database (1).sqlite' - Closes #1181.\r\n\r\n", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 792904595, "label": "Release notes for Datasette 0.54"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/1201#issuecomment-766545604", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1201", "id": 766545604, "node_id": "MDEyOklzc3VlQ29tbWVudDc2NjU0NTYwNA==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2021-01-25T05:14:31Z", "updated_at": "2021-01-25T05:14:31Z", "author_association": "OWNER", "body": "The two big ticket items are `