{"id": 710650633, "node_id": "MDU6SXNzdWU3MTA2NTA2MzM=", "number": 979, "title": "Default table view JSON should include CREATE TABLE", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 3, "created_at": "2020-09-28T23:54:58Z", "updated_at": "2023-01-09T15:32:39Z", "closed_at": "2023-01-09T15:32:22Z", "author_association": "OWNER", "pull_request": null, "body": "https://latest.datasette.io/fixtures/facetable.json doesn't currently include the CREATE TABLE statement for the page, even though it's available on the HTML version at https://latest.datasette.io/fixtures/facetable", "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/979/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": 1522778923, "node_id": "I_kwDOBm6k_c5aw8Mr", "number": 1978, "title": "Document datasette.urls.row and row_blob", "user": {"value": 25778, "label": "eyeseast"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 2, "created_at": "2023-01-06T15:45:51Z", "updated_at": "2023-01-09T14:30:00Z", "closed_at": "2023-01-09T14:30:00Z", "author_association": "CONTRIBUTOR", "pull_request": null, "body": "These are in the codebase but not in documentation. I think everything else in this class is documented.\r\n\r\n```python\r\nclass Urls:\r\n ...\r\n def row(self, database, table, row_path, format=None):\r\n path = f\"{self.table(database, table)}/{row_path}\"\r\n if format is not None:\r\n path = path_with_format(path=path, format=format)\r\n return PrefixedUrlString(path)\r\n\r\n def row_blob(self, database, table, row_path, column):\r\n return self.table(database, table) + \"/{}.blob?_blob_column={}\".format(\r\n row_path, urllib.parse.quote_plus(column)\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/1978/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "not_planned"} {"id": 1522552817, "node_id": "PR_kwDOBm6k_c5G0XxH", "number": 1977, "title": "Bump sphinx from 5.3.0 to 6.1.1", "user": {"value": 49699333, "label": "dependabot[bot]"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 2, "created_at": "2023-01-06T13:02:12Z", "updated_at": "2023-01-09T13:06:17Z", "closed_at": "2023-01-09T13:06:14Z", "author_association": "CONTRIBUTOR", "pull_request": "simonw/datasette/pulls/1977", "body": "Bumps [sphinx](https://github.com/sphinx-doc/sphinx) from 5.3.0 to 6.1.1.\n
\nRelease notes\n

Sourced from sphinx's releases.

\n
\n

v6.1.1

\n

Changelog: https://www.sphinx-doc.org/en/master/changes.html

\n

v6.1.0

\n

Changelog: https://www.sphinx-doc.org/en/master/changes.html

\n

v6.0.1

\n

Changelog: https://www.sphinx-doc.org/en/master/changes.html

\n

v6.0.0

\n

Changelog: https://www.sphinx-doc.org/en/master/changes.html

\n

v6.0.0b2

\n

Changelog: https://www.sphinx-doc.org/en/master/changes.html

\n

v6.0.0b1

\n

Changelog: https://www.sphinx-doc.org/en/master/changes.html

\n
\n
\n
\nChangelog\n

Sourced from sphinx's changelog.

\n
\n

Release 6.1.1 (released Jan 05, 2023)

\n

Bugs fixed

\n\n

Release 6.1.0 (released Jan 05, 2023)

\n

Dependencies

\n\n

Incompatible changes

\n\n

Deprecated

\n\n\n
\n

... (truncated)

\n
\n
\nCommits\n\n
\n
\n\n\n[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=sphinx&package-manager=pip&previous-version=5.3.0&new-version=6.1.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)\n\nDependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.\n\n[//]: # (dependabot-automerge-start)\n[//]: # (dependabot-automerge-end)\n\n---\n\n
\nDependabot commands and options\n
\n\nYou can trigger Dependabot actions by commenting on this PR:\n- `@dependabot rebase` will rebase this PR\n- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it\n- `@dependabot merge` will merge this PR after your CI passes on it\n- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it\n- `@dependabot cancel merge` will cancel a previously requested merge and block automerging\n- `@dependabot reopen` will reopen this PR if it is closed\n- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually\n- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)\n- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)\n- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)\n\n\n
\r\n\r\n\r\n----\n:books: Documentation preview :books:: https://datasette--1977.org.readthedocs.build/en/1977/\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/1977/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": 1524076587, "node_id": "I_kwDOBm6k_c5a15Ar", "number": 1979, "title": "More useful error message if enable_load_extension is not available", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 5, "created_at": "2023-01-07T19:13:19Z", "updated_at": "2023-01-08T00:21:23Z", "closed_at": "2023-01-08T00:21:23Z", "author_association": "OWNER", "pull_request": null, "body": "I get this from:\r\n\r\n datasette --load-extension spatialite --get /-/versions.json\r\n\r\n```\r\n File \"/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/datasette/app.py\", line 614, in _prepare_connection\r\n conn.enable_load_extension(True)\r\nAttributeError: 'sqlite3.Connection' object has no attribute 'enable_load_extension'\r\n```\r\nIt would be useful if Datasette caught this error and output something more friendly.", "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/1979/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": 957310278, "node_id": "MDU6SXNzdWU5NTczMTAyNzg=", "number": 1409, "title": "`default_allow_sql` setting (a re-imagining of the old `allow_sql` setting)", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": {"value": 3268330, "label": "Datasette 1.0"}, "comments": 10, "created_at": "2021-07-31T19:48:56Z", "updated_at": "2023-01-07T18:06:01Z", "closed_at": "2023-01-05T00:51:31Z", "author_association": "OWNER", "pull_request": null, "body": "In 49d6d2f7b0f6cb02e25022e1c9403811f1fa0a7c as part of #813 I removed the `allow_sql` setting - on the basis that users could disable the ability to execute custom SQL queries using the new permission system instead.\r\n\r\nI don't think this was the right decision. Disabling custom SQL is an important security capability, and explaining how to do it using permissions is significantly more complex than letting people know they can add `--setting allow_sql off`.\r\n\r\nSo I want to bring that setting back - maybe with a different, better name - and have it modify the default for that option if the permissions system doesn't have an opinion.\r\n\r\nThat way people can still use the setting but then use permissions to allow specific signed-in users access to execute SQL.", "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/1409/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": 1520712722, "node_id": "PR_kwDOBm6k_c5GuDBN", "number": 1976, "title": "Bump sphinx from 5.3.0 to 6.1.0", "user": {"value": 49699333, "label": "dependabot[bot]"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 2, "created_at": "2023-01-05T13:02:37Z", "updated_at": "2023-01-06T13:02:17Z", "closed_at": "2023-01-06T13:02:15Z", "author_association": "CONTRIBUTOR", "pull_request": "simonw/datasette/pulls/1976", "body": "Bumps [sphinx](https://github.com/sphinx-doc/sphinx) from 5.3.0 to 6.1.0.\n
\nRelease notes\n

Sourced from sphinx's releases.

\n
\n

v6.1.0

\n

Changelog: https://www.sphinx-doc.org/en/master/changes.html

\n

v6.0.1

\n

Changelog: https://www.sphinx-doc.org/en/master/changes.html

\n

v6.0.0

\n

Changelog: https://www.sphinx-doc.org/en/master/changes.html

\n

v6.0.0b2

\n

Changelog: https://www.sphinx-doc.org/en/master/changes.html

\n

v6.0.0b1

\n

Changelog: https://www.sphinx-doc.org/en/master/changes.html

\n
\n
\n
\nChangelog\n

Sourced from sphinx's changelog.

\n
\n

Release 6.1.0 (released Jan 05, 2023)

\n

Dependencies

\n\n

Incompatible changes

\n\n

Deprecated

\n\n

Features added

\n\n\n
\n

... (truncated)

\n
\n
\nCommits\n\n
\n
\n\n\n[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=sphinx&package-manager=pip&previous-version=5.3.0&new-version=6.1.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)\n\nDependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.\n\n[//]: # (dependabot-automerge-start)\n[//]: # (dependabot-automerge-end)\n\n---\n\n
\nDependabot commands and options\n
\n\nYou can trigger Dependabot actions by commenting on this PR:\n- `@dependabot rebase` will rebase this PR\n- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it\n- `@dependabot merge` will merge this PR after your CI passes on it\n- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it\n- `@dependabot cancel merge` will cancel a previously requested merge and block automerging\n- `@dependabot reopen` will reopen this PR if it is closed\n- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually\n- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)\n- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)\n- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)\n\n\n
\r\n\r\n\r\n----\n:books: Documentation preview :books:: https://datasette--1976.org.readthedocs.build/en/1976/\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/1976/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": 1516376583, "node_id": "PR_kwDOBm6k_c5GfPJL", "number": 1974, "title": "Bump sphinx from 5.3.0 to 6.0.0", "user": {"value": 49699333, "label": "dependabot[bot]"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 2, "created_at": "2023-01-02T13:04:26Z", "updated_at": "2023-01-05T13:02:42Z", "closed_at": "2023-01-05T13:02:40Z", "author_association": "CONTRIBUTOR", "pull_request": "simonw/datasette/pulls/1974", "body": "Bumps [sphinx](https://github.com/sphinx-doc/sphinx) from 5.3.0 to 6.0.0.\n
\nRelease notes\n

Sourced from sphinx's releases.

\n
\n

v6.0.0

\n

Changelog: https://www.sphinx-doc.org/en/master/changes.html

\n

v6.0.0b2

\n

Changelog: https://www.sphinx-doc.org/en/master/changes.html

\n

v6.0.0b1

\n

Changelog: https://www.sphinx-doc.org/en/master/changes.html

\n
\n
\n
\nChangelog\n

Sourced from sphinx's changelog.

\n
\n

