`", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/998/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"}
{"id": 717768441, "node_id": "MDU6SXNzdWU3MTc3Njg0NDE=", "number": 1001, "title": "OPTIONS requests return a 500 error", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": {"value": 5971510, "label": "Datasette 0.50"}, "comments": 8, "created_at": "2020-10-09T00:57:13Z", "updated_at": "2020-10-09T01:44:41Z", "closed_at": "2020-10-09T01:43:58Z", "author_association": "OWNER", "pull_request": null, "body": "```\r\n% curl -vv -XOPTIONS https://latest.datasette.io/\r\n* Trying 216.58.195.83:443...\r\n> OPTIONS / HTTP/1.1\r\n> Host: latest.datasette.io\r\n> User-Agent: curl/7.70.0\r\n> Accept: */*\r\n> \r\n* Mark bundle as not supporting multiuse\r\n< HTTP/1.1 500 Internal Server Error\r\n```", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/1001/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"}
{"id": 724878151, "node_id": "MDU6SXNzdWU3MjQ4NzgxNTE=", "number": 1032, "title": "Bring date parsing into Datasette core", "user": {"value": 9599, "label": "simonw"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 8, "created_at": "2020-10-19T18:30:45Z", "updated_at": "2020-10-19T19:37:55Z", "closed_at": null, "author_association": "OWNER", "pull_request": null, "body": "Currently this is mainly handled by a plugin - https://github.com/simonw/datasette-dateutil - but I realise now that this really needs to be core functionality.\r\n\r\nSee also Twitter thread: https://twitter.com/simonw/status/1318234808653213696", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/1032/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": null}
{"id": 760621356, "node_id": "MDU6SXNzdWU3NjA2MjEzNTY=", "number": 1136, "title": "Establish pattern for release branches to support bug fixes", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 8, "created_at": "2020-12-09T19:48:18Z", "updated_at": "2020-12-09T20:17:02Z", "closed_at": "2020-12-09T20:14:41Z", "author_association": "OWNER", "pull_request": null, "body": "I want to fix the bug in #1134 and ship it as Datasette 0.52.5 - but the `main` branch now has a feature in it (4c25b035b2370983c8dd5e0c8762e9154e379774 added `arraynotcontains`, #1132).\r\n\r\nI'm not ready for a feature release, so instead I want to release 0.52.5 with just that bug fix.\r\n\r\nThis is the first time I will have shipped a release from a branch. I need to establish that pattern and add it to the documentation in https://docs.datasette.io/en/stable/contributing.html", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/1136/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"}
{"id": 778450486, "node_id": "MDU6SXNzdWU3Nzg0NTA0ODY=", "number": 1171, "title": "GitHub Actions workflow to build and sign macOS binary executables", "user": {"value": 9599, "label": "simonw"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 8, "created_at": "2021-01-04T23:36:59Z", "updated_at": "2021-01-07T19:36:00Z", "closed_at": null, "author_association": "OWNER", "pull_request": null, "body": "Using PyInstaller, as explored in #93 and https://til.simonwillison.net/python/packaging-pyinstaller\r\n\r\nThe bigger challenge will be the code signing bit. I'll need a Apple Developer account ($99/year) and some extensive CI fiddling.", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/1171/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": null}
{"id": 780278550, "node_id": "MDU6SXNzdWU3ODAyNzg1NTA=", "number": 1179, "title": "Make original path available to render hooks", "user": {"value": 9599, "label": "simonw"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 8, "created_at": "2021-01-06T08:31:45Z", "updated_at": "2021-01-25T04:44:33Z", "closed_at": null, "author_association": "OWNER", "pull_request": null, "body": "https://github.com/simonw/datasette-export-notebook/blob/0.1/datasette_export_notebook/__init__.py\r\n\r\n```python\r\nasync def render_notebook(datasette, request):\r\n return Response.html(\r\n await datasette.render_template(\r\n \"export_notebook.html\",\r\n {\r\n \"csv_stream_url\": datasette.absolute_url(\r\n request,\r\n path_with_format(\r\n request=request, format=\"csv\", extra_qs={\"_stream\": \"on\"}\r\n ),\r\n ),\r\n \"json_url\": datasette.absolute_url(\r\n request,\r\n path_with_format(\r\n request=request, format=\"json\", extra_qs={\"_shape\": \"array\"}\r\n ),\r\n ),\r\n \"json\": json,\r\n },\r\n )\r\n )\r\n```\r\nThis results in https://latest-with-plugins.datasette.io/github/issue_comments.Notebook showing `http://latest-with-plugins.datasette.io/github/issue_comments.Notebook?_format=json&_shape=array`", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/1179/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": null}
{"id": 808008305, "node_id": "MDU6SXNzdWU4MDgwMDgzMDU=", "number": 230, "title": "--sniff option for sniffing delimiters", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 8, "created_at": "2021-02-14T17:43:54Z", "updated_at": "2021-02-14T21:15:33Z", "closed_at": "2021-02-14T19:24:32Z", "author_association": "OWNER", "pull_request": null, "body": "> I just spotted that `csv.Sniffer` in the Python standard library has a `.has_header(sample)` method which detects if the first row appears to be a header or not, which is interesting. https://docs.python.org/3/library/csv.html#csv.Sniffer\r\n\r\n_Originally posted by @simonw in https://github.com/simonw/sqlite-utils/issues/228#issuecomment-778812050_", "repo": {"value": 140912432, "label": "sqlite-utils"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/sqlite-utils/issues/230/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"}
{"id": 811407131, "node_id": "MDExOlB1bGxSZXF1ZXN0NTc1OTQwMTkz", "number": 1232, "title": "--crossdb option for joining across databases", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 8, "created_at": "2021-02-18T19:48:50Z", "updated_at": "2021-02-18T22:09:13Z", "closed_at": "2021-02-18T22:09:12Z", "author_association": "OWNER", "pull_request": "simonw/datasette/pulls/1232", "body": "Refs #283. Still needs:\r\n\r\n- [x] Unit test for --crossdb queries\r\n- [x] Show warning on console if it truncates at ten databases (or on web interface)\r\n- [x] Show connected databases on the `/_memory` database page\r\n- [x] Documentation\r\n- [x] https://latest.datasette.io/ demo should demonstrate this feature", "repo": {"value": 107914493, "label": "datasette"}, "type": "pull", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/1232/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": 0, "state_reason": null}
{"id": 922099793, "node_id": "MDExOlB1bGxSZXF1ZXN0NjcxMDE0NzUx", "number": 273, "title": "sqlite-utils memory command for directly querying CSV/JSON data", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 8, "created_at": "2021-06-16T05:04:58Z", "updated_at": "2021-06-18T15:01:17Z", "closed_at": "2021-06-18T15:00:52Z", "author_association": "OWNER", "pull_request": "simonw/sqlite-utils/pulls/273", "body": "Refs #272. Initial implementation only does CSV data, still needs:\r\n\r\n- [x] Implement `--save`\r\n- [x] Add `--dump` to the documentation\r\n- [x] Add `--attach` example to the documentation\r\n- [x] Replace `:memory:` in documentation", "repo": {"value": 140912432, "label": "sqlite-utils"}, "type": "pull", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/sqlite-utils/issues/273/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": 0, "state_reason": null}
{"id": 935930820, "node_id": "MDU6SXNzdWU5MzU5MzA4MjA=", "number": 1387, "title": "absolute_url() behind a proxy assembles incorrect http://127.0.0.1:8001/ URLs", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 8, "created_at": "2021-07-02T16:58:25Z", "updated_at": "2021-07-02T17:58:23Z", "closed_at": "2021-07-02T17:33:05Z", "author_association": "OWNER", "pull_request": null, "body": "Reported in the wild on https://ilsweb.cincinnatilibrary.org/collection-analysis/current_collection-3d4a4b7/bib?_facet=bib_level_callnumber - the \"next page\" link links to https://127.0.0.1:8010/collection-analysis/current_collection-3d4a4b7/bib?_facet=bib_level_callnumber&_next=100\r\n\r\nThat installation uses `\"base_url\": \"/collection-analysis/\"`\r\n\r\nWeirdly all of the other links on that page - to facet results, sort orders, row permalinks etc - work fine. It's JUST the `next_url` one that is broken.\r\n\r\nAlso broken in their JSON: https://ilsweb.cincinnatilibrary.org/collection-analysis/current_collection-3d4a4b7/bib.json?_size=1 returns\r\n\r\n```json\r\n \"suggested_facets\": [],\r\n \"next\": \"1\",\r\n \"next_url\": \"https://127.0.0.1:8010/collection-analysis/current_collection-3d4a4b7/bib.json?_size=1&_next=1\",\r\n \"private\": false,\r\n```", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/1387/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"}
{"id": 956303470, "node_id": "MDU6SXNzdWU5NTYzMDM0NzA=", "number": 1406, "title": "Tests failing with FileNotFoundError in runner.isolated_filesystem", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 8, "created_at": "2021-07-30T00:39:00Z", "updated_at": "2021-07-31T18:56:35Z", "closed_at": "2021-07-31T18:56:35Z", "author_association": "OWNER", "pull_request": null, "body": "e.g. https://github.com/simonw/datasette/runs/3197141955\r\n\r\nI've seen this error before, but I don't yet have a good workaround for it.\r\n\r\n```\r\n @contextlib.contextmanager\r\n def isolated_filesystem(\r\n self, temp_dir: t.Optional[t.Union[str, os.PathLike]] = None\r\n ) -> t.Iterator[str]:\r\n \"\"\"A context manager that creates a temporary directory and\r\n changes the current working directory to it. This isolates tests\r\n that affect the contents of the CWD to prevent them from\r\n interfering with each other.\r\n \r\n :param temp_dir: Create the temporary directory under this\r\n directory. If given, the created directory is not removed\r\n when exiting.\r\n \r\n .. versionchanged:: 8.0\r\n Added the ``temp_dir`` parameter.\r\n \"\"\"\r\n> cwd = os.getcwd()\r\nE FileNotFoundError: [Errno 2] No such file or directory\r\n\r\n/opt/hostedtoolcache/Python/3.6.14/x64/lib/python3.6/site-packages/click/testing.py:466: FileNotFoundError\r\n=========================== short test summary info ============================\r\nFAILED tests/test_publish_cloudrun.py::test_publish_cloudrun_apt_get_install\r\nFAILED tests/test_publish_cloudrun.py::test_publish_cloudrun_extra_options[---setting force_https_urls on]\r\nFAILED tests/test_publish_cloudrun.py::test_publish_cloudrun_extra_options[--setting base_url /foo---setting base_url /foo --setting force_https_urls on]\r\nFAILED tests/test_publish_cloudrun.py::test_publish_cloudrun_extra_options[--setting force_https_urls off---setting force_https_urls off]\r\nFAILED tests/test_publish_heroku.py::test_publish_heroku_requires_heroku - Fi...\r\nFAILED tests/test_publish_heroku.py::test_publish_heroku_installs_plugin - Fi...\r\nFAILED tests/test_publish_heroku.py::test_publish_heroku - FileNotFoundError:...\r\nFAILED tests/test_publish_heroku.py::test_publish_heroku_plugin_secrets - Fil...\r\n================== 8 failed, 920 passed in 188.22s (0:03:08) ===================\r\n```", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/1406/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"}
{"id": 969855774, "node_id": "MDU6SXNzdWU5Njk4NTU3NzQ=", "number": 1432, "title": "Rename Datasette.__init__(config=) parameter to settings=", "user": {"value": 9599, "label": "simonw"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 8, "created_at": "2021-08-13T01:00:27Z", "updated_at": "2021-10-19T01:16:41Z", "closed_at": null, "author_association": "OWNER", "pull_request": null, "body": "> While I'm doing this I should rename this internal variable to avoid confusion in the future:\r\n>\r\n> https://github.com/simonw/datasette/blob/e837095ef35ae155b4c78cc9a8b7133a48c94f03/datasette/app.py#L203\r\n\r\n_Originally posted by @simonw in https://github.com/simonw/datasette/issues/1431#issuecomment-898072940_", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/1432/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": null}
{"id": 1077102934, "node_id": "I_kwDOCGYnMM5AM0lW", "number": 353, "title": "Allow passing a file of code to \"sqlite-utils convert\"", "user": {"value": 536941, "label": "fgregg"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 8, "created_at": "2021-12-10T18:06:14Z", "updated_at": "2021-12-11T01:38:29Z", "closed_at": "2021-12-11T01:09:39Z", "author_association": "CONTRIBUTOR", "pull_request": null, "body": "sqlite-utils is so nice, but the ergonomics of the multiline code in kind of tough. It's really hard (maybe impossible) to make the newlines play well with Makefiles.\r\n\r\nit would be great to write your code fragment in a separate file and direct it into the sqlite-utils\r\n\r\neither like\r\n\r\n```sqlite-utils convert my.db my_table my_column < custom_code.py```\r\n\r\nor\r\n\r\n```sqlite-utils convert my.db my_table my_column --custom-code=custom_code.py```\r\n\r\nThanks, as ever, for these great tools!", "repo": {"value": 140912432, "label": "sqlite-utils"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/sqlite-utils/issues/353/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"}
{"id": 1083657868, "node_id": "I_kwDOBm6k_c5Al06M", "number": 1565, "title": "Documented JavaScript variables on different templates made available for plugins", "user": {"value": 9599, "label": "simonw"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 8, "created_at": "2021-12-17T22:30:51Z", "updated_at": "2021-12-19T22:37:29Z", "closed_at": null, "author_association": "OWNER", "pull_request": null, "body": "While working on https://github.com/simonw/datasette-leaflet-freedraw/issues/10 I found myself writing this atrocity to figure out the SQL query used for a specific table page:\r\n\r\n```javascript\r\nlet innerSql = Array.from(document.getElementsByTagName(\"span\")).filter(\r\n el => el.innerText == \"View and edit SQL\"\r\n)[0].parentElement.getAttribute(\"title\")\r\n```\r\nThis is obviously bad - it's very brittle, and will break if I ever change the text on that link (like localizing it for example).\r\n\r\nInstead, I think pages like that one should have a block of script at the bottom something like this:\r\n```javascript\r\nwindow.datasette = window.datasette || {};\r\ndatasette.view_name = 'table';\r\ndatasette.table_sql = 'select * from ...';\r\n```", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/1565/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": null}
{"id": 1160034488, "node_id": "I_kwDOCGYnMM5FJLi4", "number": 411, "title": "Support for generated columns", "user": {"value": 25778, "label": "eyeseast"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 8, "created_at": "2022-03-04T20:41:33Z", "updated_at": "2022-03-11T22:32:43Z", "closed_at": null, "author_association": "CONTRIBUTOR", "pull_request": null, "body": "This is a fairly new feature -- SQLite version 3.31.0 (2020-01-22) -- that I, admittedly, haven't gotten to work yet. But it looks _incredibly_ useful: https://dgl.cx/2020/06/sqlite-json-support\r\n\r\nI'm not sure if this is an option on `add-column` or a separate command like `add-generated-column`. Either way, it needs an argument to populate it. It could be something like this:\r\n\r\n```sh\r\nsqlite-utils add-column data.db table-name generated --as 'json_extract(data, \"$.field\")' --virtual\r\n```\r\n\r\nMore here: https://www.sqlite.org/gencol.html", "repo": {"value": 140912432, "label": "sqlite-utils"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/sqlite-utils/issues/411/reactions\", \"total_count\": 2, \"+1\": 2, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": null}
{"id": 1161584460, "node_id": "I_kwDOBm6k_c5FPF9M", "number": 1651, "title": "Get rid of the no-longer necessary ?_format=json hack for tables called x.json", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": {"value": 3268330, "label": "Datasette 1.0"}, "comments": 8, "created_at": "2022-03-07T15:40:42Z", "updated_at": "2022-03-19T04:04:50Z", "closed_at": "2022-03-15T18:25:42Z", "author_association": "OWNER", "pull_request": null, "body": "Tidy up from:\r\n- #1439", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/1651/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"}
{"id": 1163369515, "node_id": "I_kwDOBm6k_c5FV5wr", "number": 1655, "title": "query result page is using 400mb of browser memory 40x size of html page and 400x size of csv data", "user": {"value": 536941, "label": "fgregg"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 8, "created_at": "2022-03-09T00:56:40Z", "updated_at": "2023-10-17T21:53:17Z", "closed_at": null, "author_association": "CONTRIBUTOR", "pull_request": null, "body": "[this page](https://labordata.bunkum.us/opdr-8335ea3?sql=with+most_recent_lu+as+%28%0D%0A++select%0D%0A++++*%0D%0A++from%0D%0A++++%28%0D%0A++++++select%0D%0A++++++++*%0D%0A++++++from%0D%0A++++++++lm_data%0D%0A++++++order+by%0D%0A++++++++f_num%2C%0D%0A++++++++receive_date+desc%0D%0A++++%29+t%0D%0A++group+by%0D%0A++++f_num%0D%0A%29%0D%0Aselect%0D%0A++aff_abbr+%7C%7C+coalesce%28%27+local+%27+%7C%7C+desig_num%2C+%27+%27+%7C%7C+unit_name%29+as+abbr_local_name%2C%0D%0A++coalesce%28%0D%0A++++regexp_match%28%27%28.*%3F%29%28%2C%3F+AFL-CIO%24%29%27%2C+union_name%29%2C%0D%0A++++regexp_match%28%27%28.*%3F%29%28+IND%24%29%27%2C+union_name%29%2C%0D%0A++++union_name%0D%0A++%29+%7C%7C+coalesce%28%27+local+%27+%7C%7C+desig_num%2C+%27+%27+%7C%7C+unit_name%29+as+full_local_name%2C%0D%0A++*%0D%0Afrom%0D%0A++most_recent_lu%0D%0Awhere+%28desig_num+IS+NOT+NULL+OR+unit_name+IS+NOT+NULL%29+AND+desig_name+%21%3D+%27HQ%27%0D%0Alimit%0D%0A++5000+offset+0)\r\n\r\nis using about 400 mb in firefox 97 on mac os x. if you download the html for the page, it's about 11mb and if you get the csv for the data its about 1mb.\r\n\r\nit's using over a 1G on chrome 99.\r\n\r\ni found this because, i was trying to figure out why editing the SQL was getting very slow.\r\n\r\n\r\n\r\n\r\n\r\n", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/1655/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": null}
{"id": 1170144879, "node_id": "I_kwDOBm6k_c5Fvv5v", "number": 1660, "title": "Refactor and simplify Datasette routing and views", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": {"value": 3268330, "label": "Datasette 1.0"}, "comments": 8, "created_at": "2022-03-15T19:56:56Z", "updated_at": "2022-03-21T19:19:12Z", "closed_at": "2022-03-21T19:19:01Z", "author_association": "OWNER", "pull_request": null, "body": "While working on:\n- https://github.com/simonw/datasette/issues/1657\n- https://github.com/simonw/datasette/issues/1439\n\nIt became very clear that the least maintainable part of Datasette at the moment is the way routing to the database, table and row views work - in particular the subclassing mechanism with BaseView and DataView, but also the complex variety of ways in which the URL routes capture different named regular expression groups.", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/1660/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"}
{"id": 1174655187, "node_id": "I_kwDOBm6k_c5GA9DT", "number": 1671, "title": "Filters fail to work correctly against calculated numeric columns returned by SQL views because type affinity rules do not apply", "user": {"value": 9308268, "label": "rayvoelker"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 8, "created_at": "2022-03-20T19:17:24Z", "updated_at": "2022-03-22T17:43:12Z", "closed_at": null, "author_association": "NONE", "pull_request": null, "body": "I found a strange behavior, and I'm not sure if it's related to views and boolean values perhaps, or if there's something else weird going on here, but I'll provide an example that may help show what I'm seeing happen.\r\n\r\n```bash\r\n#!/bin/bash\r\n\r\necho \"\\\"id\\\",\\\"expiration_date\\\"\r\n0,2018-01-04\r\n1,2019-01-05\r\n2,2020-01-06\r\n3,2021-01-07\r\n4,2022-01-08\r\n5,2023-01-09\r\n6,2024-01-10\r\n7,2025-01-11\r\n8,2026-01-12\r\n9,2027-01-13\r\n\" > test.csv\r\ncsvs-to-sqlite test.csv test.db\r\nsqlite-utils create-view --replace test.db test_view \"select id, expiration_date, case when julianday('NOW') >= julianday(expiration_date) then 1 else 0 end as has_expired FROM test\"\r\n```\r\n\r\n```bash\r\ndatasette test.db\r\n```\r\n![image](https://user-images.githubusercontent.com/9308268/159178745-9c6152f7-eac6-4bf9-bef5-a2d63d3ee13f.png)\r\n\r\n![image](https://user-images.githubusercontent.com/9308268/159178824-c8952137-270c-42a4-ad1c-f6ad2c51e499.png)\r\n\r\n![image](https://user-images.githubusercontent.com/9308268/159178877-23e00b36-443a-43ef-83e5-e0bdddd3fdcd.png)\r\n\r\n![image](https://user-images.githubusercontent.com/9308268/159178918-65922cc7-2514-4735-a72d-4904b99976d4.png)\r\n\r\nThanks again and let me know if you want me to provide anything else!", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/1671/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": null}
{"id": 1180427792, "node_id": "I_kwDOCGYnMM5GW-YQ", "number": 421, "title": "\"Error: near \"(\": syntax error\" when using sqlite-utils indexes CLI", "user": {"value": 24938923, "label": "learning4life"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 8, "created_at": "2022-03-25T07:12:51Z", "updated_at": "2022-04-13T22:41:59Z", "closed_at": "2022-04-13T22:41:59Z", "author_association": "NONE", "pull_request": null, "body": "This bug relates to https://github.com/simonw/sqlite-utils/issues/408#issuecomment-1066139147\r\n\r\n**New error when using CLI: \"sqlite-utils indexes global.db --table\"**\r\n\r\n```\r\n(app-root) sqlite-utils indexes global.db --table\r\nError: near \"(\": syntax error\r\n(app-root) sqlite-utils --version\r\nsqlite-utils, version 3.25.1\r\n(app-root) sqlite3 --version\r\n3.36.0 2021-06-18 18:36:39\r\n(app-root) python --version\r\nPython 3.8.11\r\n```\r\n\r\n\r\nDockerfile\r\n```\r\nFROM centos/python-38-centos7\r\n\r\nUSER root\r\n\r\nRUN yum update -y\r\nRUN yum upgrade -y\r\n\r\n\r\n# epel\r\nRUN yum -y install epel-release && yum clean all\r\n\r\n# SQLite\r\nRUN yum -y install zlib-devel geos geos-devel proj proj-devel freexl freexl-devel libxml2-devel \r\n\r\nWORKDIR /build/\r\nCOPY sqlite-autoconf-3360000.tar.gz ./\r\nRUN tar -zxf sqlite-autoconf-3360000.tar.gz\r\nWORKDIR /build/sqlite-autoconf-3360000\r\nRUN ./configure\r\nRUN make\r\nRUN make install\r\n\r\n# \r\nRUN /opt/app-root/bin/python3.8 -m pip install --upgrade pip\r\nRUN pip install sqlite-utils\r\n```", "repo": {"value": 140912432, "label": "sqlite-utils"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/sqlite-utils/issues/421/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"}
{"id": 1396948693, "node_id": "I_kwDOBm6k_c5TQ77V", "number": 1829, "title": "Table/database that is private due to inherited permissions does not show padlock", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 8, "created_at": "2022-10-04T23:14:16Z", "updated_at": "2022-10-24T02:23:46Z", "closed_at": "2022-10-24T02:11:37Z", "author_association": "OWNER", "pull_request": null, "body": "I noticed that a table page that is private because the database or instance is private, e.g. this one:\r\n\r\n
\r\n\r\nIs not displaying the padlock icon that indicates the table is not visible to the public.\r\n\r\n
\r\n\r\nSame issue for the database page too, which in this case is private due to `view-instance`.", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/1829/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"}
{"id": 1432013704, "node_id": "I_kwDOBm6k_c5VWsuI", "number": 1878, "title": "/db/table/-/upsert API", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": {"value": 8711695, "label": " Datasette 1.0a2"}, "comments": 8, "created_at": "2022-11-01T20:01:18Z", "updated_at": "2022-12-08T01:12:18Z", "closed_at": "2022-12-08T01:12:17Z", "author_association": "OWNER", "pull_request": null, "body": "Equivalent to `sqlite-utils upsert`: https://sqlite-utils.datasette.io/en/stable/python-api.html#upserting-data", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/1878/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"}
{"id": 1453813400, "node_id": "I_kwDOBm6k_c5Wp26Y", "number": 1901, "title": "Some plugins show \"home\" breadcrumbs twice in the top left", "user": {"value": 95570, "label": "bgrins"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 8, "created_at": "2022-11-17T18:44:58Z", "updated_at": "2022-11-18T07:22:37Z", "closed_at": "2022-11-18T07:02:56Z", "author_association": "CONTRIBUTOR", "pull_request": null, "body": "
\r\n", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/1901/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"}
{"id": 1473814539, "node_id": "PR_kwDOBm6k_c5EMVug", "number": 1931, "title": "/db/table/-/upsert", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": {"value": 8711695, "label": " Datasette 1.0a2"}, "comments": 8, "created_at": "2022-12-03T07:01:44Z", "updated_at": "2022-12-08T01:12:17Z", "closed_at": "2022-12-08T01:12:16Z", "author_association": "OWNER", "pull_request": "simonw/datasette/pulls/1931", "body": "Refs #1878\r\n\r\nStill todo:\r\n- [x] Support `\"return\": true` properly for upserts (with tests)\r\n- [x] Require both `insert-row` and `update-row` permissions\r\n- [x] Tests are going to need to cover both rowid-only and compound primary key tables, including all of the error states\r\n- [x] Documentation\r\n\r\n\r\n----\r\n:books: Documentation preview :books:: https://datasette--1931.org.readthedocs.build/en/1931/\r\n\r\n", "repo": {"value": 107914493, "label": "datasette"}, "type": "pull", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/1931/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": 0, "state_reason": null}
{"id": 1560982210, "node_id": "PR_kwDOBm6k_c5IvYKw", "number": 2008, "title": "array facet: don't materialize unnecessary columns", "user": {"value": 193185, "label": "cldellow"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 8, "created_at": "2023-01-28T19:33:40Z", "updated_at": "2023-01-29T18:17:40Z", "closed_at": null, "author_association": "CONTRIBUTOR", "pull_request": "simonw/datasette/pulls/2008", "body": "The presence of `inner.*` causes SQLite to materialize a row with all the columns. Those columns will be discarded later.\r\n\r\nInstead, we can select only the column we'll use. This lets SQLite's optimizer realize that the other columns in the CTE definition aren't needed.\r\n\r\nOn a test table with 278K rows, 98K of which had an array, this speeds up the facet calculation from 4 sec to 1 sec.\r\n\r\n\r\n----\n:books: Documentation preview :books:: https://datasette--2008.org.readthedocs.build/en/2008/\n\r\n", "repo": {"value": 107914493, "label": "datasette"}, "type": "pull", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/2008/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": 0, "state_reason": null}
{"id": 1726531350, "node_id": "I_kwDOBm6k_c5m6McW", "number": 2079, "title": "Datasette should serve Access-Control-Max-Age", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 8, "created_at": "2023-05-25T21:50:50Z", "updated_at": "2023-05-25T22:56:28Z", "closed_at": "2023-05-25T22:08:35Z", "author_association": "OWNER", "pull_request": null, "body": "Currently the CORS headers served are:\r\n\r\nhttps://github.com/simonw/datasette/blob/9584879534ff0556e04e4c420262972884cac87b/datasette/utils/__init__.py#L1139-L1143\r\n\r\nServing `Access-Control-Max-Age: 600` would allow browsers to cache that for 10 minutes, avoiding additional CORS pre-flight OPTIONS requests during that time.", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/2079/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"}
{"id": 1781530343, "node_id": "I_kwDOBm6k_c5qL_7n", "number": 2093, "title": "Proposal: Combine settings, metadata, static, etc. into a single `datasette.yaml` File", "user": {"value": 15178711, "label": "asg017"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 8, "created_at": "2023-06-29T21:18:23Z", "updated_at": "2023-09-11T20:19:32Z", "closed_at": null, "author_association": "CONTRIBUTOR", "pull_request": null, "body": "Very often I get tripped up when trying to configure my Datasette instances. For example: if I want to change the port my app listen too, do I do that with a CLI flag, a `--setting` flag, inside `metadata.json`, or an env var? If I want to up the time limit of SQL statements, is that under `metadata.json` or a setting? Where does my plugin configuration go?\r\n\r\nNormally I need to look it up in Datasette docs, and I quickly find my answer, but the number of places where \"config\" goes it overwhelming.\r\n\r\n- Flat CLI flags like `--port`, `--host`, `--cors`, etc.\r\n- `--setting`, like `default_page_size`, `sql_time_limit_ms` etc\r\n- Inside `metadata.json`, including plugin configuration\r\n\r\nTypically my Datasette deploys are extremely long shell commands, with multiple `--setting` and other CLI flags.\r\n\r\n## Proposal: Consolidate all \"config\" into `datasette.toml`\r\n\r\nI propose that we add a new `datasette.toml` that combines \"settings\", \"metadata\", and other common CLI flags like `--port` and `--cors` into a single file. It would be similar to \"Cargo.toml\" in Rust projects, \"package.json\" in Node projects, and \"pyproject.toml\" in Python, etc.\r\n\r\nA sample of what it could look like:\r\n\r\n```toml\r\n# \"top level\" configuration that are currently CLI flags on `datasette serve`\r\n[config]\r\nport = 8020\r\nhost = \"0.0.0.0\"\r\ncors = true\r\n\r\n# replaces multiple `--setting` flags\r\n[settings]\r\nbase_url = \"/app/datasette/\"\r\ndefault_allow_sql = true\r\nsql_time_limit_ms = 3500\r\n\r\n# replaces `metadata.json`.\r\n# The contents of datasette-metadata.json could be defined in this file instead, but supporting separate files is nice (since those are easy to machine-generate)\r\n[metadata]\r\ninclude=\"./datasette-metadata.json\"\r\n\r\n# plugin-specific \r\n[plugins]\r\n[plugins.datasette-auth-github]\r\nclient_id = {env = \"DATASETTE_AUTH_GITHUB_CLIENT_ID\"}\r\nclient_secret = {env = \"GITHUB_CLIENT_SECRET\"}\r\n\r\n[plugins.datasette-cluster-map]\r\n\r\nlatitude_column = \"lat\"\r\nlongitude_column = \"lon\"\r\n```\r\n\r\n## Pros\r\n- Instead of multiple files and CLI flags, everything could be in one tidy file\r\n- Editing config in a separate file is easier than editing CLI flags, since you don't have to kill a process + edit a command every time\r\n- New users will know \"just edit my `datasette.toml` instead of needing to learn metadata + settings + CLI flags\r\n- Better dev experience for multiple environment. For example, could have `datasette -c datasette-dev.toml` for local dev environments (enables SQL, debug plugins, long timeouts, etc.), and a `datasette -c datasette-prod.toml` for \"production\" (lower timeouts, less plugins, monitoring plugins, etc.)\r\n\r\n## Cons\r\n- Yet another config-management system. Now Datasette users will need to know about metadata, settings, CLI flags, _and_ `datasette.toml`. However with enough documentation + announcements + examples, I think we can get ahead of it.\r\n- If toml is chosen, would need to add a toml parser for Python version <3.11\r\n- Multiple sources of config require priority. For example: Would `--setting default_allow_sql off` override the value inside `[settings]`? What about `--port`? \r\n\r\n## Other Notes\r\n\r\n### Toml\r\n\r\nI chose toml over json because toml supports comments. I chose toml over yaml because Python 3.11 has builtin support for it. I also find toml easier to work with since it doesn't have the odd \"gotchas\" that YAML has (\"ex `3.10` resolving to `3.1`, Norway `NO` resolving to `false`, etc.). It also mimics `pyproject.toml` which is nice. Happy to change my mind about this however\r\n\r\n\r\n### Plugin config will be difficult\r\n\r\nPlugin config is currently in `metadata.json` in two places:\r\n\r\n1. Top level, under `\"plugins.[plugin-name]\"`. This fits well into `datasette.toml` as `[plugins.plugin-name]`\r\n2. Table level, under `\"databases.[db-name].tables.[table-name].plugins.[plugin-name]`. This doesn't fit that well into `datasette.toml`, unless it's nested under `[metadata]`?\r\n\r\n### Extensions, static, one-off plugins?\r\n\r\nWe could also include equivalents of `--plugins-dir`, `--static`, and `--load-extension` into `datasette.toml`, but I'd imagine there's a few security concerns there to think through. \r\n\r\n\r\n### Explicitly list with plugins to use?\r\n\r\nI believe Datasette by default will load all install plugins on startup, but maybe `datasette.toml` can specify a list of plugins to use? For example, a dev version of `datasette.toml` can specify `datasette-pretty-traces`, but the prod version can leave it out", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/2093/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": null}
{"id": 1865281760, "node_id": "PR_kwDOBm6k_c5Ys3C5", "number": 2154, "title": "Cascade for restricted token view-table/view-database/view-instance operations", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 8, "created_at": "2023-08-24T14:24:23Z", "updated_at": "2023-08-29T16:32:35Z", "closed_at": "2023-08-29T16:32:34Z", "author_association": "OWNER", "pull_request": "simonw/datasette/pulls/2154", "body": "Refs:\r\n- #2102\r\n\r\nAlso includes a prototype implementation of `--actor option` which I'm using for testing this, from:\r\n- #2153\r\n\r\n\r\n----\n:books: Documentation preview :books:: https://datasette--2154.org.readthedocs.build/en/2154/\n\r\n", "repo": {"value": 107914493, "label": "datasette"}, "type": "pull", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/2154/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": 0, "state_reason": null}
{"id": 1907695234, "node_id": "I_kwDOBm6k_c5xtR6C", "number": 2194, "title": "Deploy failing with \"plugins/alternative_route.py: Not a directory\"", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 8, "created_at": "2023-09-21T20:17:49Z", "updated_at": "2023-09-21T22:08:19Z", "closed_at": "2023-09-21T22:08:19Z", "author_association": "OWNER", "pull_request": null, "body": "https://github.com/simonw/datasette/actions/runs/6266449018/job/17017460074\r\n\r\n
\r\n\r\nThis is a bit of a mystery, I don't think I've changed anything recently that could have broken this.", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/2194/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"}