html_url,issue_url,id,node_id,user,created_at,updated_at,author_association,body,reactions,issue,performed_via_github_app
https://github.com/simonw/datasette/issues/581#issuecomment-635055346,https://api.github.com/repos/simonw/datasette/issues/581,635055346,MDEyOklzc3VlQ29tbWVudDYzNTA1NTM0Ng==,9599,2020-05-28T02:24:14Z,2020-05-28T02:24:14Z,OWNER,Updated documentation is here: https://datasette.readthedocs.io/en/latest/plugins.html#register-output-renderer-datasette,"{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",502993509,
https://github.com/simonw/datasette/issues/581#issuecomment-634879258,https://api.github.com/repos/simonw/datasette/issues/581,634879258,MDEyOklzc3VlQ29tbWVudDYzNDg3OTI1OA==,9599,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,
https://github.com/simonw/datasette/issues/581#issuecomment-634978388,https://api.github.com/repos/simonw/datasette/issues/581,634978388,MDEyOklzc3VlQ29tbWVudDYzNDk3ODM4OA==,9599,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,
https://github.com/simonw/datasette/issues/581#issuecomment-634964457,https://api.github.com/repos/simonw/datasette/issues/581,634964457,MDEyOklzc3VlQ29tbWVudDYzNDk2NDQ1Nw==,9599,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,
https://github.com/simonw/datasette/issues/581#issuecomment-634964294,https://api.github.com/repos/simonw/datasette/issues/581,634964294,MDEyOklzc3VlQ29tbWVudDYzNDk2NDI5NA==,9599,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,
https://github.com/simonw/datasette/issues/581#issuecomment-634946319,https://api.github.com/repos/simonw/datasette/issues/581,634946319,MDEyOklzc3VlQ29tbWVudDYzNDk0NjMxOQ==,9599,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,
https://github.com/simonw/datasette/issues/581#issuecomment-634946197,https://api.github.com/repos/simonw/datasette/issues/581,634946197,MDEyOklzc3VlQ29tbWVudDYzNDk0NjE5Nw==,9599,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,
https://github.com/simonw/datasette/issues/581#issuecomment-634944832,https://api.github.com/repos/simonw/datasette/issues/581,634944832,MDEyOklzc3VlQ29tbWVudDYzNDk0NDgzMg==,9599,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,
https://github.com/simonw/datasette/issues/581#issuecomment-634943336,https://api.github.com/repos/simonw/datasette/issues/581,634943336,MDEyOklzc3VlQ29tbWVudDYzNDk0MzMzNg==,9599,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,
https://github.com/simonw/datasette/issues/581#issuecomment-592621235,https://api.github.com/repos/simonw/datasette/issues/581,592621235,MDEyOklzc3VlQ29tbWVudDU5MjYyMTIzNQ==,9599,2020-02-28T17:24:06Z,2020-05-27T21:12:21Z,OWNER,"Rather than pass a request object (hence promoting that object into part of the documented, stable API) I think I'll pass the ASGI scope - that's already a stable, documented standard.

UPDATE: changed my mind since `request` is used by other plugins too, see #706.","{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",502993509,
https://github.com/simonw/datasette/issues/581#issuecomment-634921101,https://api.github.com/repos/simonw/datasette/issues/581,634921101,MDEyOklzc3VlQ29tbWVudDYzNDkyMTEwMQ==,9599,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,
https://github.com/simonw/datasette/issues/581#issuecomment-634893744,https://api.github.com/repos/simonw/datasette/issues/581,634893744,MDEyOklzc3VlQ29tbWVudDYzNDg5Mzc0NA==,9599,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,
https://github.com/simonw/datasette/issues/581#issuecomment-634888582,https://api.github.com/repos/simonw/datasette/issues/581,634888582,MDEyOklzc3VlQ29tbWVudDYzNDg4ODU4Mg==,9599,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,
https://github.com/simonw/datasette/issues/581#issuecomment-634882770,https://api.github.com/repos/simonw/datasette/issues/581,634882770,MDEyOklzc3VlQ29tbWVudDYzNDg4Mjc3MA==,9599,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]: <Signature (view, sql, inspect)>

In [4]: inspect.signature(foo).parameters                                                                                                                                          
Out[4]: 
mappingproxy({'view': <Parameter ""view"">,
              'sql': <Parameter ""sql"">,
              'inspect': <Parameter ""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,
https://github.com/simonw/datasette/issues/581#issuecomment-634882112,https://api.github.com/repos/simonw/datasette/issues/581,634882112,MDEyOklzc3VlQ29tbWVudDYzNDg4MjExMg==,9599,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
> <class 'int'>
> ```","{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",502993509,
https://github.com/simonw/datasette/issues/581#issuecomment-634881287,https://api.github.com/repos/simonw/datasette/issues/581,634881287,MDEyOklzc3VlQ29tbWVudDYzNDg4MTI4Nw==,9599,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,
https://github.com/simonw/datasette/issues/581#issuecomment-634879734,https://api.github.com/repos/simonw/datasette/issues/581,634879734,MDEyOklzc3VlQ29tbWVudDYzNDg3OTczNA==,9599,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,
https://github.com/simonw/datasette/issues/581#issuecomment-634865620,https://api.github.com/repos/simonw/datasette/issues/581,634865620,MDEyOklzc3VlQ29tbWVudDYzNDg2NTYyMA==,9599,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,
https://github.com/simonw/datasette/issues/581#issuecomment-634857975,https://api.github.com/repos/simonw/datasette/issues/581,634857975,MDEyOklzc3VlQ29tbWVudDYzNDg1Nzk3NQ==,9599,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,
https://github.com/simonw/datasette/issues/581#issuecomment-634856748,https://api.github.com/repos/simonw/datasette/issues/581,634856748,MDEyOklzc3VlQ29tbWVudDYzNDg1Njc0OA==,9599,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,
https://github.com/simonw/datasette/issues/581#issuecomment-634853296,https://api.github.com/repos/simonw/datasette/issues/581,634853296,MDEyOklzc3VlQ29tbWVudDYzNDg1MzI5Ng==,9599,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:

<img width=""1113"" alt=""browse__museums__102_rows"" src=""https://user-images.githubusercontent.com/9599/83057883-60110000-a00c-11ea-966f-8b2a7222f1b0.png"">
","{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",502993509,
https://github.com/simonw/datasette/issues/581#issuecomment-634852196,https://api.github.com/repos/simonw/datasette/issues/581,634852196,MDEyOklzc3VlQ29tbWVudDYzNDg1MjE5Ng==,9599,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,
https://github.com/simonw/datasette/issues/581#issuecomment-569005894,https://api.github.com/repos/simonw/datasette/issues/581,569005894,MDEyOklzc3VlQ29tbWVudDU2OTAwNTg5NA==,9599,2019-12-26T08:03:59Z,2019-12-26T08:03:59Z,OWNER,"To solve https://github.com/simonw/datasette-atom/issues/6 the name of the current canned query should be made available somehow.

That way the plugin configuration could specify that the title for browse/feed should be X.","{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",502993509,
https://github.com/simonw/datasette/issues/581#issuecomment-538672413,https://api.github.com/repos/simonw/datasette/issues/581,538672413,MDEyOklzc3VlQ29tbWVudDUzODY3MjQxMw==,9599,2019-10-05T17:45:04Z,2019-10-05T17:45:04Z,OWNER,The `request` object should be made available too.,"{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",502993509,