Release 6.0.0 (released Dec 29, 2022)

\n

Dependencies

\n\n

Incompatible changes

\n\n

Features added

\n\n
\n

... (truncated)

\n
\n
\nCommits\n\n
\n
\n\n\n[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=sphinx&package-manager=pip&previous-version=5.3.0&new-version=6.0.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)\n\nDependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.\n\n[//]: # (dependabot-automerge-start)\n[//]: # (dependabot-automerge-end)\n\n---\n\n
\nDependabot commands and options\n
\n\nYou can trigger Dependabot actions by commenting on this PR:\n- `@dependabot rebase` will rebase this PR\n- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it\n- `@dependabot merge` will merge this PR after your CI passes on it\n- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it\n- `@dependabot cancel merge` will cancel a previously requested merge and block automerging\n- `@dependabot reopen` will reopen this PR if it is closed\n- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually\n- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)\n- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)\n- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)\n\n\n
\r\n\r\n\r\n----\n:books: Documentation preview :books:: https://datasette--1974.org.readthedocs.build/en/1974/\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/1974/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": 1515182998, "node_id": "I_kwDOBm6k_c5aT9uW", "number": 1970, "title": "Path \"None\" in _internal database table", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 2, "created_at": "2022-12-31T18:51:05Z", "updated_at": "2022-12-31T19:22:58Z", "closed_at": "2022-12-31T18:52:49Z", "author_association": "OWNER", "pull_request": null, "body": "See https://latest.datasette.io/_internal/databases (after https://latest.datasette.io/login-as-root)\r\n\r\n\"image\"\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/1970/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": 1503010009, "node_id": "PR_kwDOBm6k_c5FyT3c", "number": 1967, "title": "Add favicon to documentation", "user": {"value": 1839645, "label": "choldgraf"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 2, "created_at": "2022-12-19T14:01:04Z", "updated_at": "2022-12-31T19:15:51Z", "closed_at": "2022-12-31T19:00:31Z", "author_association": "CONTRIBUTOR", "pull_request": "simonw/datasette/pulls/1967", "body": "I've been browsing the datasette documentation and found it hard to quickly locate tabs with many of them open, because it does not ship a favicon. So this PR:\r\n\r\n- Grabs the favicon `.png` from datasette itself[^1]\r\n- Adds it to the `_static/` folder\r\n- Sets `html_favicon` to load it in the docs\r\n\r\n[^1]: I also learned that Chrome can fetch favicons as an internal service! See `chrome://favicon/https://datasette.io/tools/github-to-sqlite`.\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/1967/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": 1501900064, "node_id": "I_kwDOBm6k_c5ZhS0g", "number": 1966, "title": "Broken link to live demo in Getting started docs", "user": {"value": 7551922, "label": "lbellomo"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 1, "created_at": "2022-12-18T13:17:00Z", "updated_at": "2022-12-31T19:15:19Z", "closed_at": "2022-12-31T19:15:10Z", "author_association": "NONE", "pull_request": null, "body": "The link in [Play with a live demo in Getting started](https://github.com/simonw/datasette/blob/main/docs/getting_started.rst#play-with-a-live-demo) to [https://fivethirtyeight.datasettes.com/fivethirtyeight](https://fivethirtyeight.datasettes.com/fivethirtyeight) is broken and the datasette is no longer working (maybe due to the end of the free tier).", "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/1966/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": 1515186569, "node_id": "I_kwDOBm6k_c5aT-mJ", "number": 1972, "title": "Fix Sphinx warning about extlink extension", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 0, "created_at": "2022-12-31T19:12:04Z", "updated_at": "2022-12-31T19:13:26Z", "closed_at": "2022-12-31T19:13:26Z", "author_association": "OWNER", "pull_request": null, "body": "```\r\n[sphinx-autobuild] > sphinx-build -b html /Users/simon/Dropbox/Development/datasette/docs /Users/simon/Dropbox/Development/datasette/docs/_build\r\nRunning Sphinx v5.3.0\r\nloading pickled environment... done\r\nWARNING: extlinks: Sphinx-6.0 will require a caption string to contain exactly one '%s' and all other '%' need to be escaped as '%%'.\r\n```\r\n\r\n_Originally posted by @simonw in https://github.com/simonw/datasette/issues/1971#issuecomment-1368266904_\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/1972/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": 1000275035, "node_id": "PR_kwDOCGYnMM4r7n-9", "number": 327, "title": "Extract expand: Support JSON Arrays", "user": {"value": 101753, "label": "phaer"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 0, "created_at": "2021-09-19T10:34:30Z", "updated_at": "2022-12-29T09:05:36Z", "closed_at": "2022-12-29T09:05:36Z", "author_association": "NONE", "pull_request": "simonw/sqlite-utils/pulls/327", "body": "Hi,\r\n\r\nI needed to extract data in JSON Arrays to normalize data imports. I've quickly hacked the following together based on #241 which refers to #239 where you, @simonw, wrote:\r\n\r\n> Could this handle lists of objects too? That would be pretty amazing - if the column has a [{...}, {...}] list in it could turn that into a many-to-many.\r\n\r\nThey way this works in my work is that many-to-many relationships are created for anything that maps to an dictionary in a list, and many-to-one relations for everything else (assumed to be scalar values). Not sure what the best approach here would be? Are many-to-one relationships are at all useful here?\r\n\r\nWhat do you think about this approach? I could try to add it to the cli interface and documentation if wanted.\r\n\r\nThanks for this awesome piece of software in any case! :sun_with_face: ", "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/327/reactions\", \"total_count\": 1, \"+1\": 1, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": 0, "state_reason": null} {"id": 1501843596, "node_id": "PR_kwDOBm6k_c5FuaJm", "number": 1965, "title": "Detect server start/stop more reliably.", "user": {"value": 11321, "label": "janl"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 2, "created_at": "2022-12-18T10:03:42Z", "updated_at": "2022-12-20T19:08:26Z", "closed_at": "2022-12-18T16:01:51Z", "author_association": "CONTRIBUTOR", "pull_request": "simonw/datasette/pulls/1965", "body": "This is useful, especially in testing, since your test hosts might not reliabliy start the server within two seconds, so we do a definite check before progressing.\r\n\r\nBy the same token, after `kill $server_pid` wait for the pid to be gone from the process list.\r\n\r\nSince now the script can end prematurely, I also added a cleanup function to make sure the temporary certs are removed in any case.\r\n\r\nn.b. this could also be done with the use of `trap 'fn' ERR` but that felt like a bit too much magic for this short a script.\r\n\r\n\r\n----\n:books: Documentation preview :books:: https://datasette--1965.org.readthedocs.build/en/1965/\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/1965/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": 1496652622, "node_id": "I_kwDOBm6k_c5ZNRtO", "number": 1955, "title": "invoke_startup() is not run in some conditions, e.g. gunicorn/uvicorn workers, breaking lots of things", "user": {"value": 32839123, "label": "Rik-de-Kort"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 36, "created_at": "2022-12-14T13:39:56Z", "updated_at": "2022-12-19T04:34:16Z", "closed_at": "2022-12-18T02:45:18Z", "author_association": "NONE", "pull_request": null, "body": "In the past (pre-september 14, #1809) I had a running deployment of Datasette on Azure WebApps by emulating the call in cli.py to Gunicorn: `gunicorn -w 2 -k uvicorn.workers.UvicornWorker app:app`.\r\n\r\nMy most recent deployment, however, fails loudly by shouting that `Datasette.invoke_startup()` was not called. It does not seem to be possible to call `invoke_startup` when running using a uvicorn command directly like this (I've reproduced this locally using `uvicorn`). Two candidates that I have tried:\r\n* Uvicorn has a `--factory` option, but the app factory has to be synchronous, so no `await invoke_startup` there\r\n* `asyncio.get_event_loop().run_until_complete` is also not an option because `uvicorn` already has the event loop running.\r\n\r\nOne additional option is:\r\n* Use Gunicorn's [server hooks](https://docs.gunicorn.org/en/stable/settings.html#server-hooks) to call `invoke_startup`. These are also synchronous, but I might be able to get ahead of the event loop starting here.\r\n\r\nIn my current deployment setup, it does not appear to be possible to use `datasette serve` directly, so I'm stuck either\r\n* Trying to rework my complete deployment setup, for instance, using Azure functions as described [here](https://github.com/simonw/azure-functions-datasette))\r\n* Or dig into the ASGI spec and write a wrapper for the sole purpose of launching Datasette using a direct Uvicorn invocation.\r\n\r\nQuestions for the maintainers:\r\n* Is this intended behaviour/will not support/etc.? If so, I'd be happy to add a PR with a couple lines in the documentation.\r\n* if this is not intended behaviour, what is a good way to fix it? I could have a go at the ASGI spec thing (I think the Azure Functions thing is related) and provide a PR with the wrapper here, but I'm all ears!\r\n\r\nAlmost forgot, minimal reproducer:\r\n```python\r\nfrom datasette import Datasette\r\n\r\nds = Datasette(files=['./global-power-plants.db'])]\r\napp = ds.app()\r\n```\r\n\r\nSave as app.py in the same folder as global-power-plants.db, and then try running\r\n`uvicorn app:app`.\r\n\r\nOpening the resulting Datasette instance in the browser will show the error message.", "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/1955/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": 1306984363, "node_id": "I_kwDOBm6k_c5N5v-r", "number": 1771, "title": "minor a11y: `", "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/1939/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": 1486011362, "node_id": "PR_kwDOBm6k_c5E3XqB", "number": 1940, "title": "register_permissions() plugin hook", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": {"value": 8711695, "label": " Datasette 1.0a2"}, "comments": 6, "created_at": "2022-12-09T05:09:28Z", "updated_at": "2022-12-13T02:05:55Z", "closed_at": "2022-12-13T02:05:54Z", "author_association": "OWNER", "pull_request": "simonw/datasette/pulls/1940", "body": "Refs #1939\r\n\r\nFrom this comment: https://github.com/simonw/datasette/issues/1939#issuecomment-1343872168\r\n\r\n- [x] Unit test for the registration plugin hook itself\r\n- [x] Use them in `check_permission_actions_are_documented` test in `conftest.py`\r\n- [x] Add description field to `Permissions` (and update tests and docs)\r\n- [x] Documentation for `datasette.permissions` dictionary\r\n- [x] If no `default=` provided in call to `permission_allowed()` then use default from `datasette.permissions` list\r\n- [x] Remove `default=` from a bunch of places\r\n- [x] Throw an error if two permissions are registered with the same name or abbreviation (but other attributes differ)\r\n- [x] Update authentication and permissions documentation to explain that permissions are now registered and have a registered default\r\n\r\n\r\n----\r\n:books: Documentation preview :books:: https://datasette--1940.org.readthedocs.build/en/1940/\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/1940/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": 1487764628, "node_id": "I_kwDOCGYnMM5YrXyU", "number": 518, "title": "flake8 ValueError: Error code '#' supplied to 'extend-ignore' option...", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 0, "created_at": "2022-12-10T01:30:24Z", "updated_at": "2022-12-10T01:36:46Z", "closed_at": "2022-12-10T01:36:46Z", "author_association": "OWNER", "pull_request": null, "body": "> `Error code '#' supplied to 'extend-ignore' option does not match '^[A-Z]{1,3}[0-9]{0,3}$'`\r\n\r\nhttps://github.com/simonw/sqlite-utils/actions/runs/3662011265/jobs/6190770361\r\n\r\nI think from this:\r\n\r\nhttps://github.com/simonw/sqlite-utils/blob/e660635cea6c32f4022818380b1e1ee88e7c93a6/setup.cfg#L1-L3\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/518/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": 1487757143, "node_id": "I_kwDOCGYnMM5YrV9X", "number": 517, "title": "Drop support for Python 3.6", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 1, "created_at": "2022-12-10T01:23:31Z", "updated_at": "2022-12-10T01:36:36Z", "closed_at": "2022-12-10T01:36:36Z", "author_association": "OWNER", "pull_request": null, "body": "CI has started failing for Python 3.6: https://github.com/simonw/sqlite-utils/actions/runs/3576322798\r\n\r\n\"image\"\r\n\r\nIt's fixable by swiching away from `ubuntu-latest` according to:\r\n\r\n- https://github.com/actions/setup-python/issues/355#issuecomment-1335042510\r\n\r\nBut https://endoflife.date/python says that 3.6 end of life was almost 6 years ago, and end of security support nearly 1 year ago.\r\n\r\nSo I'm OK dropping support entirely - Python 3.6 users will still be able to install version 3.30, just not any releases that come next.", "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/517/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": 1434094365, "node_id": "I_kwDOBm6k_c5Veosd", "number": 1881, "title": "Tool for simulating permission checks against actors", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 9, "created_at": "2022-11-03T04:43:20Z", "updated_at": "2022-12-09T01:38:21Z", "closed_at": "2022-11-04T00:13:05Z", "author_association": "OWNER", "pull_request": null, "body": "In working on this issue:\r\n- #1855\r\n\r\nI realized that if I'm going to make actors more complicated (the proposed `_r` key for additional restricted permissions) I really need an interactive tool for simulating these checks, similar to the https://latest.datasette.io/-/allow-debug tool.", "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/1881/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": 1473664029, "node_id": "PR_kwDOBm6k_c5ELz0u", "number": 1930, "title": "Typo in JSON API `Updating a row` documentation", "user": {"value": 3556, "label": "davidbgk"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 2, "created_at": "2022-12-03T02:22:31Z", "updated_at": "2022-12-08T21:12:35Z", "closed_at": "2022-12-08T21:12:35Z", "author_association": "CONTRIBUTOR", "pull_request": "simonw/datasette/pulls/1930", "body": "\r\n\r\n\r\n----\n:books: Documentation preview :books:: https://datasette--1930.org.readthedocs.build/en/1930/\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/1930/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": 1481875485, "node_id": "PR_kwDOBm6k_c5EouZs", "number": 1935, "title": "Bump furo from 2022.9.29 to 2022.12.7", "user": {"value": 49699333, "label": "dependabot[bot]"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 1, "created_at": "2022-12-07T13:02:57Z", "updated_at": "2022-12-08T21:12:08Z", "closed_at": "2022-12-08T21:12:07Z", "author_association": "CONTRIBUTOR", "pull_request": "simonw/datasette/pulls/1935", "body": "Bumps [furo](https://github.com/pradyunsg/furo) from 2022.9.29 to 2022.12.7.\n
\nChangelog\n

