html_url,issue_url,id,node_id,user,user_label,created_at,updated_at,author_association,body,reactions,issue,issue_label,performed_via_github_app https://github.com/simonw/datasette/issues/744#issuecomment-634395343,https://api.github.com/repos/simonw/datasette/issues/744,634395343,MDEyOklzc3VlQ29tbWVudDYzNDM5NTM0Mw==,9599,simonw,2020-05-27T02:49:26Z,2020-05-27T02:49:26Z,OWNER,"OK, here's a new branch you can try. Install it like this: pip install https://github.com/simonw/datasette/archive/shutil-backport.zip If it works for you I'll merge that branch into master.","{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",608058890,link_or_copy_directory() error - Invalid cross-device link, https://github.com/simonw/datasette/issues/744#issuecomment-634446887,https://api.github.com/repos/simonw/datasette/issues/744,634446887,MDEyOklzc3VlQ29tbWVudDYzNDQ0Njg4Nw==,30607,aborruso,2020-05-27T06:01:28Z,2020-05-27T06:01:28Z,NONE,"Dear @simonw thank you for your time, now IT WORKS!!! I hope that this edit to datasette code is not for an exceptional case (my PC configuration) and that it will be useful to other users. Thank you again!!","{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",608058890,link_or_copy_directory() error - Invalid cross-device link, https://github.com/simonw/datasette/issues/744#issuecomment-634850676,https://api.github.com/repos/simonw/datasette/issues/744,634850676,MDEyOklzc3VlQ29tbWVudDYzNDg1MDY3Ng==,9599,simonw,2020-05-27T18:18:01Z,2020-05-27T18:18:01Z,OWNER,Thanks for helping test this @aborruso!,"{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",608058890,link_or_copy_directory() error - Invalid cross-device link, https://github.com/simonw/datasette/issues/581#issuecomment-634852196,https://api.github.com/repos/simonw/datasette/issues/581,634852196,MDEyOklzc3VlQ29tbWVudDYzNDg1MjE5Ng==,9599,simonw,2020-05-27T18:20:46Z,2020-05-27T18:20:46Z,OWNER,"Here's the code that calls the renderers - this needs to be expanded to check for those extra optional arguments: https://github.com/simonw/datasette/blob/2d099ad9c657d2cab59de91cdb8bfed2da236ef6/datasette/views/base.py#L387-L398","{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",502993509,Redesign register_output_renderer callback, https://github.com/simonw/datasette/issues/581#issuecomment-634853296,https://api.github.com/repos/simonw/datasette/issues/581,634853296,MDEyOklzc3VlQ29tbWVudDYzNDg1MzI5Ng==,9599,simonw,2020-05-27T18:22:46Z,2020-05-27T18:22:46Z,OWNER,"While I'm doing this, another feature I would like is the ability for renderers to opt-in / opt-out of being displayed as options on the page. https://www.niche-museums.com/browse/museums for example shows a `atom` link because the `datasette-atom` plugin is installed... but clicking it will give you a 400 error because the correct columns are not present: ","{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",502993509,Redesign register_output_renderer callback, https://github.com/simonw/datasette/issues/581#issuecomment-634856748,https://api.github.com/repos/simonw/datasette/issues/581,634856748,MDEyOklzc3VlQ29tbWVudDYzNDg1Njc0OA==,9599,simonw,2020-05-27T18:28:32Z,2020-05-27T18:28:32Z,OWNER,"Here's the code that passes a list of renderers to the template: https://github.com/simonw/datasette/blob/2d099ad9c657d2cab59de91cdb8bfed2da236ef6/datasette/views/base.py#L411-L423 A renderer is currently defined as a two-key dictionary: ```python @hookimpl def register_output_renderer(datasette): return { 'extension': 'test', 'callback': render_test } ``` I can add a third key, `""should_suggest""` which is a function that returns `True` or `False` for a given query. If that key is missing it is assumed to return `True`. One catch: what arguments should be passed to the `should_suggest(...)` function?","{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",502993509,Redesign register_output_renderer callback, https://github.com/simonw/datasette/issues/581#issuecomment-634857975,https://api.github.com/repos/simonw/datasette/issues/581,634857975,MDEyOklzc3VlQ29tbWVudDYzNDg1Nzk3NQ==,9599,simonw,2020-05-27T18:30:29Z,2020-05-27T18:30:29Z,OWNER,I'll use #770 for the `should_suggest` mechanism - this issue is for the extra arguments passed to the rendering callback.,"{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",502993509,Redesign register_output_renderer callback, https://github.com/simonw/datasette/issues/581#issuecomment-634865620,https://api.github.com/repos/simonw/datasette/issues/581,634865620,MDEyOklzc3VlQ29tbWVudDYzNDg2NTYyMA==,9599,simonw,2020-05-27T18:44:06Z,2020-05-27T18:44:06Z,OWNER,"The existing render callback takes the following arguments: > `args` - dictionary > The GET parameters of the request > > `data` - dictionary > The data to be rendered > > `view_name` - string > The name of the view where the renderer is being called. (`index`, `database`, `table`, and `row` are the most important ones.) The `data` argument is a bit of a problem, because it tightly couples plugins to a currently undocumented datastructure within Datasette. Here's how `datasette-atom` picks that apart for example: https://github.com/simonw/datasette-atom/blob/095941c23c81b70c4787cdeef873c556b573b5fa/datasette_atom/__init__.py#L15-L66 - it does things like access `data[""query""][""sql""]` to figure out the SQL query that was used. I'm going to change the design of part of this ticket. I won't break the old `data` value just yet, but I'll mark it to be deprecated by Datasette 1.0. I think the only plugins using it right now are my `datasette-atom` and `datasette-ics` and @russss's [datasette-geo](https://github.com/russss/datasette-geo/blob/0d24c9fd782eeae8d136ee791143ee8cbf49ebdf/datasette_plugin_geo/__init__.py#L94-L101) so hopefully changing this won't cause any wider damage.","{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",502993509,Redesign register_output_renderer callback, https://github.com/simonw/datasette/issues/581#issuecomment-634879258,https://api.github.com/repos/simonw/datasette/issues/581,634879258,MDEyOklzc3VlQ29tbWVudDYzNDg3OTI1OA==,9599,simonw,2020-05-27T19:09:22Z,2020-05-28T01:33:45Z,OWNER,"OK, the new design: your callback function can take any of the following arguments: - `datasette` - a Datasette instance - `columns` - the list of columns - `rows` - the list of rows (each one a SQLite `Row` object) - `sql` - the SQL query being executed - `query_name` - the name of the canned query, if this is one - `database` - the database name - `table` - the table or view name - `request` - the request object (to be documented in #706) - `view_name` - the name of the view We will also continue to support the existing `args` and `data` arguments, but these will be undocumented and will be deprecated in Datasette 1.0. UPDATE: Decided against this, see https://github.com/simonw/datasette/issues/581#issuecomment-634946197","{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",502993509,Redesign register_output_renderer callback, https://github.com/simonw/datasette/issues/581#issuecomment-634879734,https://api.github.com/repos/simonw/datasette/issues/581,634879734,MDEyOklzc3VlQ29tbWVudDYzNDg3OTczNA==,9599,simonw,2020-05-27T19:10:17Z,2020-05-27T19:12:36Z,OWNER,The `should_suggest` callback will take the same arguments: https://github.com/simonw/datasette/issues/770#issuecomment-634880090,"{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",502993509,Redesign register_output_renderer callback, https://github.com/simonw/datasette/issues/770#issuecomment-634880090,https://api.github.com/repos/simonw/datasette/issues/770,634880090,MDEyOklzc3VlQ29tbWVudDYzNDg4MDA5MA==,9599,simonw,2020-05-27T19:10:57Z,2020-05-28T04:22:47Z,OWNER,"This `can_render` callback should take the same arguments as the redesigned `render` (previously called `callback`): https://github.com/simonw/datasette/issues/581#issuecomment-634879258 - `datasette` - a Datasette instance - `columns` - the list of columns - `rows` - the list of rows (each one a SQLite `Row` object) - `sql` - the SQL query being executed - `query_name` - the name of the canned query, if this is one - `database` - the database name - `table` - the table or view name - `request` - the request object (to be documented in #706) - `view_name` - the name of the view","{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",625930207,register_output_renderer can_render mechanism, https://github.com/simonw/datasette/issues/770#issuecomment-634880474,https://api.github.com/repos/simonw/datasette/issues/770,634880474,MDEyOklzc3VlQ29tbWVudDYzNDg4MDQ3NA==,9599,simonw,2020-05-27T19:11:39Z,2020-05-27T19:11:39Z,OWNER,I'm going to rename `callback` to `render` but continue supporting `callback` until Datasette 1.0.,"{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",625930207,register_output_renderer can_render mechanism, https://github.com/simonw/datasette/issues/581#issuecomment-634881287,https://api.github.com/repos/simonw/datasette/issues/581,634881287,MDEyOklzc3VlQ29tbWVudDYzNDg4MTI4Nw==,9599,simonw,2020-05-27T19:13:09Z,2020-05-27T19:13:09Z,OWNER,"I think I need a utility function for ""call this function with this dictionary of arguments, but only pass the arguments which are inspected by the function"".","{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",502993509,Redesign register_output_renderer callback, https://github.com/simonw/datasette/issues/581#issuecomment-634882112,https://api.github.com/repos/simonw/datasette/issues/581,634882112,MDEyOklzc3VlQ29tbWVudDYzNDg4MjExMg==,9599,simonw,2020-05-27T19:14:55Z,2020-05-27T19:14:55Z,OWNER,"https://docs.python.org/3/library/inspect.html#introspecting-callables-with-the-signature-object > New in version 3.3. > > The Signature object represents the call signature of a callable object and its return annotation. To retrieve a Signature object, use the [`signature()`](https://docs.python.org/3/library/inspect.html#inspect.signature ""inspect.signature"") function. > > `inspect.``signature`(*callable*, ***, *follow_wrapped=True*) > > Return a [`Signature`](https://docs.python.org/3/library/inspect.html#inspect.Signature ""inspect.Signature"") object for the given `callable`: > > ``` > >>> from inspect import signature > >>> def foo(a, *, b:int, **kwargs): > ... pass > > >>> sig = signature(foo) > > >>> str(sig) > '(a, *, b:int, **kwargs)' > > >>> str(sig.parameters['b']) > 'b:int' > > >>> sig.parameters['b'].annotation > > ```","{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",502993509,Redesign register_output_renderer callback, https://github.com/simonw/datasette/issues/581#issuecomment-634882770,https://api.github.com/repos/simonw/datasette/issues/581,634882770,MDEyOklzc3VlQ29tbWVudDYzNDg4Mjc3MA==,9599,simonw,2020-05-27T19:16:19Z,2020-05-27T19:16:19Z,OWNER,"``` In [1]: import inspect In [2]: def foo(view, sql, inspect): ...: pass ...: In [3]: inspect.signature(foo) Out[3]: In [4]: inspect.signature(foo).parameters Out[4]: mappingproxy({'view': , 'sql': , 'inspect': }) In [5]: inspect.signature(foo).parameters.keys() Out[5]: odict_keys(['view', 'sql', 'inspect']) In [6]: set(inspect.signature(foo).parameters.keys()) Out[6]: {'inspect', 'sql', 'view'} ```","{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",502993509,Redesign register_output_renderer callback, https://github.com/simonw/datasette/issues/581#issuecomment-634888582,https://api.github.com/repos/simonw/datasette/issues/581,634888582,MDEyOklzc3VlQ29tbWVudDYzNDg4ODU4Mg==,9599,simonw,2020-05-27T19:23:23Z,2020-05-27T19:23:23Z,OWNER,"Here's the function I just wrote for this: ```python def call_with_supported_arguments(fn, **kwargs): parameters = inspect.signature(fn).parameters.keys() call_with = [] for parameter in parameters: if parameter not in kwargs: raise TypeError(""{} requires parameters {}"".format(fn, tuple(parameters))) call_with.append(kwargs[parameter]) return fn(*call_with) ```","{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",502993509,Redesign register_output_renderer callback, https://github.com/simonw/datasette/issues/581#issuecomment-634893744,https://api.github.com/repos/simonw/datasette/issues/581,634893744,MDEyOklzc3VlQ29tbWVudDYzNDg5Mzc0NA==,9599,simonw,2020-05-27T19:32:08Z,2020-05-27T19:32:08Z,OWNER,Need to figure out how best to unit test this plugin hook.,"{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",502993509,Redesign register_output_renderer callback, https://github.com/simonw/datasette/issues/771#issuecomment-634900776,https://api.github.com/repos/simonw/datasette/issues/771,634900776,MDEyOklzc3VlQ29tbWVudDYzNDkwMDc3Ng==,9599,simonw,2020-05-27T19:44:25Z,2020-05-27T19:44:25Z,OWNER,"This seems to work: ```diff diff --git a/tests/test_plugins.py b/tests/test_plugins.py index 8b6a6b4..e9a40aa 100644 --- a/tests/test_plugins.py +++ b/tests/test_plugins.py @@ -7,7 +7,7 @@ from .fixtures import ( TestClient as _TestClient, ) # noqa from datasette.app import Datasette -from datasette.plugins import get_plugins, DEFAULT_PLUGINS +from datasette.plugins import get_plugins, DEFAULT_PLUGINS, pm from datasette.utils import sqlite3 import base64 import json @@ -20,6 +20,21 @@ import pytest import urllib +def test_plugin_hooks_have_tests(): + ""Every plugin hook should be referenced in this test module"" + hooks = [name for name in dir(pm.hook) if not name.startswith(""_"")] + tests_in_this_module = [t for t in globals().keys() if t.startswith('test_')] + untested = [] + for hook in hooks: + ok = False + for test in tests_in_this_module: + if hook in test: + ok = True + if not ok: + untested.append(hook) + assert not untested, 'These plugin hooks are missing tests: {}'.format(untested) + + def test_plugins_dir_plugin_prepare_connection(app_client): response = app_client.get( ""/fixtures.json?sql=select+convert_units(100%2C+'m'%2C+'ft')"" ``` Based on how the documentation unit tests work. Currently fails with: AssertionError: These plugin hooks are missing tests: ['prepare_jinja2_environment', 'publish_subcommand', 'register_facet_classes', 'register_output_renderer'] ","{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",625980317,Unit test that checks that all plugin hooks have corresponding unit tests, https://github.com/simonw/datasette/issues/771#issuecomment-634909347,https://api.github.com/repos/simonw/datasette/issues/771,634909347,MDEyOklzc3VlQ29tbWVudDYzNDkwOTM0Nw==,9599,simonw,2020-05-27T20:01:52Z,2020-05-27T20:01:52Z,OWNER,I'll do the work for this in the pull request #772.,"{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",625980317,Unit test that checks that all plugin hooks have corresponding unit tests, https://github.com/simonw/datasette/issues/771#issuecomment-634909818,https://api.github.com/repos/simonw/datasette/issues/771,634909818,MDEyOklzc3VlQ29tbWVudDYzNDkwOTgxOA==,9599,simonw,2020-05-27T20:02:52Z,2020-05-27T20:02:52Z,OWNER,Actually I'll land this using `@pytest.mark.xfail`.,"{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",625980317,Unit test that checks that all plugin hooks have corresponding unit tests, https://github.com/simonw/datasette/issues/771#issuecomment-634915104,https://api.github.com/repos/simonw/datasette/issues/771,634915104,MDEyOklzc3VlQ29tbWVudDYzNDkxNTEwNA==,9599,simonw,2020-05-27T20:14:32Z,2020-05-27T20:14:32Z,OWNER,"``` $ pytest -k test_plugin_hooks_have_tests -vv ====================================== test session starts ====================================== platform darwin -- Python 3.7.7, pytest-5.2.4, py-1.8.1, pluggy-0.13.1 -- /Users/simon/.local/share/virtualenvs/datasette-AWNrQs95/bin/python cachedir: .pytest_cache rootdir: /Users/simon/Dropbox/Development/datasette, inifile: pytest.ini plugins: asyncio-0.10.0 collected 486 items / 475 deselected / 11 selected tests/test_plugins.py::test_plugin_hooks_have_tests[asgi_wrapper] XPASS [ 9%] tests/test_plugins.py::test_plugin_hooks_have_tests[extra_body_script] XPASS [ 18%] tests/test_plugins.py::test_plugin_hooks_have_tests[extra_css_urls] XPASS [ 27%] tests/test_plugins.py::test_plugin_hooks_have_tests[extra_js_urls] XPASS [ 36%] tests/test_plugins.py::test_plugin_hooks_have_tests[extra_template_vars] XPASS [ 45%] tests/test_plugins.py::test_plugin_hooks_have_tests[prepare_connection] XPASS [ 54%] tests/test_plugins.py::test_plugin_hooks_have_tests[prepare_jinja2_environment] XFAIL [ 63%] tests/test_plugins.py::test_plugin_hooks_have_tests[publish_subcommand] XFAIL [ 72%] tests/test_plugins.py::test_plugin_hooks_have_tests[register_facet_classes] XFAIL [ 81%] tests/test_plugins.py::test_plugin_hooks_have_tests[register_output_renderer] XFAIL [ 90%] tests/test_plugins.py::test_plugin_hooks_have_tests[render_cell] XPASS [100%] ========================= 475 deselected, 4 xfailed, 7 xpassed in 1.70s =========================","{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",625980317,Unit test that checks that all plugin hooks have corresponding unit tests, https://github.com/simonw/datasette/issues/771#issuecomment-634916313,https://api.github.com/repos/simonw/datasette/issues/771,634916313,MDEyOklzc3VlQ29tbWVudDYzNDkxNjMxMw==,9599,simonw,2020-05-27T20:17:13Z,2020-05-27T20:17:13Z,OWNER,Closed in da87e963bff24e47878a5bc2025c8bfc63d4bc93,"{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",625980317,Unit test that checks that all plugin hooks have corresponding unit tests, https://github.com/simonw/datasette/issues/581#issuecomment-634921101,https://api.github.com/repos/simonw/datasette/issues/581,634921101,MDEyOklzc3VlQ29tbWVudDYzNDkyMTEwMQ==,9599,simonw,2020-05-27T20:27:36Z,2020-05-27T20:27:36Z,OWNER,Actually passing the `request` object would be OK if I document it see https://github.com/simonw/datasette/issues/706,"{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",502993509,Redesign register_output_renderer callback, https://github.com/simonw/datasette/issues/773#issuecomment-634940522,https://api.github.com/repos/simonw/datasette/issues/773,634940522,MDEyOklzc3VlQ29tbWVudDYzNDk0MDUyMg==,9599,simonw,2020-05-27T21:07:48Z,2020-05-27T21:07:48Z,OWNER,Remove this `xfail` decorator once they are all tested: https://github.com/simonw/datasette/blob/da87e963bff24e47878a5bc2025c8bfc63d4bc93/tests/test_plugins.py#L23-L28,"{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",626001501,All plugin hooks should have unit tests, https://github.com/simonw/datasette/issues/581#issuecomment-634943336,https://api.github.com/repos/simonw/datasette/issues/581,634943336,MDEyOklzc3VlQ29tbWVudDYzNDk0MzMzNg==,9599,simonw,2020-05-27T21:13:04Z,2020-05-27T21:13:04Z,OWNER,Since I'm passing `request` I won't pass `scope` - if people want that they can access `request.scope`.,"{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",502993509,Redesign register_output_renderer callback, https://github.com/simonw/datasette/issues/581#issuecomment-634944832,https://api.github.com/repos/simonw/datasette/issues/581,634944832,MDEyOklzc3VlQ29tbWVudDYzNDk0NDgzMg==,9599,simonw,2020-05-27T21:15:50Z,2020-05-27T21:16:28Z,OWNER,"It bothers me that `query_name` here means the configured name of the canned query, but `view_name` means the name of the Datasette view class, NOT the name of an associated SQL view. That's in `table`. Can I come up with clearer names for these?","{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",502993509,Redesign register_output_renderer callback, https://github.com/simonw/datasette/issues/581#issuecomment-634946197,https://api.github.com/repos/simonw/datasette/issues/581,634946197,MDEyOklzc3VlQ29tbWVudDYzNDk0NjE5Nw==,9599,simonw,2020-05-27T21:18:30Z,2020-05-27T21:18:30Z,OWNER,"I'm going to break backwards compatibility directly here, without waiting for Datasette 1.0. The reason is that https://github.com/russss/datasette-geo hasn't been updated in 13 months so is already broken against current Datasette, and the other two plugins using this hook are owned by me so I can upgrade them myself.","{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",502993509,Redesign register_output_renderer callback, https://github.com/simonw/datasette/issues/581#issuecomment-634946319,https://api.github.com/repos/simonw/datasette/issues/581,634946319,MDEyOklzc3VlQ29tbWVudDYzNDk0NjMxOQ==,9599,simonw,2020-05-27T21:18:50Z,2020-05-27T21:18:50Z,OWNER,(I used GitHub code search to find code using this plugin hook: https://github.com/search?q=register_output_renderer&type=Code ),"{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",502993509,Redesign register_output_renderer callback, https://github.com/simonw/datasette/issues/758#issuecomment-634950200,https://api.github.com/repos/simonw/datasette/issues/758,634950200,MDEyOklzc3VlQ29tbWVudDYzNDk1MDIwMA==,9599,simonw,2020-05-27T21:26:37Z,2020-05-27T21:26:37Z,OWNER,"https://latest.datasette.io/.json currently returns: ``` { ""fixtures"": { ""name"": ""fixtures"", ""hash"": ""87b3f2c55dfb81ff1452dd306c2623fa5550b90982cfa32bad404c4d8bbedde2"", ""color"": ""87b3f2"", ""path"": ""/fixtures"", ""tables_and_views_truncated"": [ ``` I published `fixtures.db` here like this: datasette publish cloudrun fixtures.db --service datasette-hash-urls --extra-options '--config hash_urls:1' https://datasette-hash-urls-j7hipcg4aq-uw.a.run.app/.json ``` { ""fixtures"": { ""name"": ""fixtures"", ""hash"": ""bda7daa889c23f9a8f06e46d7d280dd423c76275e9593c4c1cad7c53b19032fe"", ""color"": ""bda7da"", ""path"": ""/fixtures-bda7daa"", ```","{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",612382643,Question: Access to immutable database-path, https://github.com/simonw/datasette/issues/758#issuecomment-634951605,https://api.github.com/repos/simonw/datasette/issues/758,634951605,MDEyOklzc3VlQ29tbWVudDYzNDk1MTYwNQ==,9599,simonw,2020-05-27T21:29:19Z,2020-05-27T21:29:19Z,OWNER,"But... https://datasette-hash-urls-j7hipcg4aq-uw.a.run.app/fixtures-bda7daa.json doesn't expose that hash: ``` { ""database"": ""fixtures"", ""size"": 258048, ""tables"": [ { ""name"": ""123_starts_with_digits"", ``` Likewise https://datasette-hash-urls-j7hipcg4aq-uw.a.run.app/fixtures-bda7daa/complex_foreign_keys.json ``` { ""database"": ""fixtures"", ""table"": ""complex_foreign_keys"", ""is_view"": false, ""human_description_en"": """", ""rows"": [ [ ""1"", ""1"", ""2"", ""1"" ] ], ``` And https://datasette-hash-urls-j7hipcg4aq-uw.a.run.app/fixtures-bda7daa/complex_foreign_keys/1.json ``` { ""database"": ""fixtures"", ""table"": ""complex_foreign_keys"", ""rows"": [ ```","{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",612382643,Question: Access to immutable database-path, https://github.com/simonw/datasette/issues/581#issuecomment-634964294,https://api.github.com/repos/simonw/datasette/issues/581,634964294,MDEyOklzc3VlQ29tbWVudDYzNDk2NDI5NA==,9599,simonw,2020-05-27T21:57:10Z,2020-05-27T21:57:10Z,OWNER,"Right now a rendering callback returns the following: ``` body - string or bytes, optional The response body, default empty content_type - string, optional The Content-Type header, default text/plain status_code - integer, optional The HTTP status code, default 200 ``` I'm going to add an optional `headers` dictionary key, too.","{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",502993509,Redesign register_output_renderer callback, https://github.com/simonw/datasette/issues/581#issuecomment-634964457,https://api.github.com/repos/simonw/datasette/issues/581,634964457,MDEyOklzc3VlQ29tbWVudDYzNDk2NDQ1Nw==,9599,simonw,2020-05-27T21:57:35Z,2020-05-27T21:57:35Z,OWNER,(I wonder if this would be enough to allow really smart plugins to implement ETag/conditional get),"{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",502993509,Redesign register_output_renderer callback, https://github.com/simonw/datasette/issues/706#issuecomment-634965148,https://api.github.com/repos/simonw/datasette/issues/706,634965148,MDEyOklzc3VlQ29tbWVudDYzNDk2NTE0OA==,9599,simonw,2020-05-27T21:59:07Z,2020-05-27T21:59:07Z,OWNER,"This is the full current implementation of the request object: https://github.com/simonw/datasette/blob/9424687e9e94401438896116898a071702b09d40/datasette/utils/asgi.py#L15-L95","{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",585633142,"Documentation for the ""request"" object", https://github.com/simonw/datasette/issues/706#issuecomment-634973596,https://api.github.com/repos/simonw/datasette/issues/706,634973596,MDEyOklzc3VlQ29tbWVudDYzNDk3MzU5Ng==,9599,simonw,2020-05-27T22:19:02Z,2020-05-27T22:19:02Z,OWNER,"New documentation can be seen here: https://github.com/simonw/datasette/blob/6d7cb02f00010d3cb4b4bac0460d41277652b80e/docs/internals.rst#request-object It's inspired me to reconsider the name of the `.raw_args` property, which isn't particularly clear.","{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",585633142,"Documentation for the ""request"" object", https://github.com/simonw/datasette/issues/706#issuecomment-634974088,https://api.github.com/repos/simonw/datasette/issues/706,634974088,MDEyOklzc3VlQ29tbWVudDYzNDk3NDA4OA==,9599,simonw,2020-05-27T22:20:20Z,2020-05-27T22:20:20Z,OWNER,It looks like I inherited `.raw_args` from Sanic - I use it in a few places: https://github.com/search?q=user%3Asimonw+raw_args&type=Code,"{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",585633142,"Documentation for the ""request"" object", https://github.com/simonw/datasette/issues/706#issuecomment-634974819,https://api.github.com/repos/simonw/datasette/issues/706,634974819,MDEyOklzc3VlQ29tbWVudDYzNDk3NDgxOQ==,9599,simonw,2020-05-27T22:22:20Z,2020-05-27T22:22:20Z,OWNER,"What would a better name be? - `.simple_args` - `.kv_args` - `.pair_args` - `.dict_args` - `.args_dict` I dislike the last two the least.","{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",585633142,"Documentation for the ""request"" object", https://github.com/simonw/datasette/issues/706#issuecomment-634975252,https://api.github.com/repos/simonw/datasette/issues/706,634975252,MDEyOklzc3VlQ29tbWVudDYzNDk3NTI1Mg==,9599,simonw,2020-05-27T22:23:26Z,2020-05-27T22:30:05Z,OWNER,I'm going to leave `.raw_args` in for the moment but deliberately not document it. I'll hope to phase it out entirely at a later date.,"{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",585633142,"Documentation for the ""request"" object", https://github.com/simonw/datasette/issues/581#issuecomment-634978388,https://api.github.com/repos/simonw/datasette/issues/581,634978388,MDEyOklzc3VlQ29tbWVudDYzNDk3ODM4OA==,9599,simonw,2020-05-27T22:32:03Z,2020-05-27T22:32:03Z,OWNER,Request object is now documented: https://datasette.readthedocs.io/en/latest/internals.html#request-object,"{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",502993509,Redesign register_output_renderer callback, https://github.com/simonw/datasette/issues/770#issuecomment-634980179,https://api.github.com/repos/simonw/datasette/issues/770,634980179,MDEyOklzc3VlQ29tbWVudDYzNDk4MDE3OQ==,9599,simonw,2020-05-27T22:37:19Z,2020-05-27T22:37:19Z,OWNER,"Can I come up with a better name than `should_suggest`? It's a check that sees if the current query is supported by the renderer plugin. Some options: - `can_render` - `supports_query` - `is_supported` I like `can_render`.","{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",625930207,register_output_renderer can_render mechanism,