Sourced from furo's changelog.

\n
\n

Changelog

\n\n

2022.12.07 -- Reverent Raspberry

\n\n

2022.09.29 -- Quaint Quartz

\n\n

2022.09.15 -- Pragmatic Pistachio

\n\n

2022.06.21 -- Opulent Opal

\n\n

2022.06.04.1 -- Naughty Nickel bugfix

\n\n

2022.06.04 -- Naughty Nickel

\n\n
\n

... (truncated)

\n
\n
\nCommits\n\n
\n
\n\n\n[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=furo&package-manager=pip&previous-version=2022.9.29&new-version=2022.12.7)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)\n\nDependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.\n\n[//]: # (dependabot-automerge-start)\n[//]: # (dependabot-automerge-end)\n\n---\n\n
\nDependabot commands and options\n
\n\nYou can trigger Dependabot actions by commenting on this PR:\n- `@dependabot rebase` will rebase this PR\n- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it\n- `@dependabot merge` will merge this PR after your CI passes on it\n- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it\n- `@dependabot cancel merge` will cancel a previously requested merge and block automerging\n- `@dependabot reopen` will reopen this PR if it is closed\n- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually\n- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)\n- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)\n- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)\n\n\n
\r\n\r\n\r\n----\n:books: Documentation preview :books:: https://datasette--1935.org.readthedocs.build/en/1935/\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/1935/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": 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": 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": 1473659191, "node_id": "I_kwDOBm6k_c5X1kE3", "number": 1929, "title": "Incorrect link from the API explorer to the JSON API documentation", "user": {"value": 3556, "label": "davidbgk"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 4, "created_at": "2022-12-03T02:08:58Z", "updated_at": "2022-12-06T19:36:23Z", "closed_at": "2022-12-06T19:34:20Z", "author_association": "CONTRIBUTOR", "pull_request": null, "body": "I installed `datasette==1.0a1`.\r\n\r\nWhen I go to http://127.0.0.1:8001/-/api I have a link: `Use this tool to try out the [Datasette API](https://docs.datasette.io/en/1.0a1/json_api.html).` but that documentation page does not exist.\r\n\r\nI'm not sure where it has to be fixed, should it link to the stable page https://docs.datasette.io/en/stable/json_api.html , the latest one https://docs.datasette.io/en/latest/json_api.html#the-json-write-api or would it be more appropriated to deploy documentation for the `1.0a1` version?", "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/1929/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": 1473481262, "node_id": "I_kwDOBm6k_c5X04ou", "number": 1928, "title": "Hacker News Datasette write demo", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 7, "created_at": "2022-12-02T21:17:41Z", "updated_at": "2022-12-02T23:47:11Z", "closed_at": "2022-12-02T21:43:19Z", "author_association": "OWNER", "pull_request": null, "body": "Idea is to have my existing scraper at https://github.com/simonw/scrape-hacker-news-by-domain also write to my private Datasette Cloud account, then create an atom feed from it.\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/1928/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": 1471969984, "node_id": "I_kwDOBm6k_c5XvHrA", "number": 1926, "title": "Release notes for 1.0a1 (and release it)", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": {"value": 7867486, "label": "Datasette 1.0a1"}, "comments": 1, "created_at": "2022-12-01T21:18:12Z", "updated_at": "2022-12-01T22:06:13Z", "closed_at": "2022-12-01T22:06:12Z", "author_association": "OWNER", "pull_request": null, "body": "Mainly CORS support and a few small bug fixes.\r\n\r\nChanges: https://github.com/simonw/datasette/compare/1.0a0...99da46f7258225fc6fd8e94ddc20859ccccc4109", "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/1926/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": 1214859703, "node_id": "I_kwDOBm6k_c5IaUm3", "number": 1719, "title": "Refactor `RowView` and remove `RowTableShared`", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 3, "created_at": "2022-04-25T18:06:24Z", "updated_at": "2022-12-01T21:15:19Z", "closed_at": "2022-04-25T18:33:44Z", "author_association": "OWNER", "pull_request": null, "body": "> The `RowTableShared` class is making this a whole lot more complicated.\r\n> \r\n> I'm going to split the `RowView` view out into an entirely separate `views/row.py` module.\r\n\r\n_Originally posted by @simonw in https://github.com/simonw/datasette/issues/1715#issuecomment-1108875068_", "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/1719/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": 1215174094, "node_id": "I_kwDOBm6k_c5IbhXO", "number": 1720, "title": "Design plugin hook for extras", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 14, "created_at": "2022-04-26T00:08:10Z", "updated_at": "2022-12-01T21:15:19Z", "closed_at": "2022-04-26T20:20:27Z", "author_association": "OWNER", "pull_request": null, "body": "Refs:\r\n- #262\r\n- #1709\r\n\r\nI realized that this is a really natural plugin hook - and if I design it as a hook I can implement Datasette's core extras as default plugins.", "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/1720/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": 1212823665, "node_id": "I_kwDOBm6k_c5ISjhx", "number": 1715, "title": "Refactor TableView to use asyncinject", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 13, "created_at": "2022-04-22T21:43:39Z", "updated_at": "2022-12-01T21:15:18Z", "closed_at": "2022-04-28T22:26:56Z", "author_association": "OWNER", "pull_request": null, "body": "I've been working on a dependency injection mechanism in a separate library:\r\n\r\n- https://github.com/simonw/asyncinject\r\n\r\nI think it's ready to try out with Datasette to see if it's a pattern that will work here.\r\n\r\nI'm going to attempt to refactor `TableView` to use it. There are two overall goals here:\r\n\r\n- Use `asyncinject` to add parallel execution of some aspects of the table page - most notably I want to be able to execute the `count(*)` query, the `select ...` query, the various faceting queries and the facet suggestion queries in parallel - and measure if doing so is good for performance.\r\n- Use it to execute different output formats (possibly with some changes to the existing `register_output_renderer()` plugin hook). I want CSV and JSON to use the same mechanism that plugins use.\r\n\r\nStretch goal is to get this working with streaming data too, see:\r\n\r\n- #1101", "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/1715/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": 1469973742, "node_id": "I_kwDOBm6k_c5XngTu", "number": 1922, "title": "Make sure CORS works for write APIs", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": {"value": 7867486, "label": "Datasette 1.0a1"}, "comments": 13, "created_at": "2022-11-30T17:15:55Z", "updated_at": "2022-12-01T18:47:00Z", "closed_at": "2022-12-01T18:47:00Z", "author_association": "OWNER", "pull_request": null, "body": "Split from:\r\n- #1850", "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/1922/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": 1470509936, "node_id": "I_kwDOBm6k_c5XpjNw", "number": 1924, "title": "Docs for replace:true and ignore:true options for insert API", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": {"value": 7867486, "label": "Datasette 1.0a1"}, "comments": 4, "created_at": "2022-12-01T01:33:25Z", "updated_at": "2022-12-01T18:15:15Z", "closed_at": "2022-12-01T02:08:02Z", "author_association": "OWNER", "pull_request": null, "body": "Equivalent to https://sqlite-utils.datasette.io/en/stable/cli.html#insert-replacing-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/1924/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": 1470320227, "node_id": "I_kwDOBm6k_c5Xo05j", "number": 1923, "title": "latest.datasette.io Cloud Run deploys failing", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 3, "created_at": "2022-11-30T22:49:34Z", "updated_at": "2022-11-30T23:04:56Z", "closed_at": "2022-11-30T23:04:56Z", "author_association": "OWNER", "pull_request": null, "body": "https://github.com/simonw/datasette/actions/runs/3587402085/jobs/6038106719v\r\n\r\n```\r\nWarning: \"service_account_key\" has been deprecated. Please switch to using google-github-actions/auth which supports both Workload Identity Federation and Service Account Key JSON authentication. For more details, see https://github.com/google-github-actions/setup-gcloud#authorization\r\nError: google-github-actions/setup-gcloud failed with: failed to execute command `gcloud --quiet auth activate-service-account *** --key-file -`: /opt/hostedtoolcache/gcloud/275.0.0/x64/lib/googlecloudsdk/core/console/console_io.py:544: SyntaxWarning: \"is\" with a literal. Did you mean \"==\"?\r\n if answer is None or (answer is '' and default is not None):\r\nERROR: gcloud failed to load: module 'collections' has no attribute 'MutableMapping'\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/1923/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": 1469044738, "node_id": "I_kwDOBm6k_c5Xj9gC", "number": 1918, "title": "API explorer should list mutable databases first", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": {"value": 7867486, "label": "Datasette 1.0a1"}, "comments": 1, "created_at": "2022-11-30T04:53:33Z", "updated_at": "2022-11-30T05:22:07Z", "closed_at": "2022-11-30T05:07:56Z", "author_association": "OWNER", "pull_request": null, "body": "https://latest.datasette.io/-/api hides `ephemeral` down at the bottom, would be more interesting if it was at the top.\r\n\r\nRelated:\r\n- #1915 ", "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/1918/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": 1469015001, "node_id": "I_kwDOBm6k_c5Xj2PZ", "number": 1916, "title": "GET requests against POST endpoints should not 500 error", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": {"value": 7867486, "label": "Datasette 1.0a1"}, "comments": 1, "created_at": "2022-11-30T04:04:43Z", "updated_at": "2022-11-30T05:15:19Z", "closed_at": "2022-11-30T05:15:19Z", "author_association": "OWNER", "pull_request": null, "body": "![CF37BA4D-0677-4DDD-A339-EAF163BB63B7](https://user-images.githubusercontent.com/9599/204705025-6f88e9f7-757d-45e8-a89c-ab97e84781e8.png)\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/1916/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": 1469043836, "node_id": "I_kwDOBm6k_c5Xj9R8", "number": 1917, "title": "Don't allow writable API to edit the `_memory` database", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": {"value": 7867486, "label": "Datasette 1.0a1"}, "comments": 2, "created_at": "2022-11-30T04:51:59Z", "updated_at": "2022-11-30T05:07:56Z", "closed_at": "2022-11-30T05:07:55Z", "author_association": "OWNER", "pull_request": null, "body": "It shows up on https://latest.datasette.io/-/api (once you are signed in as root) - but there's no point in creating tables in it because they likely won't persist from one request to the next, as it's not a shared named database.\r\n\r\n\"image\"\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/1917/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": 1468709531, "node_id": "I_kwDOBm6k_c5Xirqb", "number": 1915, "title": "Interactive demo of Datasette 1.0 write APIs", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 6, "created_at": "2022-11-29T21:16:03Z", "updated_at": "2022-11-30T04:05:46Z", "closed_at": "2022-11-30T04:05:46Z", "author_association": "OWNER", "pull_request": null, "body": "I'm going to try to get this working on https://latest.datasette.io/ - it already has a way for people to sign in as root, but none of the databases there are writable.\r\n\r\nSo I'm going to build a plugin which adds a writable named in-memory database.\r\n\r\nAnd some kind of mechanism for clearing out that database on a regular basis - maybe tables in that database get deleted automatically an hour after they are created?\r\n\r\n(Would be neat to display their time-left-until-deleted too)", "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/1915/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": 1421529723, "node_id": "I_kwDOBm6k_c5UutJ7", "number": 1850, "title": "Write API in Datasette core", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": {"value": 8658075, "label": "Datasette 1.0a0"}, "comments": 13, "created_at": "2022-10-24T22:13:24Z", "updated_at": "2022-11-29T20:11:20Z", "closed_at": "2022-11-29T20:11:20Z", "author_association": "OWNER", "pull_request": null, "body": "I need this for Datasette Cloud, and in thinking it through I realized that it's really time Datasette grew a default write API as well.\r\n\r\nI'm going to mostly model this off `sqlite-utils`, since I've spent a bunch of time iterating on a pseudo-JSON API for that over the past few years (piping JSON to stdin etc).\r\n\r\nI want this for Datasette 1.0. I'm going to be building it in the new [1.0-dev](https://github.com/simonw/datasette/tree/1.0-dev) branch, which is automatically deployed to https://latest-1-0-dev.datasette.io/ running on Cloud Run.\r\n\r\nAPI features to build:\r\n\r\n- [x] #1852\r\n - [x] #1856\r\n - [x] #1857\r\n - [x] #1858\r\n - [x] #1859\r\n- [x] #1871\r\n - [x] #1888\r\n- [x] #1868\r\n- [x] #1851\r\n- [x] #1863\r\n- [x] #1864\r\n- [x] #1866\r\n- [x] https://github.com/simonw/datasette/issues/1882\r\n- [x] #1862\r\n- [x] #1874\r\n - [x] https://github.com/simonw/datasette/issues/1887\r\n- [x] #1877\r\n\r\nBumped to later on:\r\n\r\n- #1855\r\n- #1878\r\n- #1873\r\n- #1875\r\n- Make sure CORS works\r\n- https://github.com/simonw/datasette/issues/1889\r\n- Alter a table - `sqlite-utils transform` style (more powerful than straight ALTER)\r\n- Execute SQL against a write connection\r\n- Maybe even multiple write SQL statements bundled in a single transaction\r\n- https://github.com/simonw/datasette/issues/1867\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/1850/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": 1468603401, "node_id": "I_kwDOBm6k_c5XiRwJ", "number": 1913, "title": "Release Datasette 1.0a0", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": {"value": 8658075, "label": "Datasette 1.0a0"}, "comments": 9, "created_at": "2022-11-29T19:41:42Z", "updated_at": "2022-11-29T20:10:35Z", "closed_at": "2022-11-29T20:10:35Z", "author_association": "OWNER", "pull_request": null, "body": "I attempted the release just now - https://github.com/simonw/datasette/releases/tag/1.0a0 - and got an unexpected test failure:\r\n\r\nhttps://github.com/simonw/datasette/actions/runs/3577355358/attempts/1\r\n\r\n```\r\n> assert delete_response.status_code == 200\r\nE assert 404 == 200\r\nE + where 404 = .status_code\r\n\r\n/home/runner/work/datasette/datasette/tests/test_api_write.py:396: AssertionError\r\n=========================== short test summary info ============================\r\nFAILED tests/test_api_write.py::test_delete_row[compound_pk_table-row_for_create2-pks2-article,k] - assert 404 == 200\r\n + where 404 = .status_code\r\n```\r\nI hit \"retry\" on that test but I expect it to fail again.\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/1913/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": 1432012302, "node_id": "I_kwDOBm6k_c5VWsYO", "number": 1877, "title": "Refactor and tidy up final write API code", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 1, "created_at": "2022-11-01T20:00:11Z", "updated_at": "2022-11-29T19:44:16Z", "closed_at": "2022-11-29T19:44:07Z", "author_association": "OWNER", "pull_request": null, "body": "- `views/table.py` has got a bit too big - I think the write classes should be pulled out into a separate module.\r\n- [x] There's duplicate logic for deciding if the table and database exist and checking permissions", "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/1877/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": 1450312343, "node_id": "I_kwDOBm6k_c5WcgKX", "number": 1892, "title": "Merge 1.0-dev branch back to main", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": {"value": 8658075, "label": "Datasette 1.0a0"}, "comments": 3, "created_at": "2022-11-15T20:04:25Z", "updated_at": "2022-11-29T19:40:23Z", "closed_at": "2022-11-29T19:40:23Z", "author_association": "OWNER", "pull_request": null, "body": "I'm committed enough to the 1.0 work now that I'm ready for the `main` branch to reflect that instead.\r\n\r\nIf I need to make any dot-releases against 0.63 I can do those from a branch.", "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/1892/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": 1468592292, "node_id": "PR_kwDOBm6k_c5D6nzE", "number": 1912, "title": "Merge 1.0-dev (with initial write API) back into main", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 1, "created_at": "2022-11-29T19:31:21Z", "updated_at": "2022-11-29T19:39:37Z", "closed_at": "2022-11-29T19:39:36Z", "author_association": "OWNER", "pull_request": "simonw/datasette/pulls/1912", "body": "See:\r\n- #1892\r\n\r\n\r\n----\n:books: Documentation preview :books:: https://datasette--1912.org.readthedocs.build/en/1912/\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/1912/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": 1450303205, "node_id": "I_kwDOBm6k_c5Wcd7l", "number": 1891, "title": "1.0a0 release notes", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": {"value": 8658075, "label": "Datasette 1.0a0"}, "comments": 4, "created_at": "2022-11-15T19:58:20Z", "updated_at": "2022-11-29T19:23:41Z", "closed_at": "2022-11-29T19:23:41Z", "author_association": "OWNER", "pull_request": null, "body": "This release will mainly help preview the new Datasette write API:\r\n- #1850", "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/1891/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": 1425029275, "node_id": "I_kwDOBm6k_c5U8Dib", "number": 1864, "title": "Delete a single record from an existing table", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": {"value": 8658075, "label": "Datasette 1.0a0"}, "comments": 4, "created_at": "2022-10-27T04:53:22Z", "updated_at": "2022-11-29T18:54:04Z", "closed_at": "2022-11-29T18:54:04Z", "author_association": "OWNER", "pull_request": null, "body": "API design:\r\n```\r\nPOST /db/table/row-pks/-/delete\r\nOr...\r\nDELETE /db/table/row-pks/-/delete\r\n```\r\nI'm just going to do `POST` for the moment, like I did here:\r\n- #1874\r\n\r\nPermission: `delete-row`\r\n\r\nStill needed:\r\n\r\n- [ ] Tests for rowid tables\r\n- [ ] Tests for compound primary keys", "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/1864/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": 1468519699, "node_id": "I_kwDOBm6k_c5Xh9UT", "number": 1911, "title": "`/db/-/create` should support creating tables with compound primary keys", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": {"value": 8658075, "label": "Datasette 1.0a0"}, "comments": 2, "created_at": "2022-11-29T18:30:47Z", "updated_at": "2022-11-29T18:50:58Z", "closed_at": "2022-11-29T18:48:05Z", "author_association": "OWNER", "pull_request": null, "body": "Found myself needing this to write the tests for:\r\n- #1864 ", "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/1911/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": 1425029242, "node_id": "I_kwDOBm6k_c5U8Dh6", "number": 1863, "title": "Update a single record in an existing table", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": {"value": 8658075, "label": "Datasette 1.0a0"}, "comments": 16, "created_at": "2022-10-27T04:53:17Z", "updated_at": "2022-11-29T18:08:53Z", "closed_at": "2022-11-29T18:06:37Z", "author_association": "OWNER", "pull_request": null, "body": "API design:\r\n\r\n```\r\nPOST /db/table/row-pks/-/update\r\n{\r\n \"field\": \"updated_value\"\r\n}\r\n```\r\nOnly the fields that you pass will be updated.\r\n\r\nMaybe this is the wrong design though? The design for insert currently looks like this:\r\n\r\n- https://github.com/simonw/datasette/issues/1851#issuecomment-1294224185\r\n\r\n```\r\nPOST /db/table/-/insert\r\nAuthorization: Bearer xxx\r\nContent-Type: application/json\r\n{\r\n \"row\": {\r\n \"id\": 1,\r\n \"name\": \"New name\"\r\n }\r\n}\r\n```\r\nI could use the same format for `/-/update`, but in this case the API doesn't require you to pass every field so `\"row\"` doesn't seem like the right key.\r\n\r\nI think I'll go with this:\r\n\r\n```\r\nPOST /db/table/1/-/update\r\nAuthorization: Bearer xxx\r\nContent-Type: application/json\r\n{\r\n \"update\": {\r\n \"name\": \"New name\"\r\n }\r\n}\r\n```\r\nThe benefit of having an `\"update\"` key is that it allows me to use other keys in the future. Maybe a `\"alter\": true` key to indicate that new columns should be added if they are missing.", "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/1863/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": 1456012874, "node_id": "I_kwDOBm6k_c5WyP5K", "number": 1905, "title": "`publish heroku` failing due to old Python version", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 4, "created_at": "2022-11-19T00:01:45Z", "updated_at": "2022-11-19T01:12:05Z", "closed_at": "2022-11-19T00:52:29Z", "author_association": "OWNER", "pull_request": null, "body": "Reported on Discord: https://discord.com/channels/823971286308356157/823971286941302908/1042814317118115901\r\n\r\n```\r\n-----> Building on the Heroku-22 stack\r\n-----> Determining which buildpack to use for this app\r\n-----> Python app detected\r\n-----> Using Python version specified in runtime.txt\r\n ! Requested runtime 'python-3.8.10' is not available for this stack (heroku-22).\r\n ! For supported versions, see: https://devcenter.heroku.com/articles/python-support\r\n ! Push rejected, failed to compile Python app.\r\n\r\n ! Push failed\r\n \u25b8 Build failed\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/1905/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": 1455932972, "node_id": "I_kwDOBm6k_c5Wx8Ys", "number": 1904, "title": "Datasette Lite tests failing due to httpx upgrade", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": {"value": 8658075, "label": "Datasette 1.0a0"}, "comments": 0, "created_at": "2022-11-18T22:49:31Z", "updated_at": "2022-11-18T22:57:48Z", "closed_at": "2022-11-18T22:52:22Z", "author_association": "OWNER", "pull_request": null, "body": "Same problem as this one:\r\n- https://github.com/simonw/datasette-lite/issues/56\r\n\r\nCaused this failure: https://github.com/simonw/datasette/actions/runs/3500765964", "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/1904/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": 1452364777, "node_id": "I_kwDOBm6k_c5WkVPp", "number": 1896, "title": "Extract logic for resolving a URL to a database / table / row", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": {"value": 8658075, "label": "Datasette 1.0a0"}, "comments": 4, "created_at": "2022-11-16T22:25:20Z", "updated_at": "2022-11-18T22:57:47Z", "closed_at": "2022-11-18T22:56:55Z", "author_association": "OWNER", "pull_request": null, "body": "> In trying to write this I realize that there's a lot of duplicated code with delete row, specifically around resolving the incoming URL into a row (or a database or a table).\r\n>\r\n> Since this is so common, I think it's worth extracting the logic out first.\r\n\r\n_Originally posted by @simonw in https://github.com/simonw/datasette/issues/1863#issuecomment-1317755263_\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/1896/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": 1434911255, "node_id": "I_kwDOCGYnMM5VhwIX", "number": 510, "title": "Cannot enable FTS5 despite it being available", "user": {"value": 1176293, "label": "ar-jan"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 3, "created_at": "2022-11-03T16:03:49Z", "updated_at": "2022-11-18T18:37:52Z", "closed_at": "2022-11-17T10:36:28Z", "author_association": "NONE", "pull_request": null, "body": "When I do `sqlite-utils enable-fts my.db table_name column_name` (with or without `--fts5`), I get an FTS4 virtual table instead of the expected FTS5.\r\n\r\nFTS5 is however available and Python/SQLite versions do not seem to be the issue. I can manually create the FTS5 virtual table, and then Datasette also works with it from this same Python environment.\r\n\r\n`>>> sqlite3.version`\r\n`2.6.0`\r\n`>>> sqlite3.sqlite_version`\r\n`3.39.4`\r\n\r\n`PRAGMA compile_options;` includes `ENABLE_FTS5`.\r\n\r\n`sqlite-utils, version 3.30`.\r\n\r\nAny ideas what's happening and how to fix?", "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/510/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": 1450796965, "node_id": "I_kwDOBm6k_c5WeWel", "number": 1894, "title": "Initialize CodeMirror during DOMContentLoaded instead of onload", "user": {"value": 95570, "label": "bgrins"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 0, "created_at": "2022-11-16T03:52:19Z", "updated_at": "2022-11-18T07:29:02Z", "closed_at": "2022-11-18T07:29:02Z", "author_association": "CONTRIBUTOR", "pull_request": null, "body": "As per https://github.com/simonw/datasette/pull/1893/files#r1023248927 this should prevent a flash between the textarea being replaced by CodeMirror.", "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/1894/reactions\", \"total_count\": 1, \"+1\": 1, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"} {"id": 1452485922, "node_id": "PR_kwDOBm6k_c5DEh-E", "number": 1898, "title": "Use DOMContentLoaded instead of load event for CodeMirror initialization", "user": {"value": 95570, "label": "bgrins"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 2, "created_at": "2022-11-17T00:19:21Z", "updated_at": "2022-11-18T07:29:01Z", "closed_at": "2022-11-18T07:29:01Z", "author_association": "CONTRIBUTOR", "pull_request": "simonw/datasette/pulls/1898", "body": " Closes #1894\r\n\r\n\r\n----\n:books: Documentation preview :books:: https://datasette--1898.org.readthedocs.build/en/1898/\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/1898/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": 1452495049, "node_id": "I_kwDOBm6k_c5Wk1DJ", "number": 1899, "title": "Clicking within the CodeMirror area below the SQL (i.e. when there's only a single line) doesn't cause the editor to get focused ", "user": {"value": 95570, "label": "bgrins"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 4, "created_at": "2022-11-17T00:29:52Z", "updated_at": "2022-11-18T07:28:28Z", "closed_at": "2022-11-18T07:20:53Z", "author_association": "CONTRIBUTOR", "pull_request": null, "body": "After the upgrade to 6 (#1893) I noticed this. I think it's because we're doing overflow:hidden to accomplish the CSS resizer.\r\n\r\nWhen there's a single line of SQL there's a gap below that line where clicking doesn't do anything. It should focus at the end of the line.", "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/1899/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": "\"Screenshot\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": 1452457263, "node_id": "I_kwDOBm6k_c5Wkr0v", "number": 1897, "title": "Serve schema JSON to the SQL editor to enable autocomplete", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 9, "created_at": "2022-11-16T23:47:45Z", "updated_at": "2022-11-18T05:33:20Z", "closed_at": "2022-11-18T02:54:43Z", "author_association": "OWNER", "pull_request": null, "body": "See:\r\n- https://github.com/simonw/datasette/issues/1893#issuecomment-1317831555\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/1897/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": 1430563092, "node_id": "PR_kwDOCGYnMM5B6_6K", "number": 508, "title": "Allow surrogates in parameters", "user": {"value": 7908073, "label": "chapmanjacobd"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 2, "created_at": "2022-10-31T22:11:49Z", "updated_at": "2022-11-17T15:11:16Z", "closed_at": "2022-10-31T22:55:36Z", "author_association": "CONTRIBUTOR", "pull_request": "simonw/sqlite-utils/pulls/508", "body": "closes #507\r\n\r\nhttps://dwheeler.com/essays/fixing-unix-linux-filenames.html\r\n\r\n\r\n----\n:books: Documentation preview :books:: https://sqlite-utils--508.org.readthedocs.build/en/508/\n\r\n", "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/508/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": 1448143294, "node_id": "I_kwDOBm6k_c5WUOm-", "number": 1890, "title": "Autocomplete text entry for filter values that correspond to facets", "user": {"value": 536941, "label": "fgregg"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 16, "created_at": "2022-11-14T14:11:31Z", "updated_at": "2022-11-17T00:47:36Z", "closed_at": "2022-11-16T03:23:01Z", "author_association": "CONTRIBUTOR", "pull_request": null, "body": "datasette allows users to enter in the value for named parameters into a free-text form field.\r\n\r\nI think it would add a lot of usability, if the form field could be a drop down of options when query value is already a faceted column.", "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/1890/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": 1450363982, "node_id": "PR_kwDOBm6k_c5C9ZuP", "number": 1893, "title": "Upgrade to CodeMirror 6, add SQL autocomplete", "user": {"value": 95570, "label": "bgrins"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 48, "created_at": "2022-11-15T20:52:35Z", "updated_at": "2022-11-16T23:54:02Z", "closed_at": "2022-11-16T23:49:06Z", "author_association": "CONTRIBUTOR", "pull_request": "simonw/datasette/pulls/1893", "body": "In an effort to get closer to table / column autocomplete I took a shot at https://github.com/simonw/datasette/issues/1796. I haven't done a lot of testing but would be curious if this fixes some of the concerns raised in https://github.com/simonw/datasette/issues/1796#issue-1355148385 for example.\r\n\r\nDone:\r\n* Changed to bundling using rollup as per https://codemirror.net/examples/bundle/\r\n* Restored a fromTextArea-like function from https://codemirror.net/docs/migration/\r\n* Removed old JS and CSS files (no external CSS needed anymore as per https://codemirror.net/examples/styling/)\r\n* Updated instructions for building the bundle\r\n\r\nNot done:\r\n* cmResize had an error, so commented out the resize handle\r\n* Add extraKeys option for shift+enter and tab\r\n\r\n\r\n----\n:books: Documentation preview :books:: https://datasette--1893.org.readthedocs.build/en/1893/\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/1893/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": 1450952393, "node_id": "I_kwDOCGYnMM5We8bJ", "number": 512, "title": "mypy failures in CI", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 3, "created_at": "2022-11-16T06:22:48Z", "updated_at": "2022-11-16T07:49:51Z", "closed_at": "2022-11-16T07:49:50Z", "author_association": "OWNER", "pull_request": null, "body": "https://github.com/simonw/sqlite-utils/actions/runs/3472012235 failed on Python 3.11:\r\n\r\nTruncated output:\r\n```\r\nsqlite_utils/db.py:2467: note: PEP 484 prohibits implicit Optional. Accordingly, mypy has changed its default to no_implicit_optional=True\r\nsqlite_utils/db.py:2467: note: Use https://github.com/hauntsaninja/no_implicit_optional to automatically upgrade your codebase\r\nsqlite_utils/db.py:2530: error: Incompatible default for argument \"where\" (default has type \"None\", argument has type \"str\") [assignment]\r\nsqlite_utils/db.py:2530: note: PEP 484 prohibits implicit Optional. Accordingly, mypy has changed its default to no_implicit_optional=True\r\nsqlite_utils/db.py:2530: note: Use https://github.com/hauntsaninja/no_implicit_optional to automatically upgrade your codebase\r\nsqlite_utils/db.py:2658: error: Argument 1 to \"count_where\" of \"Queryable\" has incompatible type \"Optional[str]\"; expected \"str\" [arg-type]\r\nFound 23 errors in 1 file (checked 51 source files)\r\n```\r\nBest look at https://github.com/hauntsaninja/no_implicit_optional", "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/512/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": 1447388809, "node_id": "I_kwDOBm6k_c5WRWaJ", "number": 1887, "title": "Add a confirm step to the drop table API", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": {"value": 8658075, "label": "Datasette 1.0a0"}, "comments": 2, "created_at": "2022-11-14T04:59:53Z", "updated_at": "2022-11-15T19:59:59Z", "closed_at": "2022-11-14T05:18:51Z", "author_association": "OWNER", "pull_request": null, "body": "> In playing with the API explorer just now I realized it's way too easy to accidentally drop a table using it.\r\n\r\n_Originally posted by @simonw in https://github.com/simonw/datasette/issues/1871#issuecomment-1313097057_\r\n\r\nAdded drop table API in:\r\n- #1874", "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/1887/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": 1429030341, "node_id": "I_kwDOBm6k_c5VLUXF", "number": 1874, "title": "API to drop a table", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": {"value": 8658075, "label": "Datasette 1.0a0"}, "comments": 4, "created_at": "2022-10-30T21:55:11Z", "updated_at": "2022-11-15T19:59:53Z", "closed_at": "2022-11-14T05:45:06Z", "author_association": "OWNER", "pull_request": null, "body": "`POST /db/table/-/drop`\r\n\r\nRequire `drop-table` permission.", "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/1874/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": 1425011030, "node_id": "I_kwDOBm6k_c5U7_FW", "number": 1862, "title": "Create a new table from one or more records, `sqlite-utils` style", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": {"value": 8658075, "label": "Datasette 1.0a0"}, "comments": 5, "created_at": "2022-10-27T04:25:02Z", "updated_at": "2022-11-15T19:59:47Z", "closed_at": "2022-11-15T06:42:09Z", "author_association": "OWNER", "pull_request": null, "body": "It's interesting to also think about what the form-based UI for this could look like - since that would involve users creating new columns of different types on the fly.\r\n\r\nWill need the `create-table` permission.", "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/1862/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": 1435294468, "node_id": "I_kwDOBm6k_c5VjNsE", "number": 1882, "title": "`/db/-/create` API for creating tables", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": {"value": 8658075, "label": "Datasette 1.0a0"}, "comments": 12, "created_at": "2022-11-03T21:44:32Z", "updated_at": "2022-11-15T19:59:43Z", "closed_at": "2022-11-15T06:00:41Z", "author_association": "OWNER", "pull_request": null, "body": "> It really feels like this should be accompanied by a `/db/-/create` API for creating tables. I had to add that to `sqlite-utils` eventually (initially it only supported creating by passing in an example document):\r\n>\r\n> https://sqlite-utils.datasette.io/en/stable/cli.html#cli-create-table\r\n\r\n_Originally posted by @simonw in https://github.com/simonw/datasette/issues/1862#issuecomment-1299073433_\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/1882/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": 1426001541, "node_id": "I_kwDOBm6k_c5U_w6F", "number": 1866, "title": "API for bulk inserting records into a table", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": {"value": 8658075, "label": "Datasette 1.0a0"}, "comments": 12, "created_at": "2022-10-27T17:19:25Z", "updated_at": "2022-11-15T19:59:34Z", "closed_at": "2022-10-30T06:04:07Z", "author_association": "OWNER", "pull_request": null, "body": "Similar to https://github.com/simonw/datasette-insert/blob/0.8/README.md#inserting-data-and-creating-tables\r\n\r\nI expect this to become by far the most common way that data gets into a Datasette instance - more so than the individual row API in:\r\n- #1851 ", "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/1866/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": 1421544654, "node_id": "I_kwDOBm6k_c5UuwzO", "number": 1851, "title": "API to insert a single record into an existing table", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": {"value": 8658075, "label": "Datasette 1.0a0"}, "comments": 22, "created_at": "2022-10-24T22:24:21Z", "updated_at": "2022-11-15T19:59:18Z", "closed_at": "2022-10-28T00:59:25Z", "author_association": "OWNER", "pull_request": null, "body": "Controlled by a new `insert-row` permission.", "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/1851/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": 1426195437, "node_id": "I_kwDOBm6k_c5VAgPt", "number": 1868, "title": "Design URLs for the write API", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": {"value": 8658075, "label": "Datasette 1.0a0"}, "comments": 5, "created_at": "2022-10-27T19:55:30Z", "updated_at": "2022-11-15T19:59:14Z", "closed_at": "2022-10-27T20:07:01Z", "author_association": "OWNER", "pull_request": null, "body": "My original design for this issue:\r\n- #1851\r\n\r\nWas `POST /db/table` with JSON of `{\"insert\": {...}}`.", "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/1868/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": 1447439985, "node_id": "I_kwDOBm6k_c5WRi5x", "number": 1888, "title": "API explorer should take immutability into account", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": {"value": 8658075, "label": "Datasette 1.0a0"}, "comments": 1, "created_at": "2022-11-14T06:00:14Z", "updated_at": "2022-11-15T19:59:10Z", "closed_at": "2022-11-14T06:04:48Z", "author_association": "OWNER", "pull_request": null, "body": "Refs:\r\n- #1871\r\n\r\nI noticed the API explorer doesn't show any links on https://latest-1-0-dev.datasette.io/-/api because the `fixtures` database is immutable.\r\n\r\nIt should still show read examples there.", "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/1888/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": 1427293909, "node_id": "I_kwDOBm6k_c5VEsbV", "number": 1871, "title": "API explorer tool", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": {"value": 8658075, "label": "Datasette 1.0a0"}, "comments": 24, "created_at": "2022-10-28T13:49:11Z", "updated_at": "2022-11-15T19:59:05Z", "closed_at": "2022-11-14T04:59:59Z", "author_association": "OWNER", "pull_request": null, "body": "The API will be much easier to develop if there's a page that helps you execute JSON POSTs against it.", "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/1871/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": 1423369494, "node_id": "I_kwDOBm6k_c5U1uUW", "number": 1859, "title": "datasette create-token CLI command", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": {"value": 8658075, "label": "Datasette 1.0a0"}, "comments": 3, "created_at": "2022-10-26T03:12:59Z", "updated_at": "2022-11-15T19:59:00Z", "closed_at": "2022-10-26T04:31:39Z", "author_association": "OWNER", "pull_request": null, "body": "The CLI equivalent of the `/-/create-token` page.", "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/1859/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": 1423364990, "node_id": "I_kwDOBm6k_c5U1tN-", "number": 1858, "title": "`max_signed_tokens_ttl` setting for a maximum duration on API tokens", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": {"value": 8658075, "label": "Datasette 1.0a0"}, "comments": 4, "created_at": "2022-10-26T03:05:53Z", "updated_at": "2022-11-15T19:58:52Z", "closed_at": "2022-10-27T03:15:05Z", "author_association": "OWNER", "pull_request": null, "body": "It's currently possible to use `/-/create-token` to create a token that lasts forever.\r\n\r\nSome administrators may wish to have a maximum expiry instead. I should support that with a setting.", "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/1858/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": 1423347412, "node_id": "I_kwDOBm6k_c5U1o7U", "number": 1857, "title": "Prevent API tokens from using /-/create-token to create more tokens", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": {"value": 8658075, "label": "Datasette 1.0a0"}, "comments": 1, "created_at": "2022-10-26T02:38:09Z", "updated_at": "2022-11-15T19:57:11Z", "closed_at": "2022-10-26T02:57:26Z", "author_association": "OWNER", "pull_request": null, "body": "> It strikes me that users should NOT be able to use a token to create additional tokens.\r\n>\r\n> The current design actually does allow that, since the `dstok_` Bearer token can be used to authenticate calls to the `/-/create-token` page.\r\n>\r\n> So I think I need a mechanism whereby that page can only allow access to users authenticated by cookie.\r\n> \r\n> Not obvious how to do that though, since Datasette's authentication actor system is designed to abstract that detail away!\r\n\r\n_Originally posted by @simonw in https://github.com/simonw/datasette/issues/1850#issuecomment-1291417100_", "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/1857/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": 1423336122, "node_id": "I_kwDOBm6k_c5U1mK6", "number": 1856, "title": "allow_signed_tokens setting for disabling API signed token mechanism", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": {"value": 8658075, "label": "Datasette 1.0a0"}, "comments": 3, "created_at": "2022-10-26T02:20:55Z", "updated_at": "2022-11-15T19:57:05Z", "closed_at": "2022-10-26T02:58:35Z", "author_association": "OWNER", "pull_request": null, "body": "Had some design thoughts here: https://github.com/simonw/datasette/issues/1852#issuecomment-1291272280\r\n\r\nI liked this option the most:\r\n\r\n --setting allow_create_tokens off", "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/1856/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": 1421552095, "node_id": "I_kwDOBm6k_c5Uuynf", "number": 1852, "title": "Default API token authentication mechanism", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": {"value": 8658075, "label": "Datasette 1.0a0"}, "comments": 30, "created_at": "2022-10-24T22:31:07Z", "updated_at": "2022-11-15T19:57:00Z", "closed_at": "2022-10-26T02:19:54Z", "author_association": "OWNER", "pull_request": null, "body": "API authentication will be via `Authorization: Bearer XXX` request headers.\r\n\r\nI'm inclined to add a default token mechanism to Datasette based on tokens that are signed with the `DATASETTE_SECRET`. Maybe the root user can access `/-/create-token` which provides a UI for generating a time-limited signed token? Could also have a `datasette token` command for creating such tokens at the command-line.\r\n\r\nPlugins can then define alternative ways of creating tokens, such as the existing https://datasette.io/plugins/datasette-auth-tokens plugin.\r\n\r\n_Originally posted by @simonw in https://github.com/simonw/datasette/issues/1850#issuecomment-1289706439_\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/1852/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": 1435917503, "node_id": "I_kwDOBm6k_c5Vlly_", "number": 1883, "title": "Errors when using table filters behind a proxy", "user": {"value": 31312775, "label": "mattmalcher"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 13, "created_at": "2022-11-04T11:18:47Z", "updated_at": "2022-11-11T09:20:22Z", "closed_at": "2022-11-11T06:54:58Z", "author_association": "NONE", "pull_request": null, "body": "Using datasette==0.63 table filters do not respect the `base_url` setting as described [here](https://docs.datasette.io/en/stable/deploying.html#running-datasette-behind-a-proxy)\r\n\r\nTo reproduce, go to:\r\nhttps://datasette-apache-proxy-demo.datasette.io/prefix/fixtures/binary_data\r\n\r\nThen use the table filter buttons.\r\nThe `/prefix/` is dropped, resulting in URL not found:\r\nhttps://datasette-apache-proxy-demo.datasette.io/fixtures/binary_data?_sort=rowid&rowid__exact=1\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/1883/reactions\", \"total_count\": 1, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 1}", "draft": null, "state_reason": "completed"} {"id": 1436539554, "node_id": "I_kwDOCGYnMM5Vn9qi", "number": 511, "title": "[insert_all, upsert_all] IntegrityError: constraint failed", "user": {"value": 7908073, "label": "chapmanjacobd"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 2, "created_at": "2022-11-04T19:21:48Z", "updated_at": "2022-11-04T22:59:54Z", "closed_at": "2022-11-04T22:54:09Z", "author_association": "CONTRIBUTOR", "pull_request": null, "body": "My understand is that `INSERT OR IGNORE` will ignore when inserts would cause duplicate keys so I'm not sure exactly why the error is raised from `sqlite3`.\r\n\r\n```\r\nimport argparse\r\nfrom pathlib import Path\r\n\r\nfrom xklb import db, utils\r\nfrom xklb.utils import log\r\n\r\n\r\ndef parse_args() -> argparse.Namespace:\r\n parser = argparse.ArgumentParser()\r\n parser.add_argument(\"database\")\r\n parser.add_argument(\"dbs\", nargs=\"*\")\r\n parser.add_argument(\"--upsert\")\r\n parser.add_argument(\"--db\", \"-db\", help=argparse.SUPPRESS)\r\n parser.add_argument(\"--verbose\", \"-v\", action=\"count\", default=0)\r\n args = parser.parse_args()\r\n\r\n if args.db:\r\n args.database = args.db\r\n Path(args.database).touch()\r\n args.db = db.connect(args)\r\n log.info(utils.dict_filter_bool(args.__dict__))\r\n\r\n return args\r\n\r\n\r\ndef merge_db(args, source_db):\r\n source_db = str(Path(source_db).resolve())\r\n\r\n s_db = db.connect(argparse.Namespace(database=source_db, verbose=args.verbose))\r\n for table in [s for s in s_db.table_names() if not \"_fts\" in s and not s.startswith(\"sqlite_\")]:\r\n log.info(\"[%s]: %s\", source_db, table)\r\n with s_db.conn:\r\n data = s_db[table].rows\r\n\r\n with args.db.conn:\r\n if args.upsert:\r\n args.db[table].upsert_all(data, pk=args.upsert.split(\",\"), alter=True)\r\n else:\r\n args.db[table].insert_all(data, alter=True, replace=True)\r\n\r\n\r\ndef merge_dbs():\r\n args = parse_args()\r\n for s_db in args.dbs:\r\n merge_db(args, s_db)\r\n\r\n\r\nif __name__ == \"__main__\":\r\n merge_dbs()\r\n\r\n```\r\n\r\n```\r\n$ lb-dev merge video.db tube_71.db --upsert path -vv\r\nSQL: INSERT OR IGNORE INTO [media]([path]) VALUES(?); - params: ['https://archive.org/details/088ghostofachanceroygetssackedrevengeofthelivinglunchdvdripxvidphz']\r\n...\r\nFile ~/.local/lib/python3.10/site-packages/sqlite_utils/db.py:3122, in Table.insert_all(self, records, pk, foreign_keys, column_order, not_null, defaults, batch_size, hash_id, hash_id_columns, alter, ignore, replace, truncate, extracts, conversions, columns, upsert, analyze)\r\n 3116 all_columns += [\r\n 3117 column for column in record if column not in all_columns\r\n 3118 ]\r\n 3120 first = False\r\n-> 3122 self.insert_chunk(\r\n 3123 alter,\r\n 3124 extracts,\r\n 3125 chunk,\r\n 3126 all_columns,\r\n 3127 hash_id,\r\n 3128 hash_id_columns,\r\n 3129 upsert,\r\n 3130 pk,\r\n 3131 conversions,\r\n 3132 num_records_processed,\r\n 3133 replace,\r\n 3134 ignore,\r\n 3135 )\r\n 3137 if analyze:\r\n 3138 self.analyze()\r\n\r\nFile ~/.local/lib/python3.10/site-packages/sqlite_utils/db.py:2887, in Table.insert_chunk(self, alter, extracts, chunk, all_columns, hash_id, hash_id_columns, upsert, pk, conversions, num_records_processed, replace, ignore)\r\n 2885 for query, params in queries_and_params:\r\n 2886 try:\r\n-> 2887 result = self.db.execute(query, params)\r\n 2888 except OperationalError as e:\r\n 2889 if alter and (\" column\" in e.args[0]):\r\n 2890 # Attempt to add any missing columns, then try again\r\n\r\nFile ~/.local/lib/python3.10/site-packages/sqlite_utils/db.py:484, in Database.execute(self, sql, parameters)\r\n 482 self._tracer(sql, parameters)\r\n 483 if parameters is not None:\r\n--> 484 return self.conn.execute(sql, parameters)\r\n 485 else:\r\n 486 return self.conn.execute(sql)\r\n\r\nIntegrityError: constraint failed\r\n> /home/xk/.local/lib/python3.10/site-packages/sqlite_utils/db.py(484)execute()\r\n 482 self._tracer(sql, parameters)\r\n 483 if parameters is not None:\r\n--> 484 return self.conn.execute(sql, parameters)\r\n 485 else:\r\n 486 return self.conn.execute(sql)\r\n```\r\n\r\n```\r\nsqlite3 --version\r\n3.36.0 2021-06-18 18:36:39\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/511/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": 473083260, "node_id": "MDU6SXNzdWU0NzMwODMyNjA=", "number": 50, "title": "\"Too many SQL variables\" on large inserts", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 4, "created_at": "2019-07-25T21:43:31Z", "updated_at": "2022-11-04T14:38:36Z", "closed_at": "2019-07-28T11:59:33Z", "author_association": "OWNER", "pull_request": null, "body": "Reported here: https://github.com/dogsheep/healthkit-to-sqlite/issues/9\r\n\r\nIt looks like there's a default limit of 999 variables - we need to be smart about that, maybe dynamically lower the batch size based on the number of columns.", "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/50/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": 1429029604, "node_id": "I_kwDOCGYnMM5VLULk", "number": 506, "title": "Make `cursor.rowcount` accessible (wontfix)", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 3, "created_at": "2022-10-30T21:51:55Z", "updated_at": "2022-11-01T17:37:47Z", "closed_at": "2022-11-01T17:37:13Z", "author_association": "OWNER", "pull_request": null, "body": "In building this Datasette feature on top of `sqlite-utils` I thought it might be useful to expose the number of rows that had been affected by a bulk insert or update - the `cursor.rowcount`:\r\n\r\n- https://github.com/simonw/datasette/issues/1866\r\n\r\nThis isn't currently exposed by `sqlite-utils`.", "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/506/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": 1431786951, "node_id": "I_kwDOBm6k_c5VV1XH", "number": 1876, "title": "SQL query should wrap on SQL interrupted screen", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 2, "created_at": "2022-11-01T17:14:01Z", "updated_at": "2022-11-01T17:22:33Z", "closed_at": "2022-11-01T17:22:33Z", "author_association": "OWNER", "pull_request": null, "body": "Just saw this:\r\n\r\n\"CleanShot", "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/1876/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": 1430325103, "node_id": "I_kwDOCGYnMM5VQQdv", "number": 507, "title": "conn.execute: UnicodeEncodeError: 'utf-8' codec can't encode character", "user": {"value": 7908073, "label": "chapmanjacobd"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 1, "created_at": "2022-10-31T18:49:51Z", "updated_at": "2022-11-01T00:40:17Z", "closed_at": "2022-11-01T00:40:16Z", "author_association": "CONTRIBUTOR", "pull_request": null, "body": "I'm not really sure what caused this and it happened in the middle of my program (after running for 35775 seconds).\r\n\r\n```\r\nExtracting metadata 49.9% (chunk 9893 of 19831)\r\n...\r\n File \"/home/xk/.local/lib/python3.10/site-packages/xklb/fs_extract.py\", line 90, in extract_chunk\r\n args.db[\"media\"].insert_all(utils.list_dict_filter_bool(media), pk=\"path\", alter=True, replace=True)\r\n File \"/home/xk/.local/lib/python3.10/site-packages/sqlite_utils/db.py\", line 3107, in insert_all\r\n self.insert_chunk(\r\n File \"/home/xk/.local/lib/python3.10/site-packages/sqlite_utils/db.py\", line 2872, in insert_chunk\r\n result = self.db.execute(query, params)\r\n File \"/home/xk/.local/lib/python3.10/site-packages/sqlite_utils/db.py\", line 483, in execute\r\n return self.conn.execute(sql, parameters)\r\nUnicodeEncodeError: 'utf-8' codec can't encode character '\\udcc3' in position 62: surrogates not allowed\r\n```\r\n\r\nThis might be relevant: https://stackoverflow.com/questions/31898353/python-cant-encode-with-surrogateescape\r\n\r\nI'm going to try re-running with \r\n\r\n```py\r\n def execute(\r\n self, sql: str, parameters: Optional[Union[Iterable, dict]] = None\r\n ) -> sqlite3.Cursor:\r\n \"\"\"\r\n Execute SQL query and return a ``sqlite3.Cursor``.\r\n\r\n :param sql: SQL query to execute\r\n :param parameters: Parameters to use in that query - an iterable for ``where id = ?``\r\n parameters, or a dictionary for ``where id = :id``\r\n \"\"\"\r\n try:\r\n if self._tracer:\r\n self._tracer(sql, parameters)\r\n if parameters is not None:\r\n return self.conn.execute(sql, parameters)\r\n else:\r\n return self.conn.execute(sql)\r\n except UnicodeEncodeError:\r\n sql = sql.encode('utf-8', 'surrogatepass').decode('utf-8')\r\n if parameters is not None:\r\n parameters = parameters.encode('utf-8', 'surrogatepass').decode('utf-8')\r\n return self.execute(sql, parameters)\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/507/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": 1428560020, "node_id": "I_kwDOBm6k_c5VJhiU", "number": 1872, "title": "SITE-BUSTING ERROR: \"render_template() called before await ds.invoke_startup()\"", "user": {"value": 192568, "label": "mroswell"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 3, "created_at": "2022-10-30T02:28:39Z", "updated_at": "2022-10-30T06:26:01Z", "closed_at": "2022-10-30T06:26:01Z", "author_association": "CONTRIBUTOR", "pull_request": null, "body": "1. My https://list.saferdisinfectants.org/disinfectants/listN page (linked from https://SaferDisinfectants.org ) has been running beautifully for a year and a half, including a GitHub Actions workflow that's been routinely updating the database.\r\n\r\n2. I received a recent report that the list page is down. I don't know when it went down, but the content is replaced with: \"render_template() called before await ds.invoke_startup()\"\r\n\r\n3. The local datasette repo runs without incident.\r\n\r\n4. The site is hosted on vercel, linked to my github repo. Perhaps some vercel changes were made, but not by anyone on our side. Here is a screenshot of the current project settings:\r\n\r\n\"Screen\r\n\r\nHere a screenshot of the latest deployment status:\r\n\"Screen\r\n\r\nThis is my repository:\r\nhttps://github.com/mroswell/list-N\r\n(I notice: datasette==0.59 in my requirements.txt file)\r\n\r\nBecause it's been long while since I actively worked on this or any other datasette project, I forget a lot of what I knew at one point. Perhaps some configuration file could be missing? Or perhaps I just need to know the right incantation to add to that vercel settings page. \r\n\r\nHelp is welcome as the nonprofit org is soon hosting its annual conference, and we'd love to have the page working again.\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/1872/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": 1426253476, "node_id": "I_kwDOBm6k_c5VAuak", "number": 1869, "title": "Release 0.63", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 3, "created_at": "2022-10-27T20:53:01Z", "updated_at": "2022-10-27T22:24:38Z", "closed_at": "2022-10-27T22:11:33Z", "author_association": "OWNER", "pull_request": null, "body": "Most of the release notes are already written:\r\n- https://github.com/simonw/datasette/releases/tag/0.63a0\r\n- https://github.com/simonw/datasette/releases/tag/0.63a1", "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/1869/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"}