{"id": 1808215339, "node_id": "I_kwDOBm6k_c5rxy0r", "number": 2104, "title": "Tables starting with an underscore should be treated as hidden", "user": {"value": 9599, "label": "simonw"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 2, "created_at": "2023-07-17T17:13:53Z", "updated_at": "2023-07-18T22:41:37Z", "closed_at": null, "author_association": "OWNER", "pull_request": null, "body": "Plugins can then take advantage of this pattern, for example:\r\n- https://github.com/simonw/datasette-auth-tokens/pull/8", "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/2104/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": null} {"id": 1808116827, "node_id": "I_kwDOBm6k_c5rxaxb", "number": 2103, "title": "data attribute on Datasette tables exposing the primary key of the row", "user": {"value": 9599, "label": "simonw"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 0, "created_at": "2023-07-17T16:18:25Z", "updated_at": "2023-07-17T16:18:25Z", "closed_at": null, "author_association": "OWNER", "pull_request": null, "body": "Maybe put it on the `` but probably better to go on the `td.type-pk`.", "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/2103/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": null} {"id": 1805076818, "node_id": "I_kwDOBm6k_c5rl0lS", "number": 2102, "title": "API tokens with view-table but not view-database/view-instance cannot access the table", "user": {"value": 9599, "label": "simonw"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 7, "created_at": "2023-07-14T15:34:27Z", "updated_at": "2023-07-18T11:47:21Z", "closed_at": null, "author_association": "OWNER", "pull_request": null, "body": "> Spotted a problem while working on this: if you grant a token access to view table for a specific table but don't also grant view database and view instance permissions, that token is useless.\r\n>\r\n> This was a deliberate design decision in Datasette - it's documented on https://docs.datasette.io/en/1.0a2/authentication.html#access-permissions-in-metadata\r\n>\r\n>> If a user cannot access a specific database, they will not be able to access tables, views or queries within that database. If a user cannot access the instance they will not be able to access any of the databases, tables, views or queries.\r\n>\r\n> I'm now second-guessing if this was a good decision.\r\n\r\n_Originally posted by @simonw in https://github.com/simonw/datasette-auth-tokens/issues/7#issuecomment-1636031702_\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/2102/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": null} {"id": 1803264272, "node_id": "I_kwDOBm6k_c5re6EQ", "number": 2101, "title": "alter: true support for JSON write API", "user": {"value": 9599, "label": "simonw"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 1, "created_at": "2023-07-13T15:24:11Z", "updated_at": "2023-07-13T15:24:18Z", "closed_at": null, "author_association": "OWNER", "pull_request": null, "body": "Requested here: https://discord.com/channels/823971286308356157/823971286941302908/1129034187073134642\r\n\r\n> The former datasette-insert plugin had an option `?alter=1` to auto-add new columns. Does the JSON write API also have this?", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/2101/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": null} {"id": 1802613340, "node_id": "PR_kwDOBm6k_c5VZhfw", "number": 2100, "title": "Make primary key view accessible to render_cell hook", "user": {"value": 1563881, "label": "meowcat"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 0, "created_at": "2023-07-13T09:30:36Z", "updated_at": "2023-07-13T09:30:50Z", "closed_at": null, "author_association": "FIRST_TIME_CONTRIBUTOR", "pull_request": "simonw/datasette/pulls/2100", "body": "\r\n\r\n\r\n----\n:books: Documentation preview :books:: https://datasette--2100.org.readthedocs.build/en/2100/\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/2100/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": 1801394744, "node_id": "I_kwDOCGYnMM5rXxo4", "number": 567, "title": "Plugin system", "user": {"value": 15178711, "label": "asg017"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 2, "created_at": "2023-07-12T17:02:14Z", "updated_at": "2023-07-17T21:42:37Z", "closed_at": null, "author_association": "NONE", "pull_request": null, "body": "I'd like there to be a plugin system for sqlite-utils, similar to the datasette/llm plugins. I'd like to make plugins that would do things like:\r\n\r\n- Register SQLite extensions for more SQL functions + virtual tables\r\n- Register new subcommands\r\n- Different input file formats for `sqlite-utils memory`\r\n- Different output file formats (in addition to `--csv` `--tsv` `--nl` etc.\r\n\r\nA few real-world use-cases of plugins I'd like to see in sqlite-utils:\r\n\r\n- Register many of my sqlite extensions in sqlite-utils (`sqlite-http`, `sqlite-lines`, `sqlite-regex`, etc.)\r\n- New subcommands to work with `sqlite-vss` vector tables\r\n- Input/ouput Parquet/Avro/Arrow IPC files with `sqlite-arrow`", "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/567/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": null} {"id": 1798901709, "node_id": "PR_kwDOBm6k_c5VM2MK", "number": 2099, "title": "Bump black from 23.3.0 to 23.7.0", "user": {"value": 49699333, "label": "dependabot[bot]"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 0, "created_at": "2023-07-11T13:05:53Z", "updated_at": "2023-07-11T13:06:16Z", "closed_at": null, "author_association": "CONTRIBUTOR", "pull_request": "simonw/datasette/pulls/2099", "body": "Bumps [black](https://github.com/psf/black) from 23.3.0 to 23.7.0.\n
\nRelease notes\n

Sourced from black's releases.

\n
\n

23.7.0

\n

Highlights

\n\n

Stable style

\n\n

Preview style

\n\n

Configuration

\n\n

Packaging

\n\n

Parser

\n\n

Performance

\n\n

Output

\n\n
\n

... (truncated)

\n
\n
\nChangelog\n

Sourced from black's changelog.

\n
\n

23.7.0

\n

Highlights

\n\n

Stable style

\n\n

Preview style

\n\n

Configuration

\n\n

Packaging

\n\n

Parser

\n\n

Performance

\n\n

Output

\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=black&package-manager=pip&previous-version=23.3.0&new-version=23.7.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--2099.org.readthedocs.build/en/2099/\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/2099/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": 1796830110, "node_id": "PR_kwDOBm6k_c5VFw3j", "number": 2098, "title": "Bump blacken-docs from 1.14.0 to 1.15.0", "user": {"value": 49699333, "label": "dependabot[bot]"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 0, "created_at": "2023-07-10T13:49:12Z", "updated_at": "2023-07-10T13:49:31Z", "closed_at": null, "author_association": "CONTRIBUTOR", "pull_request": "simonw/datasette/pulls/2098", "body": "Bumps [blacken-docs](https://github.com/asottile/blacken-docs) from 1.14.0 to 1.15.0.\n
\nChangelog\n

Sourced from blacken-docs's changelog.

\n
\n

1.15.0 (2023-07-09)

\n\n
\n
\n
\nCommits\n\n
\n
\n\n\n[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=blacken-docs&package-manager=pip&previous-version=1.14.0&new-version=1.15.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--2098.org.readthedocs.build/en/2098/\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/2098/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": 1795219865, "node_id": "I_kwDOCGYnMM5rAOGZ", "number": 566, "title": "`--no-headers` doesn't work on most formats", "user": {"value": 33625, "label": "zellyn"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 2, "created_at": "2023-07-09T03:43:36Z", "updated_at": "2023-07-09T04:13:35Z", "closed_at": null, "author_association": "NONE", "pull_request": null, "body": "Version 3.33\r\n\r\n```\r\nsqlite-utils query library.db 'select asin from audible' --fmt plain --no-headers | head -3\r\nasin\r\n0062804006\r\n0062891421\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/566/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": null} {"id": 1795187493, "node_id": "I_kwDODLZ_YM5rAGMl", "number": 12, "title": "Switch to pyproject.toml", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 2, "created_at": "2023-07-09T01:06:56Z", "updated_at": "2023-07-09T01:19:43Z", "closed_at": "2023-07-09T01:19:42Z", "author_association": "MEMBER", "pull_request": null, "body": "First of my CLI tools to use https://til.simonwillison.net/python/pyproject", "repo": {"value": 213286752, "label": "pocket-to-sqlite"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/dogsheep/pocket-to-sqlite/issues/12/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": 1795051447, "node_id": "I_kwDOBm6k_c5q_k-3", "number": 2097, "title": "Drop Python 3.7", "user": {"value": 9599, "label": "simonw"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 0, "created_at": "2023-07-08T18:39:44Z", "updated_at": "2023-07-08T18:39:50Z", "closed_at": null, "author_association": "OWNER", "pull_request": null, "body": "> I'm going to drop Python 3.7.\r\n\r\n_Originally posted by @simonw in https://github.com/simonw/datasette/issues/1153#issuecomment-1627455892_\r\n\r\nIt's not supported any more: https://devguide.python.org/versions/", "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/2097/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": null} {"id": 1794604602, "node_id": "PR_kwDOBm6k_c5U-akg", "number": 2096, "title": "Clarify docs for descriptions in metadata", "user": {"value": 15906, "label": "garthk"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 0, "created_at": "2023-07-08T01:57:58Z", "updated_at": "2023-07-08T01:58:13Z", "closed_at": null, "author_association": "FIRST_TIME_CONTRIBUTOR", "pull_request": "simonw/datasette/pulls/2096", "body": "G'day! I got confused while debugging, earlier today. That's on me, but it does strike me a little repetition in the metadata documentation might help those flicking around it rather than reading it from top to bottom. No worries if you think otherwise.\r\n\r\n\r\n----\n:books: Documentation preview :books:: https://datasette--2096.org.readthedocs.build/en/2096/\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/2096/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": 1794097871, "node_id": "I_kwDOBm6k_c5q78LP", "number": 2095, "title": "Introduce \"dark mode\" CSS", "user": {"value": 3315059, "label": "jamietanna"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 0, "created_at": "2023-07-07T19:15:58Z", "updated_at": "2023-07-07T19:15:58Z", "closed_at": null, "author_association": "NONE", "pull_request": null, "body": "Using [the CSS media query `prefers-color-scheme`](https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme) we can provide a dark-mode version of Datasette", "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/2095/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": null} {"id": 1786258502, "node_id": "I_kwDOCGYnMM5qeCRG", "number": 565, "title": "Table renaming utilities", "user": {"value": 9599, "label": "simonw"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 1, "created_at": "2023-07-03T14:07:42Z", "updated_at": "2023-07-03T14:09:31Z", "closed_at": null, "author_association": "OWNER", "pull_request": null, "body": "> I find myself wanting two new features in `sqlite-utils`:\r\n> - The ability to have the new transformed table set to a specific name, while keeping the old table around\r\n> - The ability to rename a table (`sqlite-utils` doesn't have a table rename function at all right now)\r\n\r\n_Originally posted by @simonw in https://github.com/simonw/llm/issues/65#issuecomment-1618375042_\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/565/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": null} {"id": 1786243905, "node_id": "I_kwDOCGYnMM5qd-tB", "number": 564, "title": "Document that running `db.transform()` tidies up the schema indentation", "user": {"value": 9599, "label": "simonw"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 0, "created_at": "2023-07-03T13:59:28Z", "updated_at": "2023-07-03T13:59:33Z", "closed_at": null, "author_association": "OWNER", "pull_request": null, "body": "> ... and it turns out running `.transform()` with no arguments still fixes the format of the schema!\r\n\r\n```pycon\r\n>>> db[\"log\"].add_column(\"foo\", str)\r\n\r\n>>> db[\"log\"].add_column(\"bar\", str)\r\n
\r\n>>> db[\"log\"].add_column(\"baz\", str)\r\n
\r\n>>> print(db[\"log\"].schema)\r\nCREATE TABLE \"log\" (\r\n [id] INTEGER PRIMARY KEY,\r\n [name2] TEXT,\r\n [age] INTEGER,\r\n [weight] FLOAT\r\n, [foo] TEXT, [bar] TEXT, [baz] TEXT)\r\n>>> db[\"log\"].transform()\r\n
\r\n>>> print(db[\"log\"].schema)\r\nCREATE TABLE \"log\" (\r\n [id] INTEGER PRIMARY KEY,\r\n [name2] TEXT,\r\n [age] INTEGER,\r\n [weight] FLOAT,\r\n [foo] TEXT,\r\n [bar] TEXT,\r\n [baz] TEXT\r\n)\r\n```\r\n\r\n_Originally posted by @simonw in https://github.com/simonw/llm/issues/65#issuecomment-1618347727_\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/564/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": null} {"id": 1785360409, "node_id": "I_kwDOCGYnMM5qanAZ", "number": 563, "title": "`--empty-null` option when importing CSV", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 1, "created_at": "2023-07-03T05:23:36Z", "updated_at": "2023-07-03T05:44:43Z", "closed_at": "2023-07-03T05:42:30Z", "author_association": "OWNER", "pull_request": null, "body": "CSV files with empty cells in (which come through as the empty string) are common and a bit gross.\r\n\r\nHaving an option that means \"and if it's an empty string store `null` instead) would be cool.\r\n\r\nI brainstormed name options here https://chat.openai.com/share/c947b738-ee7d-419c-af90-bc84e90987da", "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/563/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": 1784794489, "node_id": "I_kwDOCGYnMM5qYc15", "number": 562, "title": "Explore the intersection between sqlite-utils and dataclasses", "user": {"value": 9599, "label": "simonw"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 1, "created_at": "2023-07-02T19:23:08Z", "updated_at": "2023-07-02T19:26:39Z", "closed_at": null, "author_association": "OWNER", "pull_request": null, "body": "> Aside: this makes me think it might be cool if `sqlite-utils` had a way of working with dataclasses rather than just dicts, and knew how to create a SQLite table to match a dataclass and maybe how to code-generate dataclasses for a specific table schema (dynamically or even using code-generation that can be written to disk, for better editor integrations).\r\n\r\n_Originally posted by @simonw in https://github.com/simonw/llm/issues/65#issuecomment-1616742529_\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/562/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": null} {"id": 1783304750, "node_id": "I_kwDOBm6k_c5qSxIu", "number": 2094, "title": "JS Plugin Hooks for the Code Editor", "user": {"value": 15178711, "label": "asg017"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 0, "created_at": "2023-07-01T00:51:57Z", "updated_at": "2023-07-01T00:51:57Z", "closed_at": null, "author_association": "CONTRIBUTOR", "pull_request": null, "body": "When #2052 merges, I'd like to add support to add extensions/functions to the Datasette code editor. \r\n\r\nI'd eventually like to build a JS plugin for [`sqlite-docs`](https://github.com/asg017/sqlite-docs), to add things like:\r\n\r\n- Inline documentation for tables/columns on hover\r\n- Inline docs for custom functions that are loaded in\r\n- More detailed autocomplete for tables/columns/functions\r\n\r\nI did some hacking to see what this would look like, see here:\r\n\r\n\"image\"\r\n\"image\"\r\n\r\nThere can be a new hook that allows JS plugins to add new \"extension\" in the CodeMirror editorview here:\r\n\r\nhttps://github.com/simonw/datasette/blob/8cd60fd1d899952f1153460469b3175465f33f80/datasette/static/cm-editor-6.0.1.js#L25\r\n\r\nWill need some more planning. For example, the Codemirror bundle in Datasette has functions that we could re-export for plugins to use (so we don't load 2 version of `\"@codemirror/autocomplete\"`, for example. ", "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/2094/reactions\", \"total_count\": 1, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 1, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": null} {"id": 1781530343, "node_id": "I_kwDOBm6k_c5qL_7n", "number": 2093, "title": "Proposal: Combine settings, metadata, static, etc. into a single `datasette.toml` File", "user": {"value": 15178711, "label": "asg017"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 7, "created_at": "2023-06-29T21:18:23Z", "updated_at": "2023-07-02T02:17:47Z", "closed_at": null, "author_association": "CONTRIBUTOR", "pull_request": null, "body": "Very often I get tripped up when trying to configure my Datasette instances. For example: if I want to change the port my app listen too, do I do that with a CLI flag, a `--setting` flag, inside `metadata.json`, or an env var? If I want to up the time limit of SQL statements, is that under `metadata.json` or a setting? Where does my plugin configuration go?\r\n\r\nNormally I need to look it up in Datasette docs, and I quickly find my answer, but the number of places where \"config\" goes it overwhelming.\r\n\r\n- Flat CLI flags like `--port`, `--host`, `--cors`, etc.\r\n- `--setting`, like `default_page_size`, `sql_time_limit_ms` etc\r\n- Inside `metadata.json`, including plugin configuration\r\n\r\nTypically my Datasette deploys are extremely long shell commands, with multiple `--setting` and other CLI flags.\r\n\r\n## Proposal: Consolidate all \"config\" into `datasette.toml`\r\n\r\nI propose that we add a new `datasette.toml` that combines \"settings\", \"metadata\", and other common CLI flags like `--port` and `--cors` into a single file. It would be similar to \"Cargo.toml\" in Rust projects, \"package.json\" in Node projects, and \"pyproject.toml\" in Python, etc.\r\n\r\nA sample of what it could look like:\r\n\r\n```toml\r\n# \"top level\" configuration that are currently CLI flags on `datasette serve`\r\n[config]\r\nport = 8020\r\nhost = \"0.0.0.0\"\r\ncors = true\r\n\r\n# replaces multiple `--setting` flags\r\n[settings]\r\nbase_url = \"/app/datasette/\"\r\ndefault_allow_sql = true\r\nsql_time_limit_ms = 3500\r\n\r\n# replaces `metadata.json`.\r\n# The contents of datasette-metadata.json could be defined in this file instead, but supporting separate files is nice (since those are easy to machine-generate)\r\n[metadata]\r\ninclude=\"./datasette-metadata.json\"\r\n\r\n# plugin-specific \r\n[plugins]\r\n[plugins.datasette-auth-github]\r\nclient_id = {env = \"DATASETTE_AUTH_GITHUB_CLIENT_ID\"}\r\nclient_secret = {env = \"GITHUB_CLIENT_SECRET\"}\r\n\r\n[plugins.datasette-cluster-map]\r\n\r\nlatitude_column = \"lat\"\r\nlongitude_column = \"lon\"\r\n```\r\n\r\n## Pros\r\n- Instead of multiple files and CLI flags, everything could be in one tidy file\r\n- Editing config in a separate file is easier than editing CLI flags, since you don't have to kill a process + edit a command every time\r\n- New users will know \"just edit my `datasette.toml` instead of needing to learn metadata + settings + CLI flags\r\n- Better dev experience for multiple environment. For example, could have `datasette -c datasette-dev.toml` for local dev environments (enables SQL, debug plugins, long timeouts, etc.), and a `datasette -c datasette-prod.toml` for \"production\" (lower timeouts, less plugins, monitoring plugins, etc.)\r\n\r\n## Cons\r\n- Yet another config-management system. Now Datasette users will need to know about metadata, settings, CLI flags, _and_ `datasette.toml`. However with enough documentation + announcements + examples, I think we can get ahead of it.\r\n- If toml is chosen, would need to add a toml parser for Python version <3.11\r\n- Multiple sources of config require priority. For example: Would `--setting default_allow_sql off` override the value inside `[settings]`? What about `--port`? \r\n\r\n## Other Notes\r\n\r\n### Toml\r\n\r\nI chose toml over json because toml supports comments. I chose toml over yaml because Python 3.11 has builtin support for it. I also find toml easier to work with since it doesn't have the odd \"gotchas\" that YAML has (\"ex `3.10` resolving to `3.1`, Norway `NO` resolving to `false`, etc.). It also mimics `pyproject.toml` which is nice. Happy to change my mind about this however\r\n\r\n\r\n### Plugin config will be difficult\r\n\r\nPlugin config is currently in `metadata.json` in two places:\r\n\r\n1. Top level, under `\"plugins.[plugin-name]\"`. This fits well into `datasette.toml` as `[plugins.plugin-name]`\r\n2. Table level, under `\"databases.[db-name].tables.[table-name].plugins.[plugin-name]`. This doesn't fit that well into `datasette.toml`, unless it's nested under `[metadata]`?\r\n\r\n### Extensions, static, one-off plugins?\r\n\r\nWe could also include equivalents of `--plugins-dir`, `--static`, and `--load-extension` into `datasette.toml`, but I'd imagine there's a few security concerns there to think through. \r\n\r\n\r\n### Explicitly list with plugins to use?\r\n\r\nI believe Datasette by default will load all install plugins on startup, but maybe `datasette.toml` can specify a list of plugins to use? For example, a dev version of `datasette.toml` can specify `datasette-pretty-traces`, but the prod version can leave it out", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/2093/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": null} {"id": 1781047747, "node_id": "I_kwDOBm6k_c5qKKHD", "number": 2092, "title": "test_homepage intermittent failure", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 2, "created_at": "2023-06-29T15:20:37Z", "updated_at": "2023-06-29T15:26:28Z", "closed_at": "2023-06-29T15:24:13Z", "author_association": "OWNER", "pull_request": null, "body": "e.g. in https://github.com/simonw/datasette/actions/runs/5413590227/jobs/9839373852\r\n\r\n```\r\n=================================== FAILURES ===================================\r\n________________________________ test_homepage _________________________________\r\n[gw0] linux -- Python 3.7.17 /opt/hostedtoolcache/Python/3.7.17/x64/bin/python\r\n\r\nds_client = \r\n\r\n @pytest.mark.asyncio\r\n async def test_homepage(ds_client):\r\n response = await ds_client.get(\"/.json\")\r\n assert response.status_code == 200\r\n assert \"application/json; charset=utf-8\" == response.headers[\"content-type\"]\r\n data = response.json()\r\n assert data.keys() == {\"fixtures\": 0}.keys()\r\n d = data[\"fixtures\"]\r\n assert d[\"name\"] == \"fixtures\"\r\n assert d[\"tables_count\"] == 24\r\n assert len(d[\"tables_and_views_truncated\"]) == 5\r\n assert d[\"tables_and_views_more\"] is True\r\n # 4 hidden FTS tables + no_primary_key (hidden in metadata)\r\n assert d[\"hidden_tables_count\"] == 6\r\n # 201 in no_primary_key, plus 6 in other hidden tables:\r\n> assert d[\"hidden_table_rows_sum\"] == 207, data\r\nE AssertionError: {'fixtures': {'color': '9403e5', 'hash': None, 'hidden_table_rows_sum': 0, 'hidden_tables_count': 6, ...}}\r\nE assert 0 == 207\r\n```\r\nMy guess is that this is a timing error, where very occasionally the \"count rows but stop counting if it exceeds a time limit\" thing fails.", "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/2092/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": 1781022369, "node_id": "I_kwDOBm6k_c5qKD6h", "number": 2091, "title": "Drop support for Python 3.7", "user": {"value": 9599, "label": "simonw"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 2, "created_at": "2023-06-29T15:06:38Z", "updated_at": "2023-06-29T15:18:34Z", "closed_at": null, "author_association": "OWNER", "pull_request": null, "body": "It's EOL now, as of 2023-06-27 (two days ago): https://devguide.python.org/versions/\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/2091/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": null} {"id": 1781005740, "node_id": "I_kwDOBm6k_c5qJ_2s", "number": 2090, "title": "Adopt ruff for linting", "user": {"value": 9599, "label": "simonw"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 2, "created_at": "2023-06-29T14:56:43Z", "updated_at": "2023-06-29T15:05:04Z", "closed_at": null, "author_association": "OWNER", "pull_request": null, "body": "https://beta.ruff.rs/docs/", "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/2090/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": null} {"id": 1780973290, "node_id": "I_kwDOBm6k_c5qJ37q", "number": 2089, "title": "codespell test failure", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 5, "created_at": "2023-06-29T14:40:10Z", "updated_at": "2023-06-29T14:48:11Z", "closed_at": "2023-06-29T14:48:10Z", "author_association": "OWNER", "pull_request": null, "body": "https://github.com/simonw/datasette/actions/runs/5413443676/jobs/9838999356\r\n```\r\n codespell docs/*.rst --ignore-words docs/codespell-ignore-words.txt\r\n codespell datasette -S datasette/static --ignore-words docs/codespell-ignore-words.txt\r\n shell: /usr/bin/bash -e {0}\r\n env:\r\n pythonLocation: /opt/hostedtoolcache/Python/3.9.17/x64\r\n LD_LIBRARY_PATH: /opt/hostedtoolcache/Python/3.9.17/x64/lib\r\ndocs/metadata.rst:192: displaing ==> displaying\r\n```\r\nThis failure is legit, it found a spelling mistake: https://github.com/simonw/datasette/blob/ede62036180993dbd9d4e5d280fc21c183cda1c3/docs/metadata.rst#L192", "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/2089/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": 1777548699, "node_id": "I_kwDOCGYnMM5p8z2b", "number": 561, "title": "`--stop-after` option for `insert` and `upsert` commands", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 1, "created_at": "2023-06-27T18:44:15Z", "updated_at": "2023-06-27T18:50:09Z", "closed_at": "2023-06-27T18:50:08Z", "author_association": "OWNER", "pull_request": null, "body": "I found myself wanting to insert rows from a 849MB CSV file without processing the whole thing: https://huggingface.co/datasets/jerpint-org/HackAPrompt-Playground-Submissions/tree/main", "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/561/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": 1773458985, "node_id": "PR_kwDOCGYnMM5T2mMb", "number": 560, "title": "Use sqlean if available in environment", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 10, "created_at": "2023-06-25T19:48:48Z", "updated_at": "2023-06-26T08:21:00Z", "closed_at": "2023-06-25T23:25:51Z", "author_association": "OWNER", "pull_request": "simonw/sqlite-utils/pulls/560", "body": "Refs:\r\n- #559 \r\n\r\n\r\n----\n:books: Documentation preview :books:: https://sqlite-utils--560.org.readthedocs.build/en/560/\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/560/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": 1773450152, "node_id": "I_kwDOCGYnMM5ptLOo", "number": 559, "title": "sqlean support", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 0, "created_at": "2023-06-25T19:27:26Z", "updated_at": "2023-06-25T23:25:53Z", "closed_at": "2023-06-25T23:25:53Z", "author_association": "OWNER", "pull_request": null, "body": "If sqlean is available, use that.\r\n\r\nRefs:\r\n- https://github.com/nalgeon/sqlean.py/issues/1#issuecomment-1605707788\r\n\r\nThis will provide a good workaround for:\r\n- #235 ", "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/559/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": 1765870617, "node_id": "I_kwDOBm6k_c5pQQwZ", "number": 2087, "title": "`--settings settings.json` option", "user": {"value": 9599, "label": "simonw"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 2, "created_at": "2023-06-20T17:48:45Z", "updated_at": "2023-07-14T17:02:03Z", "closed_at": null, "author_association": "OWNER", "pull_request": null, "body": "https://discord.com/channels/823971286308356157/823971286941302908/1120705940728066080\r\n\r\n> May I add a request to the whole metadata / settings ? Allow to pass `--settings path/to/settings.json` instead of having to rely exclusively on directory mode to centralize settings (this would reflect the behavior of providing metadata)", "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/2087/reactions\", \"total_count\": 1, \"+1\": 1, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": null} {"id": 1764792125, "node_id": "I_kwDOBm6k_c5pMJc9", "number": 2086, "title": "Show information on startup in directory configuration mode", "user": {"value": 9599, "label": "simonw"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 0, "created_at": "2023-06-20T07:13:33Z", "updated_at": "2023-06-20T07:13:33Z", "closed_at": null, "author_association": "OWNER", "pull_request": null, "body": "https://discord.com/channels/823971286308356157/823971286941302908/1120516587036889098\r\n\r\n> One thing that would be helpful would be message at launch indicating a metadata.json is getting picked up. I'm using directory mode and was editing the wrong file for awhile before I realize nothing I was doing was having any effect.", "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/2086/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": null} {"id": 1762180409, "node_id": "I_kwDOBm6k_c5pCL05", "number": 2085, "title": "Interactive row selection in Datasette ", "user": {"value": 24938923, "label": "learning4life"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 0, "created_at": "2023-06-18T08:29:45Z", "updated_at": "2023-06-18T08:31:23Z", "closed_at": null, "author_association": "NONE", "pull_request": null, "body": "Simon did a excellent [prototype](https://til.simonwillison.net/datasette/row-selection-prototype) of an interactive row selection in Datasette.\r\n\r\nI hope this [functionality](https://camo.githubusercontent.com/3d4a0f31fb6a27fd279f809af5b53dc3b76faa63c7721e228951c5252b645a77/68747470733a2f2f7374617469632e73696d6f6e77696c6c69736f6e2e6e65742f7374617469632f323032332f6461746173657474652d7069636b65722e676966) can be turned into a Datasette plugin.\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/2085/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": null} {"id": 1761613778, "node_id": "I_kwDOBm6k_c5pABfS", "number": 2084, "title": "Support facets for columns that contain timestamps", "user": {"value": 19492893, "label": "devxpy"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 0, "created_at": "2023-06-17T03:33:54Z", "updated_at": "2023-06-17T03:33:54Z", "closed_at": null, "author_association": "NONE", "pull_request": null, "body": "\r\nDjango has this very nice filter for datetime fields -\r\n\r\n\"image\"\r\n\r\nIt would be nice to have something similar to facet by a field that contains a timestamp in datasette too - Which doesn't seem to do anything with timestamps right now...\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/2084/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": null} {"id": 1756975532, "node_id": "PR_kwDOBm6k_c5S_5Jl", "number": 2083, "title": "Bump blacken-docs from 1.13.0 to 1.14.0", "user": {"value": 49699333, "label": "dependabot[bot]"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 0, "created_at": "2023-06-14T13:57:52Z", "updated_at": "2023-06-29T14:31:55Z", "closed_at": "2023-06-29T14:31:54Z", "author_association": "CONTRIBUTOR", "pull_request": "simonw/datasette/pulls/2083", "body": "Bumps [blacken-docs](https://github.com/asottile/blacken-docs) from 1.13.0 to 1.14.0.\n
\nChangelog\n

Sourced from blacken-docs's changelog.

\n
\n

1.14.0 (2023-06-13)

\n
    \n
  • Support Python 3.12.
  • \n
\n
\n
\n
\nCommits\n\n
\n
\n\n\n[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=blacken-docs&package-manager=pip&previous-version=1.13.0&new-version=1.14.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--2083.org.readthedocs.build/en/2083/\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/2083/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": 1754174496, "node_id": "I_kwDOCGYnMM5ojpQg", "number": 558, "title": "Ability to define unique columns when creating a table", "user": {"value": 1910303, "label": "aguinane"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 0, "created_at": "2023-06-13T06:56:19Z", "updated_at": "2023-06-13T06:56:19Z", "closed_at": null, "author_association": "NONE", "pull_request": null, "body": "When creating a new table, it would be good to have an option to set unique columns similar to how not_null is set.\r\n\r\n```python\r\nfrom sqlite_utils import Database\r\n\r\ncolumns = {\"mRID\": str, \"name\": str}\r\ndb = Database(\"example.db\")\r\ndb[\"ExampleTable\"].create(columns, pk=\"mRID\", not_null=[\"mRID\"], if_not_exists=True)\r\ndb[\"ExampleTable\"].create_index([\"mRID\"], unique=True, if_not_exists=True)\r\n```\r\n\r\nSo something like this would add the UNIQUE flag to the table definition. \r\n\r\n```python\r\ndb[\"ExampleTable\"].create(columns, pk=\"mRID\", not_null=[\"mRID\"], unique=[\"mRID\"], if_not_exists=True)\r\n```\r\n\r\n```sql\r\nCREATE TABLE ExampleTable (\r\n mRID TEXT PRIMARY KEY\r\n NOT NULL\r\n UNIQUE,\r\n name TEXT\r\n);\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/558/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": null} {"id": 1751214236, "node_id": "I_kwDOC8SPRc5oYWic", "number": 36, "title": "Getting sqlite_master may not be modified when creating dogsheep index", "user": {"value": 8711912, "label": "khushmeeet"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 0, "created_at": "2023-06-11T03:21:53Z", "updated_at": "2023-06-11T03:21:53Z", "closed_at": null, "author_association": "NONE", "pull_request": null, "body": "When creating a `dogsheep` index from `config.yml` file on pocket.db (created using pocket-to-sqlite), I am getting this error\r\n\r\n```\r\nTraceback (most recent call last):\r\n File \"/Users/khushmeeet/.pyenv/versions/3.11.2/bin/dogsheep-beta\", line 8, in \r\n sys.exit(cli())\r\n ^^^^^\r\n File \"/Users/khushmeeet/.pyenv/versions/3.11.2/lib/python3.11/site-packages/click/core.py\", line 1130, in __call__\r\n return self.main(*args, **kwargs)\r\n ^^^^^^^^^^^^^^^^^^^^^^^^^^\r\n File \"/Users/khushmeeet/.pyenv/versions/3.11.2/lib/python3.11/site-packages/click/core.py\", line 1055, in main\r\n rv = self.invoke(ctx)\r\n ^^^^^^^^^^^^^^^^\r\n File \"/Users/khushmeeet/.pyenv/versions/3.11.2/lib/python3.11/site-packages/click/core.py\", line 1657, in invoke\r\n return _process_result(sub_ctx.command.invoke(sub_ctx))\r\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\r\n File \"/Users/khushmeeet/.pyenv/versions/3.11.2/lib/python3.11/site-packages/click/core.py\", line 1404, in invoke\r\n return ctx.invoke(self.callback, **ctx.params)\r\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\r\n File \"/Users/khushmeeet/.pyenv/versions/3.11.2/lib/python3.11/site-packages/click/core.py\", line 760, in invoke\r\n return __callback(*args, **kwargs)\r\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^\r\n File \"/Users/khushmeeet/.pyenv/versions/3.11.2/lib/python3.11/site-packages/dogsheep_beta/cli.py\", line 36, in index\r\n run_indexer(\r\n File \"/Users/khushmeeet/.pyenv/versions/3.11.2/lib/python3.11/site-packages/dogsheep_beta/utils.py\", line 32, in run_indexer\r\n ensure_table_and_indexes(db, tokenize)\r\n File \"/Users/khushmeeet/.pyenv/versions/3.11.2/lib/python3.11/site-packages/dogsheep_beta/utils.py\", line 91, in ensure_table_and_indexes\r\n table.add_foreign_key(*fk)\r\n File \"/Users/khushmeeet/.pyenv/versions/3.11.2/lib/python3.11/site-packages/sqlite_utils/db.py\", line 2155, in add_foreign_key\r\n self.db.add_foreign_keys([(self.name, column, other_table, other_column)])\r\n File \"/Users/khushmeeet/.pyenv/versions/3.11.2/lib/python3.11/site-packages/sqlite_utils/db.py\", line 1116, in add_foreign_keys\r\n cursor.execute(\r\nsqlite3.OperationalError: table sqlite_master may not be modified\r\n```\r\n\r\nCommand I ran to get this error\r\n```\r\ndogsheep-beta index pocket.db config.yml\r\n```\r\n\r\nDogsheep version\r\n```\r\ndogsheep-beta, version 0.10.2\r\n```\r\n\r\nPython version \r\n```\r\nPython 3.11.2\r\n```", "repo": {"value": 197431109, "label": "dogsheep-beta"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/dogsheep/dogsheep-beta/issues/36/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": null} {"id": 1740150327, "node_id": "I_kwDOCGYnMM5nuJY3", "number": 557, "title": "Aliased ROWID option for tables created from alter=True commands", "user": {"value": 7908073, "label": "chapmanjacobd"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 2, "created_at": "2023-06-04T05:29:28Z", "updated_at": "2023-06-14T06:09:21Z", "closed_at": "2023-06-05T19:26:26Z", "author_association": "CONTRIBUTOR", "pull_request": null, "body": "> If you use INTEGER PRIMARY KEY column, the VACUUM does not change the values of that column. However, if you use unaliased rowid, the VACUUM command will reset the rowid values.\r\n\r\nROWID should never be used with foreign keys but the simple act of aliasing rowid to id (which is what happens when one does `id integer primary key` DDL) makes it OK.\r\n\r\nIt would be convenient if there were more options to use a string column (eg. filepath) as the PK, and be able to use it during upserts, but when creating a foreign key, to create an integer column which aliases rowid\r\n\r\nI made an attempt to switch to integer primary keys here but it is not going well... In my usecase the path column is a business key. Yes, it should be as simple as including the `id` column in any select statement where I plan on using `upsert` but it would be nice if this could be abstracted away somehow https://github.com/chapmanjacobd/library/commit/788cd125be01d76f0fe2153335d9f6b21db1343c\r\n\r\nhttps://github.com/chapmanjacobd/library/actions/runs/5173602136/jobs/9319024777", "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/557/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": 1740026046, "node_id": "I_kwDOCGYnMM5ntrC-", "number": 556, "title": "Support storing incrementally piped values", "user": {"value": 601708, "label": "mcint"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 1, "created_at": "2023-06-04T00:45:23Z", "updated_at": "2023-06-04T01:21:15Z", "closed_at": null, "author_association": "CONTRIBUTOR", "pull_request": null, "body": "I'm trying to use sqlite-utils to data generated incrementally. There are a few\naspects of this that I don't currently know how to handle. I would like an option\nto apply writes incrementally, line-by-line as they are received. I would like an\noption to echo incremental progress. And, it would be nice to have \n\nIn particular, I'm using CoreLocationCLI -w -j to generate, newline-delimited JSON.\n\nOne variant of the command \n\n`stdbuf -oL CoreLocationCLI -w -j | pee 'sqlite-utils insert loc.db loc -' nl`\n\n`pee`, from `moreutils`, is like `tee` but spawns and pipes to the processes\ncreated by invoking each of its arguments, so, for gratuitous demonstration,\n`pee 'sponge out.log' cat` would behave like `tee`.\n\nIt looks like I can get what I want with:\n`stdbuf -oL CoreLocationCLI -w -j | while read line; do <<<\"$line\" sqlite-utils insert loc.db loc -; echo \"$line\"; done | nl`\n\n\n\n\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/556/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": null} {"id": 1734786661, "node_id": "PR_kwDOBm6k_c5R0fcK", "number": 2082, "title": "Catch query interrupted on facet suggest row count", "user": {"value": 10843208, "label": "redraw"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 0, "created_at": "2023-05-31T18:42:46Z", "updated_at": "2023-05-31T18:45:26Z", "closed_at": null, "author_association": "FIRST_TIME_CONTRIBUTOR", "pull_request": "simonw/datasette/pulls/2082", "body": "Just like facet's `suggest()` is trapping `QueryInterrupted` for facet columns, we also need to trap `get_row_count()`, which can reach timeout if database tables are big enough. \r\n\r\nI've included `get_columns()` inside the block as that's just another query, despite it's a really cheap one and might never raise the exception.\r\n\r\n\r\n----\r\n:books: Documentation preview :books:: https://datasette--2082.org.readthedocs.build/en/2082/\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/2082/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": 1733198948, "node_id": "I_kwDOCGYnMM5nToRk", "number": 555, "title": "Filter table by a large bunch of ids", "user": {"value": 10843208, "label": "redraw"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 1, "created_at": "2023-05-31T00:29:51Z", "updated_at": "2023-06-14T22:01:57Z", "closed_at": null, "author_association": "NONE", "pull_request": null, "body": "Hi! this might be a question related to both SQLite & sqlite-utils, and you might be more experienced with them.\r\n\r\nI have a large bunch of ids, and I'm wondering which is the best way to query them in terms of performance, and simplicity if possible.\r\n\r\nThe naive approach would be something like `select * from table where rowid in (?, ?, ?...)` but that wouldn't scale if ids are >1k.\r\n\r\nAnother approach might be creating a temp table, or in-memory db table, insert all ids in that table and then join with the target one.\r\n\r\nI failed to attach an in-memory db both using sqlite-utils, and plain sql's execute(), so my closest approach is something like,\r\n\r\n```python\r\ndef filter_existing_video_ids(video_ids):\r\n db = get_db() # contains a \"videos\" table\r\n db.execute(\"CREATE TEMPORARY TABLE IF NOT EXISTS tmp (video_id TEXT NOT NULL PRIMARY KEY)\")\r\n db[\"tmp\"].insert_all([{\"video_id\": video_id} for video_id in video_ids])\r\n for row in db[\"tmp\"].rows_where(\"video_id not in (select video_id from videos)\"):\r\n yield row[\"video_id\"]\r\n db[\"tmp\"].drop()\r\n```\r\n\r\nThat kinda worked, I couldn't find an option in sqlite-utils's `create_table()` to tell it's a temporary table. Also, `tmp` table is not dropped finally, neither using `.drop()` despite being created with the keyword `TEMPORARY`. I believe it should be automatically dropped after connection/session ends though I read.", "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/555/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": null} {"id": 1727478903, "node_id": "I_kwDOBm6k_c5m9zx3", "number": 2081, "title": "Update Endpoints defined in metadata throws 403 Forbidden after a while", "user": {"value": 15085007, "label": "cutmasta-kun"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 0, "created_at": "2023-05-26T11:52:30Z", "updated_at": "2023-05-26T11:52:30Z", "closed_at": null, "author_association": "NONE", "pull_request": null, "body": "Hello. I expose an endpoint to update `tasks`:\r\n```\r\n{\r\n \"title\": \"My Datasette Instance\",\r\n \"databases\": {\r\n \"tasks\": {\r\n \"queries\": {\r\n \"update_task\": {\r\n \"sql\": \"UPDATE tasks SET status = :status, result = :result, systemMessage = :systemMessage WHERE queueID = :queueID\",\r\n \"write\": true,\r\n \"on_success_message\": \"Task updated\",\r\n \"on_success_redirect\": \"/tasks/tasks.json\",\r\n \"on_error_message\": \"Task update failed\",\r\n \"on_error_redirect\": \"/tasks.json\",\r\n \"params\": [\"queueID\", \"taskData\", \"status\", \"result\", \"systemMessage\"]\r\n }\r\n }\r\n }\r\n }\r\n}\r\n```\r\n\r\nThis works really well! But after a while, the Datasette Instanz answers with **403 Forbidden**.\r\nI have to delete the database and recreate it in order to work again.\r\n\r\nAny help here? (\u00b4\u3002\uff3f\u3002\uff40)", "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/2081/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": null} {"id": 1726603778, "node_id": "PR_kwDOBm6k_c5RYvTU", "number": 2080, "title": "New View base class", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 3, "created_at": "2023-05-25T23:22:55Z", "updated_at": "2023-05-26T00:18:45Z", "closed_at": "2023-05-26T00:18:44Z", "author_association": "OWNER", "pull_request": "simonw/datasette/pulls/2080", "body": "Refs:\r\n\r\n- #2078\r\n\r\nTODO:\r\n\r\n- [x] Teach router layer how to handle this\r\n- [x] Use it for something\r\n\r\n\r\n----\r\n:books: Documentation preview :books:: https://datasette--2080.org.readthedocs.build/en/2080/\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/2080/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": 0, "state_reason": null} {"id": 1726531350, "node_id": "I_kwDOBm6k_c5m6McW", "number": 2079, "title": "Datasette should serve Access-Control-Max-Age", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 8, "created_at": "2023-05-25T21:50:50Z", "updated_at": "2023-05-25T22:56:28Z", "closed_at": "2023-05-25T22:08:35Z", "author_association": "OWNER", "pull_request": null, "body": "Currently the CORS headers served are:\r\n\r\nhttps://github.com/simonw/datasette/blob/9584879534ff0556e04e4c420262972884cac87b/datasette/utils/__init__.py#L1139-L1143\r\n\r\nServing `Access-Control-Max-Age: 600` would allow browsers to cache that for 10 minutes, avoiding additional CORS pre-flight OPTIONS requests during that time.", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/2079/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"} {"id": 1726236847, "node_id": "I_kwDOBm6k_c5m5Eiv", "number": 2078, "title": "Resolve the difference between `wrap_view()` and `BaseView`", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 16, "created_at": "2023-05-25T17:44:32Z", "updated_at": "2023-05-26T00:18:46Z", "closed_at": "2023-05-26T00:18:46Z", "author_association": "OWNER", "pull_request": null, "body": "There are two patterns for implementing views in Datasette at the moment. I want to combine those.\r\n\r\nPart of:\r\n- #2053", "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/2078/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": 1720096994, "node_id": "I_kwDOCGYnMM5mhpji", "number": 554, "title": "`IndexError` when doing `.insert(..., pk='id')` after `insert_all`", "user": {"value": 1231935, "label": "xavdid"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 1, "created_at": "2023-05-22T17:13:02Z", "updated_at": "2023-05-22T17:18:33Z", "closed_at": null, "author_association": "NONE", "pull_request": null, "body": "I believe this is related to https://github.com/simonw/sqlite-utils/issues/98.\r\n\r\nWhen `pk` is specified by table A's `insert` call, it throws an index error if a different table has written a row with a higher rowid than exists in the first table. Here's a basic example:\r\n\r\n```py\r\nfrom sqlite_utils import Database\r\n\r\n\r\ndef test_pk_for_insert(fresh_db):\r\n user = {\"id\": \"abc\", \"name\": \"david\"}\r\n\r\n fresh_db[\"users\"].insert(user, pk=\"id\")\r\n\r\n fresh_db[\"comments\"].insert_all(\r\n [\r\n {\"id\": \"def\", \"text\": \"ok\"},\r\n {\"id\": \"ghi\", \"text\": \"great\"},\r\n ],\r\n )\r\n\r\n fresh_db[\"users\"].insert(\r\n user,\r\n ignore=True,\r\n # BUG: when specifying pk on the second insert call \r\n # db.py goes into a block it doesn't expect and we get the error\r\n pk=\"id\",\r\n )\r\n\r\n\r\nif __name__ == \"__main__\":\r\n db = Database(\"bug.db\")\r\n if db[\"users\"].exists():\r\n raise ValueError(\r\n \"bug only shows on a new database - remove bug.db before running the script\"\r\n )\r\n test_pk_for_insert(db)\r\n```\r\n\r\nThe error is:\r\n\r\n```py\r\n File \"/Users/david/projects/reddit-to-sqlite/.venv/lib/python3.11/site-packages/sqlite_utils/db.py\", line 2960, in insert_chunk\r\n row = list(self.rows_where(\"rowid = ?\", [self.last_rowid]))[0]\r\n ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^\r\nIndexError: list index out of range\r\n```\r\n\r\nThe issue is in this block: \r\n\r\nhttps://github.com/simonw/sqlite-utils/blob/2747257a3334d55e890b40ec58fada57ae8cfbfd/sqlite_utils/db.py#L2954-L2958\r\n\r\nrelevant locals are:\r\n\r\n- `pk`: `'id'`\r\n- `result.lastrowid`: `2`\r\n\r\nWhat's most interesting is the comment `# self.last_rowid will be 0 if a \"INSERT OR IGNORE\" happened`, which doesn't seem to be the case here. ", "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/554/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": null} {"id": 1719759468, "node_id": "PR_kwDOBm6k_c5RBXH_", "number": 2077, "title": "Bump furo from 2023.3.27 to 2023.5.20", "user": {"value": 49699333, "label": "dependabot[bot]"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 2, "created_at": "2023-05-22T13:58:16Z", "updated_at": "2023-06-29T14:40:35Z", "closed_at": null, "author_association": "CONTRIBUTOR", "pull_request": "simonw/datasette/pulls/2077", "body": "Bumps [furo](https://github.com/pradyunsg/furo) from 2023.3.27 to 2023.5.20.\n
\nChangelog\n

Sourced from furo's changelog.

\n
\n

Changelog

\n\n

2023.05.20 -- Unassuming Ultramarine

\n
    \n
  • \u2728 Add support for Sphinx 7.
  • \n
  • Drop support for Sphinx 5.
  • \n
  • Improve the screen-reader label for sidebar collapse.
  • \n
  • Make it easier to create derived themes from Furo.
  • \n
  • Bump all JS dependencies (NodeJS and npm packages).
  • \n
\n

2023.03.27 -- Tasty Tangerine

\n
    \n
  • Regenerate with newer version of sphinx-theme-builder, to fix RECORD hashes.
  • \n
  • Add missing class to Font Awesome examples
  • \n
\n

2023.03.23 -- Sassy Saffron

\n
    \n
  • Update Python version classifiers.
  • \n
  • Increase the icon size in mobile header.
  • \n
  • Increase admonition title bg opacity.
  • \n
  • Change the default API background to transparent.
  • \n
  • Transition the API background change.
  • \n
  • Remove the "indent" of API entries which have a background.
  • \n
  • Break long inline code literals.
  • \n
\n

2022.12.07 -- Reverent Raspberry

\n
    \n
  • \u2728 Add support for Sphinx 6.
  • \n
  • \u2728 Improve footnote presentation with docutils 0.18+.
  • \n
  • Drop support for Sphinx 4.
  • \n
  • Improve documentation about what the edit button does.
  • \n
  • Improve handling of empty-flexboxes for better print experience on Chrome.
  • \n
  • Improve styling for inline signatures.
  • \n
  • Replace the meta generator tag with a comment.
  • \n
  • Tweak labels with icons to prevent users selecting icons as text on touch.
  • \n
\n

2022.09.29 -- Quaint Quartz

\n
    \n
  • Add ability to set arbitrary URLs for edit button.
  • \n
\n\n
\n

... (truncated)

\n
\n
\nCommits\n
    \n
  • d2c9ca8 Prepare release: 2023.05.20
  • \n
  • 662d21b Update changelog
  • \n
  • 591780b Bump compatible Sphinx version
  • \n
  • c2e7837 Bump NodeJS and package versions
  • \n
  • dd85574 Use the reference HtmlFormatter class defined on PygmentsBridge. (#657)
  • \n
  • 6bff419 Fix broken link (#654)
  • \n
  • e7f732e Improve the screen-reader label for sidebar collapse
  • \n
  • 48c0bf2 Drop the check for the theme name
  • \n
  • 1b17d81 [pre-commit.ci] pre-commit autoupdate (#646)
  • \n
  • 4904fd5 Remove Python 3.8 constraint from Black pre-commit config (#647)
  • \n
  • Additional commits viewable in compare view
  • \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=2023.3.27&new-version=2023.5.20)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)\n\nYou can trigger a rebase of this PR 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--2077.org.readthedocs.build/en/2077/\n\r\n\n> **Note**\n> Automatic rebases have been disabled on this pull request as it has been open for over 30 days.", "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/2077/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": 1718635018, "node_id": "PR_kwDOCGYnMM5Q9lY4", "number": 553, "title": "Reformatted CLI examples in docs", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 2, "created_at": "2023-05-21T20:44:34Z", "updated_at": "2023-05-21T20:57:27Z", "closed_at": "2023-05-21T20:57:23Z", "author_association": "OWNER", "pull_request": "simonw/sqlite-utils/pulls/553", "body": "Refs:\r\n- #551\r\n\r\n\r\n----\n:books: Documentation preview :books:: https://sqlite-utils--553.org.readthedocs.build/en/553/\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/553/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": 1718612569, "node_id": "I_kwDOCGYnMM5mb_JZ", "number": 552, "title": "Document how to setup shell auto-completion", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 1, "created_at": "2023-05-21T19:20:41Z", "updated_at": "2023-05-21T21:05:16Z", "closed_at": "2023-05-21T21:03:40Z", "author_association": "OWNER", "pull_request": null, "body": "https://click.palletsprojects.com/en/8.1.x/shell-completion/\r\n\r\nThis works for `zsh`:\r\n\r\n eval \"$(_SQLITE_UTILS_COMPLETE=zsh_source sqlite-utils)\"\r\n\r\nThis will probably work for `bash`:\r\n\r\n eval \"$(_SQLITE_UTILS_COMPLETE=bash_source sqlite-utils)\"\r\n\r\nNeed to add this to the installation docs here: https://sqlite-utils.datasette.io/en/stable/installation.html - along with the pattern for adding that to `.zshrc` or whatever.", "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/552/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": 1718607907, "node_id": "I_kwDOCGYnMM5mb-Aj", "number": 551, "title": "Make as many examples in the CLI docs as possible copy-and-pastable", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 6, "created_at": "2023-05-21T19:04:10Z", "updated_at": "2023-05-21T21:04:04Z", "closed_at": "2023-05-21T20:57:24Z", "author_association": "OWNER", "pull_request": null, "body": "e.g. in this section:\r\n\r\nhttps://sqlite-utils.datasette.io/en/stable/cli.html#running-queries-directly-against-csv-or-json\r\n\r\n\"image\"\r\n\r\nThe little copy button will also copy the `$ ` which breaks the examples when copied.", "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/551/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": 1718595700, "node_id": "I_kwDOCGYnMM5mb7B0", "number": 550, "title": "AttributeError: 'EntryPoints' object has no attribute 'get' for flake8 on Python 3.7", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 3, "created_at": "2023-05-21T18:24:39Z", "updated_at": "2023-05-21T18:42:25Z", "closed_at": "2023-05-21T18:41:58Z", "author_association": "OWNER", "pull_request": null, "body": "https://github.com/simonw/sqlite-utils/actions/runs/5039064797/jobs/9036965488\r\n\r\n```\r\nTraceback (most recent call last):\r\n File \"/opt/hostedtoolcache/Python/3.7.16/x64/bin/flake8\", line 8, in \r\n sys.exit(main())\r\n File \"/opt/hostedtoolcache/Python/3.7.16/x64/lib/python3.7/site-packages/flake8/main/cli.py\", line 22, in main\r\n app.run(argv)\r\n File \"/opt/hostedtoolcache/Python/3.7.16/x64/lib/python3.7/site-packages/flake8/main/application.py\", line 363, in run\r\n self._run(argv)\r\n File \"/opt/hostedtoolcache/Python/3.7.16/x64/lib/python3.7/site-packages/flake8/main/application.py\", line 350, in _run\r\n self.initialize(argv)\r\n File \"/opt/hostedtoolcache/Python/3.7.16/x64/lib/python3.7/site-packages/flake8/main/application.py\", line 330, in initialize\r\n self.find_plugins(config_finder)\r\n File \"/opt/hostedtoolcache/Python/3.7.16/x64/lib/python3.7/site-packages/flake8/main/application.py\", line 153, in find_plugins\r\n self.check_plugins = plugin_manager.Checkers(local_plugins.extension)\r\n File \"/opt/hostedtoolcache/Python/3.7.16/x64/lib/python3.7/site-packages/flake8/plugins/manager.py\", line 357, in __init__\r\n self.namespace, local_plugins=local_plugins\r\n File \"/opt/hostedtoolcache/Python/3.7.16/x64/lib/python3.7/site-packages/flake8/plugins/manager.py\", line 238, in __init__\r\n self._load_entrypoint_plugins()\r\n File \"/opt/hostedtoolcache/Python/3.7.16/x64/lib/python3.7/site-packages/flake8/plugins/manager.py\", line 254, in _load_entrypoint_plugins\r\n eps = importlib_metadata.entry_points().get(self.namespace, ())\r\nAttributeError: 'EntryPoints' object has no attribute 'get'\r\nError: Process completed with exit code 1.\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/550/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": 1718586377, "node_id": "PR_kwDOCGYnMM5Q9cAv", "number": 549, "title": "TUI powered by Trogon", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 3, "created_at": "2023-05-21T17:55:42Z", "updated_at": "2023-05-21T18:42:00Z", "closed_at": "2023-05-21T18:41:56Z", "author_association": "OWNER", "pull_request": "simonw/sqlite-utils/pulls/549", "body": "Refs:\r\n- #545\r\n\r\n\r\n----\n:books: Documentation preview :books:: https://sqlite-utils--549.org.readthedocs.build/en/549/\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/549/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": 1718576761, "node_id": "I_kwDOCGYnMM5mb2Z5", "number": 548, "title": "analyze-tables should validate provide --column names", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 1, "created_at": "2023-05-21T17:20:24Z", "updated_at": "2023-05-21T17:35:52Z", "closed_at": "2023-05-21T17:35:52Z", "author_association": "OWNER", "pull_request": null, "body": "Noticed this while testing:\r\n- #547 \r\n\r\nIf you pass a non-existent column to `-c/--column` you don't get an error message.", "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/548/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": 1718572201, "node_id": "I_kwDOCGYnMM5mb1Sp", "number": 547, "title": "No need to show common values if everything is null", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 1, "created_at": "2023-05-21T17:05:07Z", "updated_at": "2023-05-21T17:19:21Z", "closed_at": "2023-05-21T17:19:21Z", "author_association": "OWNER", "pull_request": null, "body": "Noticed this:\r\n\r\n```\r\n% sqlite-utils analyze-tables content.db repos -c delete_branch_on_merge --common-limit 20 --no-least\r\nrepos.delete_branch_on_merge: (1/1)\r\n\r\n Total rows: 158\r\n Null rows: 158\r\n Blank rows: 0\r\n\r\n Distinct values: 0\r\n\r\n Most common:\r\n 158: None\r\n```\r\n\r\nThe `158: None` there is duplicate information considering we already know there are 158/158 null rows.", "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/547/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": 1718550688, "node_id": "PR_kwDOCGYnMM5Q9VH0", "number": 546, "title": "Analyze tables options: --common-limit, --no-most, --no-least", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 2, "created_at": "2023-05-21T15:54:39Z", "updated_at": "2023-05-21T16:19:30Z", "closed_at": "2023-05-21T16:19:30Z", "author_association": "OWNER", "pull_request": "simonw/sqlite-utils/pulls/546", "body": "Refs #544\r\n\r\n- [x] Documentation for CLI options\r\n- [x] Documentation for new Python API parameters: `most_common: bool` and `least_common: bool`\r\n- [x] Tests for CLI\r\n- [x] Tests for Python API", "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/546/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": 1718517882, "node_id": "I_kwDOCGYnMM5mboB6", "number": 545, "title": "Try out Trogon for a tui interface", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 6, "created_at": "2023-05-21T14:08:25Z", "updated_at": "2023-05-21T19:33:13Z", "closed_at": "2023-05-21T18:41:58Z", "author_association": "OWNER", "pull_request": null, "body": "https://github.com/Textualize/trogon", "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/545/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": 1718515590, "node_id": "I_kwDOCGYnMM5mbneG", "number": 544, "title": "New options for analyze-tables --common-limit --no-most and --no-least", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 2, "created_at": "2023-05-21T14:03:19Z", "updated_at": "2023-05-21T17:03:06Z", "closed_at": "2023-05-21T16:19:31Z", "author_association": "OWNER", "pull_request": null, "body": "The \"least common\" section is frequently uninteresting, especially for huge tables with a large number of repeated-once values.\r\n\r\n sqlite-utils analyze-tables content.db repos --common-limit 20 --no-least", "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/544/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": 1715468032, "node_id": "PR_kwDOBm6k_c5QzEAM", "number": 2076, "title": "Datsette gpt plugin", "user": {"value": 130708713, "label": "StudioCordillera"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 0, "created_at": "2023-05-18T11:22:30Z", "updated_at": "2023-05-18T11:22:45Z", "closed_at": null, "author_association": "FIRST_TIME_CONTRIBUTOR", "pull_request": "simonw/datasette/pulls/2076", "body": "\r\n\r\n\r\n----\n:books: Documentation preview :books:: https://datasette--2076.org.readthedocs.build/en/2076/\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/2076/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": 1710164693, "node_id": "PR_kwDOBm6k_c5QhIL2", "number": 2075, "title": "Bump sphinx from 6.1.3 to 7.0.1", "user": {"value": 49699333, "label": "dependabot[bot]"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 1, "created_at": "2023-05-15T13:59:31Z", "updated_at": "2023-06-29T14:31:59Z", "closed_at": null, "author_association": "CONTRIBUTOR", "pull_request": "simonw/datasette/pulls/2075", "body": "Bumps [sphinx](https://github.com/sphinx-doc/sphinx) from 6.1.3 to 7.0.1.\n
\nRelease notes\n

Sourced from sphinx's releases.

\n
\n

v7.0.1

\n

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

\n

v7.0.0

\n

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

\n

v7.0.0rc1

\n

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

\n

v6.2.1

\n

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

\n

v6.2.0

\n

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

\n
\n
\n
\nChangelog\n

Sourced from sphinx's changelog.

\n
\n

Release 7.0.1 (released May 12, 2023)

\n

Dependencies

\n
    \n
  • #11411: Support Docutils 0.20_. Patch by Adam Turner.
  • \n
\n

.. _Docutils 0.20: https://docutils.sourceforge.io/RELEASE-NOTES.html#release-0-20-2023-05-04

\n

Bugs fixed

\n
    \n
  • #11418: Clean up remaining references to sphinx.setup_command\nfollowing the removal of support for setuptools.\nPatch by Willem Mulder.
  • \n
\n

Release 7.0.0 (released Apr 29, 2023)

\n

Incompatible changes

\n
    \n
  • #11359: Remove long-deprecated aliases for MecabSplitter and\nDefaultSplitter in sphinx.search.ja.
  • \n
  • #11360: Remove deprecated make_old_id functions in domain object\ndescription classes.
  • \n
  • #11363: Remove the Setuptools integration (build_sphinx hook in\nsetup.py).
  • \n
  • #11364: Remove deprecated sphinx.ext.napoleon.iterators module.
  • \n
  • #11365: Remove support for the jsdump format in sphinx.search.
  • \n
  • #11366: Make locale a required argument to\nsphinx.util.i18n.format_date().
  • \n
  • #11370: Remove deprecated sphinx.util.stemmer module.
  • \n
  • #11371: Remove deprecated sphinx.pycode.ast.parse() function.
  • \n
  • #11372: Remove deprecated sphinx.io.read_doc() function.
  • \n
  • #11373: Removed deprecated sphinx.util.get_matching_files() function.
  • \n
  • #11378: Remove deprecated sphinx.util.docutils.is_html5_writer_available()\nfunction.
  • \n
  • #11379: Make the env argument to Builder subclasses required.
  • \n
  • #11380: autosummary: Always emit grouped import exceptions.
  • \n
  • #11381: Remove deprecated style key for HTML templates.
  • \n
  • #11382: Remove deprecated sphinx.writers.latex.LaTeXTranslator.docclasses\nattribute.
  • \n
  • #11383: Remove deprecated sphinx.builders.html.html5_ready and\nsphinx.builders.html.HTMLTranslator attributes.
  • \n
  • #11385: Remove support for HTML 4 output.
  • \n
\n

Release 6.2.1 (released Apr 25, 2023)

\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=6.1.3&new-version=7.0.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)\n\nYou can trigger a rebase of this PR 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--2075.org.readthedocs.build/en/2075/\n\r\n\n> **Note**\n> Automatic rebases have been disabled on this pull request as it has been open for over 30 days.\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/2075/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": 1708981860, "node_id": "PR_kwDOBm6k_c5QdMea", "number": 2074, "title": "sort files by mtime", "user": {"value": 3919561, "label": "abbbi"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 0, "created_at": "2023-05-14T15:25:15Z", "updated_at": "2023-05-14T15:25:29Z", "closed_at": null, "author_association": "FIRST_TIME_CONTRIBUTOR", "pull_request": "simonw/datasette/pulls/2074", "body": "serving multiple database files and getting tired by the default sort, changes so the sort order puts the latest changed databases to be on top of the list so don't have to scroll down, lazy as i am ;)\r\n\r\n\r\n----\n:books: Documentation preview :books:: https://datasette--2074.org.readthedocs.build/en/2074/\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/2074/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": 1708030220, "node_id": "I_kwDOBm6k_c5lznkM", "number": 2073, "title": "Faceting doesn't work against integer columns in views", "user": {"value": 9599, "label": "simonw"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 2, "created_at": "2023-05-12T18:20:10Z", "updated_at": "2023-05-12T18:24:07Z", "closed_at": null, "author_association": "OWNER", "pull_request": null, "body": "Spotted this issue here: https://til.simonwillison.net/datasette/baseline\r\n\r\nI had to do this workaround:\r\n```sql\r\ncreate view baseline as select\r\n _key,\r\n spec,\r\n '' || json_extract(status, '$.is_baseline') as is_baseline,\r\n json_extract(status, '$.since') as baseline_since,\r\n json_extract(status, '$.support.chrome') as baseline_chrome,\r\n json_extract(status, '$.support.edge') as baseline_edge,\r\n json_extract(status, '$.support.firefox') as baseline_firefox,\r\n json_extract(status, '$.support.safari') as baseline_safari,\r\n compat_features,\r\n caniuse,\r\n usage_stats,\r\n status\r\nfrom\r\n [index]\r\n```\r\nI think the core issue here is that, against a table, `select * from x where integer_column = '1'` works correctly, due to some kind of column type conversion mechanism... but this mechanism doesn't work against views.", "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/2073/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": null} {"id": 1702354223, "node_id": "I_kwDOBm6k_c5ld90v", "number": 2070, "title": "Mechanism for deploying a preview of a branch using Vercel", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 2, "created_at": "2023-05-09T16:21:45Z", "updated_at": "2023-05-09T16:25:00Z", "closed_at": "2023-05-09T16:24:31Z", "author_association": "OWNER", "pull_request": null, "body": "I prototyped that here: https://github.com/simonw/one-off-actions/blob/main/.github/workflows/deploy-datasette-branch-preview.yml\r\n\r\nIt deployed the `json-extras-query` branch here: https://datasette-preview-json-extras-query.vercel.app/", "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/2070/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": 1701018909, "node_id": "I_kwDOCGYnMM5lY30d", "number": 543, "title": "Tests broken on Windows due to new convert() lambda names", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 0, "created_at": "2023-05-08T22:11:29Z", "updated_at": "2023-05-08T22:19:04Z", "closed_at": "2023-05-08T22:19:04Z", "author_association": "OWNER", "pull_request": null, "body": "https://github.com/simonw/sqlite-utils/actions/runs/4920084038/jobs/8788501314\r\n```python\r\nsql = 'update [example] set [dt] = lambda_-9223371942137158589([dt]);'\r\n```\r\nFrom:\r\n- #526", "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/543/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": 1700936245, "node_id": "I_kwDOCGYnMM5lYjo1", "number": 542, "title": "Remove `skip_false=True` and `--no-skip-false` in `sqlite-utils` 4.0", "user": {"value": 9599, "label": "simonw"}, "state": "open", "locked": 0, "assignee": null, "milestone": {"value": 9374594, "label": "4.0 backwards incomatible changes"}, "comments": 1, "created_at": "2023-05-08T21:04:28Z", "updated_at": "2023-05-08T21:07:41Z", "closed_at": null, "author_association": "OWNER", "pull_request": null, "body": "Following:\r\n- #527\r\n\r\nThe only reason I didn't remove fix this mis-feature entirely is that it represents a backwards incompatible change. I'll make that change in 4.0.", "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/542/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": null} {"id": 1700840265, "node_id": "I_kwDOCGYnMM5lYMNJ", "number": 541, "title": "Get tests to pass with `pytest -Werror`", "user": {"value": 9599, "label": "simonw"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 1, "created_at": "2023-05-08T19:57:23Z", "updated_at": "2023-05-08T19:59:35Z", "closed_at": null, "author_association": "OWNER", "pull_request": null, "body": "Inspired by:\r\n- #534", "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/541/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": null} {"id": 1699184583, "node_id": "I_kwDOCGYnMM5lR3_H", "number": 540, "title": "sphinx.builders.linkcheck build error", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 4, "created_at": "2023-05-07T18:37:09Z", "updated_at": "2023-05-08T04:56:13Z", "closed_at": "2023-05-07T18:42:36Z", "author_association": "OWNER", "pull_request": null, "body": "https://readthedocs.org/projects/sqlite-utils/builds/20512693/\r\n```\r\n Running Sphinx v6.2.1\r\n\r\nTraceback (most recent call last):\r\n File \"/home/docs/checkouts/readthedocs.org/user_builds/sqlite-utils/envs/latest/lib/python3.8/site-packages/sphinx/registry.py\", line 442, in load_extension\r\n mod = import_module(extname)\r\n File \"/home/docs/checkouts/readthedocs.org/user_builds/sqlite-utils/envs/latest/lib/python3.8/importlib/__init__.py\", line 127, in import_module\r\n return _bootstrap._gcd_import(name[level:], package, level)\r\n File \"\", line 1014, in _gcd_import\r\n File \"\", line 991, in _find_and_load\r\n File \"\", line 975, in _find_and_load_unlocked\r\n File \"\", line 671, in _load_unlocked\r\n File \"\", line 783, in exec_module\r\n File \"\", line 219, in _call_with_frames_removed\r\n File \"/home/docs/checkouts/readthedocs.org/user_builds/sqlite-utils/envs/latest/lib/python3.8/site-packages/sphinx/builders/linkcheck.py\", line 20, in \r\n from requests import Response\r\n File \"/home/docs/checkouts/readthedocs.org/user_builds/sqlite-utils/envs/latest/lib/python3.8/site-packages/requests/__init__.py\", line 43, in \r\n import urllib3\r\n File \"/home/docs/checkouts/readthedocs.org/user_builds/sqlite-utils/envs/latest/lib/python3.8/site-packages/urllib3/__init__.py\", line 38, in \r\n raise ImportError(\r\nImportError: urllib3 v2.0 only supports OpenSSL 1.1.1+, currently the 'ssl' module is compiled with OpenSSL 1.0.2n 7 Dec 2017. See: https://github.com/urllib3/urllib3/issues/2168\r\n\r\nThe above exception was the direct cause of the following exception:\r\n\r\nTraceback (most recent call last):\r\n File \"/home/docs/checkouts/readthedocs.org/user_builds/sqlite-utils/envs/latest/lib/python3.8/site-packages/sphinx/cmd/build.py\", line 280, in build_main\r\n app = Sphinx(args.sourcedir, args.confdir, args.outputdir,\r\n File \"/home/docs/checkouts/readthedocs.org/user_builds/sqlite-utils/envs/latest/lib/python3.8/site-packages/sphinx/application.py\", line 225, in __init__\r\n self.setup_extension(extension)\r\n File \"/home/docs/checkouts/readthedocs.org/user_builds/sqlite-utils/envs/latest/lib/python3.8/site-packages/sphinx/application.py\", line 404, in setup_extension\r\n self.registry.load_extension(self, extname)\r\n File \"/home/docs/checkouts/readthedocs.org/user_builds/sqlite-utils/envs/latest/lib/python3.8/site-packages/sphinx/registry.py\", line 445, in load_extension\r\n raise ExtensionError(__('Could not import extension %s') % extname,\r\nsphinx.errors.ExtensionError: Could not import extension sphinx.builders.linkcheck (exception: urllib3 v2.0 only supports OpenSSL 1.1.1+, currently the 'ssl' module is compiled with OpenSSL 1.0.2n 7 Dec 2017. See: https://github.com/urllib3/urllib3/issues/2168)\r\n\r\nExtension error:\r\nCould not import extension sphinx.builders.linkcheck (exception: urllib3 v2.0 only supports OpenSSL 1.1.1+, currently the 'ssl' module is compiled with OpenSSL 1.0.2n 7 Dec 2017. See: https://github.com/urllib3/urllib3/issues/2168)\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/540/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": 1699174055, "node_id": "I_kwDOCGYnMM5lR1an", "number": 539, "title": "`--raw-lines` option, like `--raw` for multiple lines", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 4, "created_at": "2023-05-07T18:07:46Z", "updated_at": "2023-05-07T18:43:24Z", "closed_at": "2023-05-07T18:26:18Z", "author_association": "OWNER", "pull_request": null, "body": "I wanted to output newline-separated output of the first column of every row in the results - like `--row` but for more than one line.", "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/539/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": 1698865182, "node_id": "I_kwDOBm6k_c5lQqAe", "number": 2069, "title": "[BUG] Cannot insert new data to deployed instance", "user": {"value": 31861128, "label": "yqlbu"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 1, "created_at": "2023-05-07T02:59:42Z", "updated_at": "2023-05-07T03:17:35Z", "closed_at": null, "author_association": "NONE", "pull_request": null, "body": "## Summary\r\n\r\nRecently, I deployed an instance of datasette to Vercel with the following plugins:\r\n\r\n- datasette-auth-tokens\r\n- datasette-insert\r\n\r\nWith the above plugins, I was able to insert new data to local sqlite db. However, when it comes to the deployment on Vercel, things behave differently. I observed some errors from the logs console on Vercel:\r\n\r\n```console\r\nFile \"/var/task/datasette/database.py\", line 179, in _execute_writes\r\nconn = self.connect(write=True)\r\nFile \"/var/task/datasette/database.py\", line 93, in connect\r\nassert not (write and not self.is_mutable)\r\nAssertionError\r\n``` \r\n\r\n\"image\"\r\n\r\nI think it is a potential bug.\r\n\r\n## Reproduce\r\n\r\n
metadata.json\r\n
\r\n\r\n```json\r\n{\r\n \"plugins\": {\r\n \"datasette-insert\": {\r\n \"allow\": {\r\n \"id\": \"*\"\r\n }\r\n },\r\n \"datasette-auth-tokens\": {\r\n \"tokens\": [\r\n {\r\n \"token\": {\r\n \"$env\": \"INSERT_TOKEN\"\r\n },\r\n \"actor\": {\r\n \"id\": \"repeater\"\r\n }\r\n }\r\n ],\r\n \"param\": \"_auth_token\"\r\n }\r\n }\r\n}\r\n```\r\n\r\n
\r\n\r\n
commands\r\n
\r\n\r\n```bash\r\n# deploy\r\ndatasette publish vercel remote.db \\\r\n --project=repeater-bot-sqlite \\\r\n --metadata metadata.json \\\r\n --install datasette-auth-tokens \\\r\n --install datasette-insert \\\r\n --vercel-json=vercel.json\r\n\r\n# test insert\r\ncat fixtures/dogs.json | curl --request POST -d @- -H \"Authorization: Bearer \" \\\r\n 'https://repeater-bot-sqlite.vercel.app/-/insert/remote/dogs?pk=id'\r\n```\r\n\r\n
\r\n\r\n
logs\r\n
\r\n\r\n```console\r\nTraceback (most recent call last):\r\nFile \"/var/task/datasette/app.py\", line 1354, in route_path\r\nresponse = await view(request, send)\r\nFile \"/var/task/datasette/app.py\", line 1500, in async_view_fn\r\nresponse = await async_call_with_supported_arguments(\r\nFile \"/var/task/datasette/utils/__init__.py\", line 1005, in async_call_with_supported_arguments\r\nreturn await fn(*call_with)\r\nFile \"/var/task/datasette_insert/__init__.py\", line 14, in insert_or_upsert\r\nresponse = await insert_or_upsert_implementation(request, datasette)\r\nFile \"/var/task/datasette_insert/__init__.py\", line 91, in insert_or_upsert_implementation\r\ntable_count = await db.execute_write_fn(write_in_thread, block=True)\r\nFile \"/var/task/datasette/database.py\", line 167, in execute_write_fn\r\nraise result\r\nFile \"/var/task/datasette/database.py\", line 179, in _execute_writes\r\nconn = self.connect(write=True)\r\nFile \"/var/task/datasette/database.py\", line 93, in connect\r\nassert not (write and not self.is_mutable)\r\nAssertionError\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/2069/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": null} {"id": 1695428235, "node_id": "I_kwDOCGYnMM5lDi6L", "number": 538, "title": "`table.upsert_all` fails to write rows when `not_null` is present", "user": {"value": 1231935, "label": "xavdid"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 9, "created_at": "2023-05-04T07:30:38Z", "updated_at": "2023-05-08T20:06:35Z", "closed_at": "2023-05-08T19:27:02Z", "author_association": "NONE", "pull_request": null, "body": "I found an odd bug today, where calls to `table.upsert_all` don't write rows if you include the `not_null` kwarg.\r\n\r\n## Repro Example\r\n\r\n```py\r\nfrom sqlite_utils import Database\r\n\r\ndb = Database(\"upsert-test.db\")\r\n\r\ndb[\"comments\"].upsert_all(\r\n [{\"id\": 1, \"name\": \"david\"}],\r\n pk=\"id\",\r\n not_null=[\"name\"],\r\n)\r\n\r\nassert list(db[\"comments\"].rows) # err!\r\n```\r\n\r\nThe schema is correctly created:\r\n\r\n```sql\r\nCREATE TABLE [comments] (\r\n [id] INTEGER PRIMARY KEY,\r\n [name] TEXT NOT NULL\r\n)\r\n```\r\n\r\nBut no rows are created. Removing either the `not_null` kwargs works as expected, as does an `insert_all` call.\r\n\r\n## Version Info\r\n\r\n- Python: `3.11.0`\r\n- sqlite-utils: `3.30`\r\n- sqlite: `3.39.5 2022-10-14`", "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/538/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": 1690842199, "node_id": "PR_kwDOBm6k_c5PgNaA", "number": 2068, "title": "Bump sphinx from 6.1.3 to 7.0.0", "user": {"value": 49699333, "label": "dependabot[bot]"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 1, "created_at": "2023-05-01T13:58:46Z", "updated_at": "2023-05-15T13:59:38Z", "closed_at": "2023-05-15T13:59:36Z", "author_association": "CONTRIBUTOR", "pull_request": "simonw/datasette/pulls/2068", "body": "Bumps [sphinx](https://github.com/sphinx-doc/sphinx) from 6.1.3 to 7.0.0.\n
\nRelease notes\n

Sourced from sphinx's releases.

\n
\n

v7.0.0

\n

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

\n

v7.0.0rc1

\n

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

\n

v6.2.1

\n

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

\n

v6.2.0

\n

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

\n
\n
\n
\nChangelog\n

Sourced from sphinx's changelog.

\n
\n

Release 7.0.0 (released Apr 29, 2023)

\n

Incompatible changes

\n
    \n
  • #11359: Remove long-deprecated aliases for MecabSplitter and\nDefaultSplitter in sphinx.search.ja.
  • \n
  • #11360: Remove deprecated make_old_id functions in domain object\ndescription classes.
  • \n
  • #11363: Remove the Setuptools integration (build_sphinx hook in\nsetup.py).
  • \n
  • #11364: Remove deprecated sphinx.ext.napoleon.iterators module.
  • \n
  • #11365: Remove support for the jsdump format in sphinx.search.
  • \n
  • #11366: Make locale a required argument to\nsphinx.util.i18n.format_date().
  • \n
  • #11370: Remove deprecated sphinx.util.stemmer module.
  • \n
  • #11371: Remove deprecated sphinx.pycode.ast.parse() function.
  • \n
  • #11372: Remove deprecated sphinx.io.read_doc() function.
  • \n
  • #11373: Removed deprecated sphinx.util.get_matching_files() function.
  • \n
  • #11378: Remove deprecated sphinx.util.docutils.is_html5_writer_available()\nfunction.
  • \n
  • #11379: Make the env argument to Builder subclasses required.
  • \n
  • #11380: autosummary: Always emit grouped import exceptions.
  • \n
  • #11381: Remove deprecated style key for HTML templates.
  • \n
  • #11382: Remove deprecated sphinx.writers.latex.LaTeXTranslator.docclasses\nattribute.
  • \n
  • #11383: Remove deprecated sphinx.builders.html.html5_ready and\nsphinx.builders.html.HTMLTranslator attributes.
  • \n
  • #11385: Remove support for HTML 4 output.
  • \n
\n

Release 6.2.1 (released Apr 25, 2023)

\n

Bugs fixed

\n
    \n
  • #11355: Revert the default type of :confval:nitpick_ignore and\n:confval:nitpick_ignore_regex to list.
  • \n
\n

Release 6.2.0 (released Apr 23, 2023)

\n

Dependencies

\n
    \n
  • Require Docutils 0.18.1 or greater.
  • \n
\n

Incompatible changes

\n\n
\n

... (truncated)

\n
\n
\nCommits\n
    \n
  • d568b2f Bump to 7.0.0 final
  • \n
  • ff79edf Remove jsdump references post removal
  • \n
  • 1a5133a Bump to 7.0.0rc1 final
  • \n
  • 5795fc7 Update sphinx.deprecation for Sphinx 7.0 (#11386)
  • \n
  • 6202087 Add a note to CHANGES for PR 11385
  • \n
  • ad47373 Remove HTML 4 support (#11385)
  • \n
  • 3e3251d Remove HTMLTranslator and html5_ready from sphinx.builders.html (...
  • \n
  • 77fd819 Remove deprecated LaTeXTranslator.docclasses attribute (#11382)
  • \n
  • 4be56f3 Remove deprecated style key for HTML templates (#11381)
  • \n
  • 49027a9 Autosummary: Always emit grouped ImportError exceptions (#11380)
  • \n
  • Additional commits viewable in compare view
  • \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=6.1.3&new-version=7.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--2068.org.readthedocs.build/en/2068/\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/2068/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": 1690765434, "node_id": "I_kwDOBm6k_c5kxwh6", "number": 2067, "title": "Litestream-restored db: errors on 3.11 and 3.10.8; but works on py3.10.7 and 3.10.6", "user": {"value": 39538958, "label": "justmars"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 1, "created_at": "2023-05-01T12:42:28Z", "updated_at": "2023-05-03T00:16:03Z", "closed_at": null, "author_association": "NONE", "pull_request": null, "body": "Hi! Wondering if this issue is limited to my local system or if it affects others as well. \r\n\r\nIt seems like 3.11 errors out on a \"litestream-restored\" database. On further investigation, it also appears to conk out on 3.10.8 but works on 3.10.7 and 3.10.6.\r\n\r\nTo demo issue I created a test database, replicated it to an aws s3 bucket, then restored the same under various .pyenv-versioned shells where I test whether I can read the database via the sqlite3 cli.\r\n\r\n```sh\r\n# create new shell with 3.11.3\r\nlitestream restore -o data/db.sqlite s3://mytestbucketxx/db\r\nsqlite3 data/db.sqlite \r\n# SQLite version 3.41.2 2023-03-22 11:56:21\r\n# Enter \".help\" for usage hints.\r\n# sqlite> .tables\r\n# _litestream_lock _litestream_seq movie \r\n# sqlite> \r\n```\r\n\r\nHowever this get me an `OperationalError` when reading via datasette:\r\n\r\n
\r\nError on 3.11.3 and 3.10.8\r\n\r\n```sh\r\ndatasette data/db.sqlite\r\n```\r\n\r\n```console\r\n/tester/.venv/lib/python3.11/site-packages/pkg_resources/__init__.py:121: DeprecationWarning: pkg_resources is deprecated as an API\r\n warnings.warn(\"pkg_resources is deprecated as an API\", DeprecationWarning)\r\nTraceback (most recent call last):\r\n File \"/tester/.venv/bin/datasette\", line 8, in \r\n sys.exit(cli())\r\n ^^^^^\r\n File \"/tester/.venv/lib/python3.11/site-packages/click/core.py\", line 1130, in __call__\r\n return self.main(*args, **kwargs)\r\n ^^^^^^^^^^^^^^^^^^^^^^^^^^\r\n File \"/tester/.venv/lib/python3.11/site-packages/click/core.py\", line 1055, in main\r\n rv = self.invoke(ctx)\r\n ^^^^^^^^^^^^^^^^\r\n File \"/tester/.venv/lib/python3.11/site-packages/click/core.py\", line 1657, in invoke\r\n return _process_result(sub_ctx.command.invoke(sub_ctx))\r\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\r\n File \"/tester/.venv/lib/python3.11/site-packages/click/core.py\", line 1404, in invoke\r\n return ctx.invoke(self.callback, **ctx.params)\r\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\r\n File \"/tester/.venv/lib/python3.11/site-packages/click/core.py\", line 760, in invoke\r\n return __callback(*args, **kwargs)\r\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^\r\n File \"/tester/.venv/lib/python3.11/site-packages/datasette/cli.py\", line 143, in wrapped\r\n return fn(*args, **kwargs)\r\n ^^^^^^^^^^^^^^^^^^^\r\n File \"/tester/.venv/lib/python3.11/site-packages/datasette/cli.py\", line 615, in serve\r\n asyncio.get_event_loop().run_until_complete(check_databases(ds))\r\n File \"/Users/mv/.pyenv/versions/3.11.3/lib/python3.11/asyncio/base_events.py\", line 653, in run_until_complete\r\n return future.result()\r\n ^^^^^^^^^^^^^^^\r\n File \"/tester/.venv/lib/python3.11/site-packages/datasette/cli.py\", line 660, in check_databases\r\n await database.execute_fn(check_connection)\r\n File \"/tester/.venv/lib/python3.11/site-packages/datasette/database.py\", line 213, in execute_fn\r\n return await asyncio.get_event_loop().run_in_executor(\r\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\r\n File \"/Users/mv/.pyenv/versions/3.11.3/lib/python3.11/concurrent/futures/thread.py\", line 58, in run\r\n result = self.fn(*self.args, **self.kwargs)\r\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\r\n File \"/tester/.venv/lib/python3.11/site-packages/datasette/database.py\", line 211, in in_thread\r\n return fn(conn)\r\n ^^^^^^^^\r\n File \"/tester/.venv/lib/python3.11/site-packages/datasette/utils/__init__.py\", line 951, in check_connection\r\n for r in conn.execute(\r\n ^^^^^^^^^^^^^\r\nsqlite3.OperationalError: unable to open database file\r\n```\r\n\r\n
\r\n\r\n\r\n
\r\nWorks on 3.10.7, 3.10.6\r\n\r\n```sh\r\n# create new shell with 3.10.7 / 3.10.6\r\nlitestream restore -o data/db.sqlite s3://mytestbucketxx/db\r\ndatasette data/db.sqlite\r\n# ...\r\n# INFO: Uvicorn running on http://127.0.0.1:8001 (Press CTRL+C to quit)\r\n```\r\n\r\n
\r\n\r\nIn both scenarios, the only dependencies were the pinned python version and the latest Datasette version 0.64.", "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/2067/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": null} {"id": 1686042269, "node_id": "I_kwDOBm6k_c5kfvad", "number": 2066, "title": "Failing test: httpx.InvalidURL: URL too long", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 10, "created_at": "2023-04-27T03:48:47Z", "updated_at": "2023-04-27T04:27:50Z", "closed_at": "2023-04-27T04:27:50Z", "author_association": "OWNER", "pull_request": null, "body": "https://github.com/simonw/datasette/actions/runs/4815723640/jobs/8574667731\r\n```\r\n def urlparse(url: str = \"\", **kwargs: typing.Optional[str]) -> ParseResult:\r\n # Initial basic checks on allowable URLs.\r\n # ---------------------------------------\r\n \r\n # Hard limit the maximum allowable URL length.\r\n if len(url) > MAX_URL_LENGTH:\r\n> raise InvalidURL(\"URL too long\")\r\nE httpx.InvalidURL: URL too long\r\n\r\n/opt/hostedtoolcache/Python/3.7.16/x64/lib/python3.7/site-packages/httpx/_urlparse.py:155: InvalidURL\r\n=========================== short test summary info ============================\r\nFAILED tests/test_csv.py::test_max_csv_mb - httpx.InvalidURL: URL too long\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/2066/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": 1686033652, "node_id": "I_kwDOBm6k_c5kftT0", "number": 2065, "title": "Datasette cannot be installed with Rye", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 4, "created_at": "2023-04-27T03:35:42Z", "updated_at": "2023-04-27T05:09:36Z", "closed_at": "2023-04-27T05:09:36Z", "author_association": "OWNER", "pull_request": null, "body": "https://github.com/mitsuhiko/rye\r\n\r\nI tried this:\r\n\r\n rye install datasette\r\n\r\nBut now:\r\n\r\n```\r\n% ~/.rye/shims/datasette\r\nTraceback (most recent call last):\r\n File \"/Users/simon/.rye/shims/datasette\", line 5, in \r\n from datasette.cli import cli\r\n File \"/Users/simon/.rye/tools/datasette/lib/python3.11/site-packages/datasette/cli.py\", line 17, in \r\n from .app import (\r\n File \"/Users/simon/.rye/tools/datasette/lib/python3.11/site-packages/datasette/app.py\", line 14, in \r\n import pkg_resources\r\nModuleNotFoundError: No module named 'pkg_resources'\r\n```\r\nI think that's because `setuptools` is not included in Rye.", "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/2065/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": 1683229834, "node_id": "PR_kwDOBm6k_c5PG0wF", "number": 2064, "title": "Bump sphinx from 6.1.3 to 6.2.1", "user": {"value": 49699333, "label": "dependabot[bot]"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 1, "created_at": "2023-04-25T13:57:49Z", "updated_at": "2023-05-01T13:58:53Z", "closed_at": "2023-05-01T13:58:52Z", "author_association": "CONTRIBUTOR", "pull_request": "simonw/datasette/pulls/2064", "body": "Bumps [sphinx](https://github.com/sphinx-doc/sphinx) from 6.1.3 to 6.2.1.\n
\nRelease notes\n

Sourced from sphinx's releases.

\n
\n

v6.2.1

\n

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

\n

v6.2.0

\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.2.1 (released Apr 25, 2023)

\n

Bugs fixed

\n
    \n
  • #11355: Revert the default type of :confval:nitpick_ignore and\n:confval:nitpick_ignore_regex to list.
  • \n
\n

Release 6.2.0 (released Apr 23, 2023)

\n

Dependencies

\n
    \n
  • Require Docutils 0.18.1 or greater.
  • \n
\n

Incompatible changes

\n
    \n
  • LaTeX: removal of some internal TeX \\dimen registers (not previously\npublicly documented) as per 5.1.0 code comments in sphinx.sty:\n\\sphinxverbatimsep, \\sphinxverbatimborder, \\sphinxshadowsep,\n\\sphinxshadowsize, and \\sphinxshadowrule. (refs: #11105)
  • \n
  • Remove .egg support from pycode ModuleAnalyser; Python eggs are a\nnow-obsolete binary distribution format
  • \n
  • #11089: Remove deprecated code in sphinx.builders.linkcheck.\nPatch by Daniel Eades
  • \n
  • Remove internal-only sphinx.locale.setlocale
  • \n
\n

Deprecated

\n
    \n
  • #11247: Deprecate the legacy intersphinx_mapping format
  • \n
  • sphinx.util.osutil.cd is deprecated in favour of contextlib.chdir.
  • \n
\n

Features added

\n
    \n
  • #11277: :rst:dir:autoproperty allows the return type to be specified as\na type comment (e.g., # type: () -> int). Patch by B\u00e9n\u00e9dikt Tran
  • \n
  • #10811: Autosummary: extend __all__ to imported members for template rendering\nwhen option autosummary_ignore_module_all is set to False. Patch by\nClement Pinard
  • \n
  • #11147: Add a content_offset parameter to nested_parse_with_titles(),\nallowing for correct line numbers during nested parsing.\nPatch by Jeremy Maitin-Shepard
  • \n
  • Update to Unicode CLDR 42
  • \n
  • Add a --jobs synonym for -j. Patch by Hugo van Kemenade
  • \n
  • LaTeX: a command \\sphinxbox for styling text elements with a (possibly
  • \n
\n\n
\n

... (truncated)

\n
\n
\nCommits\n
    \n
  • ec993dd Bump to 6.2.1 final
  • \n
  • d2aa91f Revert the default type of nitpick_ignore[_regex] to list
  • \n
  • 60d8fa1 Bump version
  • \n
  • 70102ac Bump to 6.2.0 final
  • \n
  • 4e27a5f Remove unneeded JavaScript from sphinx13 theme
  • \n
  • bffb547 Note correct deprecation version for sphinx.util.osutil.cd
  • \n
  • 59de8d5 Revert "Support and prefer .jinja to _t for static templates (#11165)...
  • \n
  • aee3c0a Partially revert "Disable localisation when SOURCE_DATE_EPOCH is set (#10949)...
  • \n
  • 186d596 Use overwrite_file context manager in test_ext_autodoc_configs (#11320)
  • \n
  • 77483f2 Add missing test decorator for test_util_inspect (#11321)
  • \n
  • Additional commits viewable in compare view
  • \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=6.1.3&new-version=6.2.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--2064.org.readthedocs.build/en/2064/\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/2064/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": 1681339696, "node_id": "PR_kwDOBm6k_c5PAcGt", "number": 2063, "title": "Bump sphinx from 6.1.3 to 6.2.0", "user": {"value": 49699333, "label": "dependabot[bot]"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 1, "created_at": "2023-04-24T13:58:21Z", "updated_at": "2023-04-25T13:57:55Z", "closed_at": "2023-04-25T13:57:53Z", "author_association": "CONTRIBUTOR", "pull_request": "simonw/datasette/pulls/2063", "body": "Bumps [sphinx](https://github.com/sphinx-doc/sphinx) from 6.1.3 to 6.2.0.\n
\nRelease notes\n

Sourced from sphinx's releases.

\n
\n

v6.2.0

\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.2.0 (released Apr 23, 2023)

\n

Dependencies

\n
    \n
  • Require Docutils 0.18.1 or greater.
  • \n
\n

Incompatible changes

\n
    \n
  • LaTeX: removal of some internal TeX \\dimen registers (not previously\npublicly documented) as per 5.1.0 code comments in sphinx.sty:\n\\sphinxverbatimsep, \\sphinxverbatimborder, \\sphinxshadowsep,\n\\sphinxshadowsize, and \\sphinxshadowrule. (refs: #11105)
  • \n
  • Remove .egg support from pycode ModuleAnalyser; Python eggs are a\nnow-obsolete binary distribution format
  • \n
  • #11089: Remove deprecated code in sphinx.builders.linkcheck.\nPatch by Daniel Eades
  • \n
  • Remove internal-only sphinx.locale.setlocale
  • \n
\n

Deprecated

\n
    \n
  • #11247: Deprecate the legacy intersphinx_mapping format
  • \n
  • sphinx.util.osutil.cd is deprecated in favour of contextlib.chdir.
  • \n
\n

Features added

\n
    \n
  • #11277: :rst:dir:autoproperty allows the return type to be specified as\na type comment (e.g., # type: () -> int). Patch by B\u00e9n\u00e9dikt Tran
  • \n
  • #10811: Autosummary: extend __all__ to imported members for template rendering\nwhen option autosummary_ignore_module_all is set to False. Patch by\nClement Pinard
  • \n
  • #11147: Add a content_offset parameter to nested_parse_with_titles(),\nallowing for correct line numbers during nested parsing.\nPatch by Jeremy Maitin-Shepard
  • \n
  • Update to Unicode CLDR 42
  • \n
  • Add a --jobs synonym for -j. Patch by Hugo van Kemenade
  • \n
  • LaTeX: a command \\sphinxbox for styling text elements with a (possibly\nrounded) box, optional background color and shadow, has been added.\nSee :ref:sphinxbox. (refs: #11224)
  • \n
  • LaTeX: add \\sphinxstylenotetitle, ..., \\sphinxstylewarningtitle, ...,\nfor an extra layer of mark-up freeing up \\sphinxstrong for other uses.\nSee :ref:latex-macros. (refs: #11267)
  • \n
  • LaTeX: :dudir:note, :dudir:hint, :dudir:important and :dudir:tip can\nnow each be styled as the other admonitions, i.e. possibly with a background\ncolor, individual border widths and paddings, possibly rounded corners, and\noptional shadow. See :ref:additionalcss. (refs: #11234)
  • \n
\n\n
\n

... (truncated)

\n
\n
\nCommits\n
    \n
  • e7d4c36 Bump to 6.2.0 final
  • \n
  • 4e27a5f Remove unneeded JavaScript from sphinx13 theme
  • \n
  • bffb547 Note correct deprecation version for sphinx.util.osutil.cd
  • \n
  • 59de8d5 Revert "Support and prefer .jinja to _t for static templates (#11165)...
  • \n
  • aee3c0a Partially revert "Disable localisation when SOURCE_DATE_EPOCH is set (#10949)...
  • \n
  • 186d596 Use overwrite_file context manager in test_ext_autodoc_configs (#11320)
  • \n
  • 77483f2 Add missing test decorator for test_util_inspect (#11321)
  • \n
  • d8f15c7 Increase timeout threshold for linkcheck tests (#11326)
  • \n
  • b430e05 Create a 'search field' component for themes (#11045)
  • \n
  • e2f66ce Update CHANGES for PR #11333
  • \n
  • Additional commits viewable in compare view
  • \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=6.1.3&new-version=6.2.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--2063.org.readthedocs.build/en/2063/\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/2063/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": 1674322631, "node_id": "PR_kwDOBm6k_c5OpEz_", "number": 2061, "title": "Add \"Packaging a plugin using Poetry\" section in docs", "user": {"value": 1238873, "label": "rclement"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 0, "created_at": "2023-04-19T07:23:28Z", "updated_at": "2023-04-19T07:27:18Z", "closed_at": null, "author_association": "FIRST_TIME_CONTRIBUTOR", "pull_request": "simonw/datasette/pulls/2061", "body": "This PR adds a new section about packaging a plugin using `poetry` within the \"Writing plugins\" page of the documentation.\r\n\r\n\r\n----\n:books: Documentation preview :books:: https://datasette--2061.org.readthedocs.build/en/2061/\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/2061/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": 1665510265, "node_id": "I_kwDOBm6k_c5jRat5", "number": 2060, "title": "Clean up a bunch of warnings from ruff", "user": {"value": 9599, "label": "simonw"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 0, "created_at": "2023-04-13T01:23:02Z", "updated_at": "2023-04-13T01:23:02Z", "closed_at": null, "author_association": "OWNER", "pull_request": null, "body": "See:\r\n- #2056\r\n\r\n`ruff` spots a bunch of warnings about things like unused variables - would be good to clean up as many of these as possible.", "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/2060/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": null} {"id": 1665200812, "node_id": "PR_kwDOCGYnMM5OKveS", "number": 537, "title": "Support self-referencing FKs in `Table.create`", "user": {"value": 544011, "label": "numist"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 3, "created_at": "2023-04-12T20:26:59Z", "updated_at": "2023-05-08T22:45:33Z", "closed_at": "2023-05-08T21:10:01Z", "author_association": "CONTRIBUTOR", "pull_request": "simonw/sqlite-utils/pulls/537", "body": "\r\n\r\n\r\n----\n:books: Documentation preview :books:: https://sqlite-utils--537.org.readthedocs.build/en/537/\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/537/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": 1665053646, "node_id": "I_kwDOBm6k_c5jPrPO", "number": 2059, "title": "\"Deceptive site ahead\" alert on Heroku deployment", "user": {"value": 1186275, "label": "mtdukes"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 1, "created_at": "2023-04-12T18:34:51Z", "updated_at": "2023-04-13T01:13:01Z", "closed_at": null, "author_association": "NONE", "pull_request": null, "body": "I deployed a fairly basic instance of Datasette (`datasette-auth-passwords` is the only plugin) using Heroku. The deployed URL now gives a \"Deceptive site ahead\" warning to users.\r\n\r\nIs there way around this? Maybe a way to add ownership verification [through Google's search console](https://search.google.com/search-console/welcome)? ", "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/2059/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": null} {"id": 1663399821, "node_id": "I_kwDOBm6k_c5jJXeN", "number": 2058, "title": "500 \"attempt to write a readonly database\" error caused by \"PRAGMA schema_version\"", "user": {"value": 9599, "label": "simonw"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 9, "created_at": "2023-04-11T23:57:50Z", "updated_at": "2023-04-13T16:35:21Z", "closed_at": null, "author_association": "OWNER", "pull_request": null, "body": "I've not been able to replicate this myself yet, but I've seen log files from a user affected by it.\r\n\r\n```\r\nFile \"/usr/local/lib/python3.11/site-packages/datasette/views/base.py\", line 89, in dispatch_request\r\nawait self.ds.refresh_schemas()\r\nFile \"/usr/local/lib/python3.11/site-packages/datasette/app.py\", line 371, in refresh_schemas\r\nawait self._refresh_schemas()\r\nFile \"/usr/local/lib/python3.11/site-packages/datasette/app.py\", line 386, in _refresh_schemas\r\nschema_version = (await db.execute(\"PRAGMA schema_version\")).first()[0]\r\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\r\nFile \"/usr/local/lib/python3.11/site-packages/datasette/database.py\", line 267, in execute\r\nresults = await self.execute_fn(sql_operation_in_thread)\r\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\r\nFile \"/usr/local/lib/python3.11/site-packages/datasette/database.py\", line 213, in execute_fn\r\nreturn await asyncio.get_event_loop().run_in_executor(\r\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\r\nFile \"/usr/local/lib/python3.11/concurrent/futures/thread.py\", line 58, in run\r\nresult = self.fn(*self.args, **self.kwargs)\r\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\r\nFile \"/usr/local/lib/python3.11/site-packages/datasette/database.py\", line 211, in in_thread\r\nreturn fn(conn)\r\n^^^^^^^^\r\nFile \"/usr/local/lib/python3.11/site-packages/datasette/database.py\", line 237, in sql_operation_in_thread\r\ncursor.execute(sql, params if params is not None else {})\r\nsqlite3.OperationalError: attempt to write a readonly database\r\n```\r\nThat's running the official Datasette Docker image on https://fly.io/ - it's causing 500 errors on every page of their site.", "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/2058/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": null} {"id": 1662951875, "node_id": "I_kwDOBm6k_c5jHqHD", "number": 2057, "title": "DeprecationWarning: pkg_resources is deprecated as an API", "user": {"value": 9599, "label": "simonw"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 3, "created_at": "2023-04-11T17:41:20Z", "updated_at": "2023-04-11T17:48:24Z", "closed_at": null, "author_association": "OWNER", "pull_request": null, "body": "Got this running tests against Python 3.11.\r\n\r\n```\r\n../../../.local/share/virtualenvs/datasette-big-local-6Yn-280V/lib/python3.11/site-packages/datasette/app.py:14: in \r\n import pkg_resources\r\n../../../.local/share/virtualenvs/datasette-big-local-6Yn-280V/lib/python3.11/site-packages/pkg_resources/__init__.py:121: in \r\n warnings.warn(\"pkg_resources is deprecated as an API\", DeprecationWarning)\r\nE DeprecationWarning: pkg_resources is deprecated as an API\r\n```\r\n\r\nI ran with `pytest -Werror --pdb -x` to get the debugger for that warning, but it turned out searching the code worked better. It's used in these two places:\r\n\r\nhttps://github.com/simonw/datasette/blob/5890a20c374fb0812d88c9b0ef26a838bfa06c76/datasette/plugins.py#L43-L50\r\n\r\nhttps://github.com/simonw/datasette/blob/5890a20c374fb0812d88c9b0ef26a838bfa06c76/datasette/app.py#L1037", "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/2057/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": null} {"id": 1661860507, "node_id": "PR_kwDOBm6k_c5N_bMw", "number": 2056, "title": "GitHub Action to lint Python code with ruff", "user": {"value": 3709715, "label": "cclauss"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 6, "created_at": "2023-04-11T06:41:27Z", "updated_at": "2023-04-15T14:24:46Z", "closed_at": null, "author_association": "FIRST_TIME_CONTRIBUTOR", "pull_request": "simonw/datasette/pulls/2056", "body": "[Ruff](https://beta.ruff.rs/) supports [over 500 lint rules](https://beta.ruff.rs/docs/rules) and can be used to replace [Flake8](https://pypi.org/project/flake8/) (plus dozens of plugins), [isort](https://pypi.org/project/isort/), [pydocstyle](https://pypi.org/project/pydocstyle/), [yesqa](https://github.com/asottile/yesqa), [eradicate](https://pypi.org/project/eradicate/), [pyupgrade](https://pypi.org/project/pyupgrade/), and [autoflake](https://pypi.org/project/autoflake/), all while executing (in Rust) tens or hundreds of times faster than any individual tool.\r\n\r\nThe ruff Action uses minimal steps to run in ~5 seconds, rapidly providing intuitive GitHub Annotations to contributors.\r\n\r\n![image](https://user-images.githubusercontent.com/3709715/223758136-afc386d2-70aa-4eff-953a-2c2d82ceea23.png)\r\n\r\n\r\n----\n:books: Documentation preview :books:: https://datasette--2056.org.readthedocs.build/en/2056/\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/2056/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": 1661617056, "node_id": "I_kwDODD6af85jCkOg", "number": 15, "title": "ambiguous column name: createdAt - on checkin_details view", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 0, "created_at": "2023-04-11T01:07:47Z", "updated_at": "2023-04-11T03:16:37Z", "closed_at": "2023-04-11T03:16:37Z", "author_association": "MEMBER", "pull_request": null, "body": "It looks like Swarm changed their schema and now both `venues` and `checkins` have `createdAt` fields.\r\n\r\nWhich breaks this view: https://github.com/dogsheep/swarm-to-sqlite/blob/719b6e96a016d0ca8b316d3bed9c2a7a0cb499ee/swarm_to_sqlite/utils.py#L171-L188", "repo": {"value": 205429375, "label": "swarm-to-sqlite"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/dogsheep/swarm-to-sqlite/issues/15/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": 1659525418, "node_id": "PR_kwDOCGYnMM5N35VZ", "number": 536, "title": "Add paths for homebrew on Apple silicon", "user": {"value": 25778, "label": "eyeseast"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 1, "created_at": "2023-04-08T13:34:21Z", "updated_at": "2023-04-13T01:44:43Z", "closed_at": "2023-04-13T01:44:43Z", "author_association": "CONTRIBUTOR", "pull_request": "simonw/sqlite-utils/pulls/536", "body": "Does what it says and nothing else. This is the same set of paths as Datasette uses.\r\n\r\n\r\n----\n:books: Documentation preview :books:: https://sqlite-utils--536.org.readthedocs.build/en/536/\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/536/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": 1657861026, "node_id": "I_kwDOBm6k_c5i0POi", "number": 2054, "title": "Make detailed notes on how table, query and row views work right now", "user": {"value": 9599, "label": "simonw"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 13, "created_at": "2023-04-06T18:21:09Z", "updated_at": "2023-04-07T20:14:38Z", "closed_at": null, "author_association": "OWNER", "pull_request": null, "body": "Research to help influence the following:\r\n- #2049 \r\n- #2053 \r\n- #2050 \r\n- #262 ", "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/2054/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": null} {"id": 1656432059, "node_id": "PR_kwDOBm6k_c5NuBNG", "number": 2053, "title": "WIP new JSON for queries", "user": {"value": 9599, "label": "simonw"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 7, "created_at": "2023-04-05T23:26:15Z", "updated_at": "2023-05-26T23:13:03Z", "closed_at": null, "author_association": "OWNER", "pull_request": "simonw/datasette/pulls/2053", "body": "Refs:\r\n- #2049\r\n\r\nTODO:\r\n\r\n- [x] Read queries JSON\r\n- [ ] Implement error display with `\"ok\": false` and an errors key\r\n- [ ] Read queries HTML\r\n- [ ] Read queries other formats (plugins)\r\n- [ ] Canned read queries (dispatched to from table)\r\n- [ ] Write queries (a canned query thing)\r\n- [ ] Implement different shapes, refactoring to share code with table\r\n- [ ] Implement a sensible subset of extras, also refactoring to share code with table\r\n- [ ] Get all tests passing\r\n\r\n\r\n----\r\n:books: Documentation preview :books:: https://datasette--2053.org.readthedocs.build/en/2053/\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/2053/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": 1, "state_reason": null} {"id": 1655860104, "node_id": "I_kwDOCGYnMM5ismuI", "number": 535, "title": "rows: --transpose or psql extended view-like functionality", "user": {"value": 7908073, "label": "chapmanjacobd"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 2, "created_at": "2023-04-05T15:37:33Z", "updated_at": "2023-06-15T08:39:49Z", "closed_at": "2023-06-14T22:05:28Z", "author_association": "CONTRIBUTOR", "pull_request": null, "body": "It would be nice if the rows subcommand had a flag, perhaps called `--transpose` which would print in long form instead of wide. Similar to extended display mode in psql (`\\x`)\r\n\r\nIn other words instead of this:\r\n\r\n```\r\nsqlite-utils rows --limit 5 --fmt github track_metadata.db songs\r\n```\r\n\r\n| track_id | title | song_id | release | artist_id | artist_mbid | artist_name | duration | artist_familiarity | artist_hotttnesss | year | track_7digitalid | shs_perf | shs_work |\r\n|--------------------|-------------------|--------------------|--------------------------------------|--------------------|--------------------------------------|------------------|------------|----------------------|---------------------|--------|--------------------|------------|------------|\r\n| TRMMMYQ128F932D901 | Silent Night | SOQMMHC12AB0180CB8 | Monster Ballads X-Mas | ARYZTJS1187B98C555 | 357ff05d-848a-44cf-b608-cb34b5701ae5 | Faster Pussy cat | 252.055 | 0.649822 | 0.394032 | 2003 | 7032331 | -1 | 0 |\r\n| TRMMMKD128F425225D | Tanssi vaan | SOVFVAK12A8C1350D9 | Karkuteill\u00e4 | ARMVN3U1187FB3A1EB | 8d7ef530-a6fd-4f8f-b2e2-74aec765e0f9 | Karkkiautomaatti | 156.551 | 0.439604 | 0.356992 | 1995 | 1514808 | -1 | 0 |\r\n| TRMMMRX128F93187D9 | No One Could Ever | SOGTUKN12AB017F4F1 | Butter | ARGEKB01187FB50750 | 3d403d44-36ce-465c-ad43-ae877e65adc4 | Hudson Mohawke | 138.971 | 0.643681 | 0.437504 | 2006 | 6945353 | -1 | 0 |\r\n| TRMMMCH128F425532C | Si Vos Quer\u00e9s | SOBNYVR12A8C13558C | De Culo | ARNWYLR1187B9B2F9C | 12be7648-7094-495f-90e6-df4189d68615 | Yerba Brava | 145.058 | 0.448501 | 0.372349 | 2003 | 2168257 | -1 | 0 |\r\n| TRMMMWA128F426B589 | Tangle Of Aspens | SOHSBXH12A8C13B0DF | Rene Ablaze Presents Winter Sessions | AREQDTE1269FB37231 | | Der Mystic | 514.298 | 0 | 0 | 0 | 2264873 | -1 | 0 |\r\n\r\n\r\nThe output would look something like this:\r\n\r\n```\r\n$ for col in (sqlite-columns track_metadata.db songs)\r\n sqlite-utils --fmt github track_metadata.db \"select $col from songs order by rowid desc limit 5\"\r\nend\r\n```\r\n\r\n| track_id |\r\n|--------------------|\r\n| TRYYYVU12903CD01E3 |\r\n| TRYYYDJ128F9310A21 |\r\n| TRYYYMG128F4260ECA |\r\n| TRYYYJO128F426DA37 |\r\n| TRYYYUS12903CD2DF0 |\r\n| title |\r\n|-------------------------------------|\r\n| Fernweh feat. Sektion Kuchik\u00e4schtli |\r\n| Faraday |\r\n| Novemba |\r\n| Jago Chhadeo |\r\n| O Samba Da Vida |\r\n| song_id |\r\n|--------------------|\r\n| SOWXJXQ12AB0189F43 |\r\n| SOLXGOR12A81C21EB7 |\r\n| SOHODZI12A8C137BB3 |\r\n| SOXQYIQ12A8C137FBB |\r\n| SOTXAME12AB018F136 |\r\n| release |\r\n|---------------------------------|\r\n| So Oder So |\r\n| The Trance Collection Vol. 2 |\r\n| Dub_Connected: electronic music |\r\n| Naale Baba Lassi Pee Gya |\r\n| Pacha V.I.P. |\r\n| artist_id |\r\n|--------------------|\r\n| AR7PLM21187B990D08 |\r\n| ARCMCOK1187B9B1073 |\r\n| ARZ3R6M1187B9AF750 |\r\n| ART5FZD1187B9A7FCF |\r\n| AR7Z4J81187FB3FC59 |\r\n| artist_mbid |\r\n|--------------------------------------|\r\n| 3af2b07e-c91c-4160-9bda-f0b9e3144ed3 |\r\n| 4ac5f3de-c5ad-475e-ad50-41f1ef9dba20 |\r\n| 8b97e9c8-61f5-4615-9a96-276f24204e34 |\r\n| 2357c400-9109-42b6-b3fe-9e2d9f8e3872 |\r\n| 9d50cb20-7e42-45cc-b0dd-154c3e92a577 |\r\n| artist_name |\r\n|----------------|\r\n| Texta |\r\n| Elude |\r\n| Gabriel Le Mar |\r\n| Kuldeep Manak |\r\n| Kiko Navarro |\r\n| duration |\r\n|------------|\r\n| 295.079 |\r\n| 484.519 |\r\n| 553.038 |\r\n| 244.166 |\r\n| 217.443 |\r\n| artist_familiarity |\r\n|----------------------|\r\n| 0.552977 |\r\n| 0.403668 |\r\n| 0.556918 |\r\n| 0.4015 |\r\n| 0.528617 |\r\n| artist_hotttnesss |\r\n|---------------------|\r\n| 0.454869 |\r\n| 0.256935 |\r\n| 0.336914 |\r\n| 0.374866 |\r\n| 0.411595 |\r\n| year |\r\n|--------|\r\n| 2004 |\r\n| 0 |\r\n| 0 |\r\n| 0 |\r\n| 0 |\r\n| track_7digitalid |\r\n|--------------------|\r\n| 8486723 |\r\n| 5472456 |\r\n| 2219291 |\r\n| 1632096 |\r\n| 7522478 |\r\n| shs_perf |\r\n|------------|\r\n| -1 |\r\n| -1 |\r\n| -1 |\r\n| -1 |\r\n| -1 |\r\n| shs_work |\r\n|------------|\r\n| 0 |\r\n| 0 |\r\n| 0 |\r\n| 0 |\r\n| 0 |\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/535/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": 1651082214, "node_id": "PR_kwDOBm6k_c5NcFCf", "number": 2052, "title": "feat: Javascript Plugin API (Custom panels, column menu items with JS actions)", "user": {"value": 9020979, "label": "hydrosquall"}, "state": "open", "locked": 0, "assignee": {"value": 15178711, "label": "asg017"}, "milestone": null, "comments": 16, "created_at": "2023-04-02T20:23:44Z", "updated_at": "2023-07-12T16:38:28Z", "closed_at": null, "author_association": "FIRST_TIME_CONTRIBUTOR", "pull_request": "simonw/datasette/pulls/2052", "body": "## Motivation\r\n\r\n- Allow plugins that add data visualizations [`datasette-vega`](https://github.com/simonw/datasette-vega), [`datasette-leaflet`](https://github.com/simonw/datasette-leaflet), and [`datasette-nteract-data-explorer`](https://github.com/hydrosquall/datasette-nteract-data-explorer) to co-exist safely\r\n- Standardize APIs / hooks to ease development for new JS plugin developers (better compat with datasette-lite) through standardized DOM selectors, methods for extending the existing Table UI. This has come up as a feature request several times (see research notes for examples)\r\n- Discussion w/ @simonw about a general-purpose Datasette JS API\r\n\r\n## Changes\r\n\r\nSummary: Provide 2 new surface areas for Datasette JS plugin developers\r\n\r\n1. Custom column header items: \r\n2. Basic \"panels\" controlled by buttons: \r\n\r\n### User Facing Changes\r\n\r\n- Allow creating menu items under table header that triggers JS (instead of opening hrefs per the existing [menu_link](https://docs.datasette.io/en/stable/plugin_hooks.html#menu-links-datasette-actor-request) hook). Items can respond to any column metadata provided by the column header (e.g. label). The proof of concept plugins log data to the console, or copy the column name to clipboard.\r\n- Allow plugins to register UI elements in a panel controller. The parent component handles switching the visibility of active plugins.\r\n - Because native button elements are used, the panel is keyboard-accessible - use tab / shift-tab to cycle through tab options, and `enter` to select.\r\n - There's room to improve the styling, but the focus of this PR is on the API rather than the UX.\r\n\r\n### (plugin) Developer Facing Changes\r\n\r\n- Dispatch a `datasette_init` [CustomEvent](https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent) when the `datasetteManager` is finished loading.\r\n- Provide `manager.registerPlugin` API for adding new functionality that coordinates with Datasette lifecycle events.\r\n- Provide a `manager.selectors` map of DOM elements that users may want to hook into.\r\n - Updated `table.js` to use refer to these to motivating keeping things in sync\r\n- Allow plugins to register themselves with 2 hooks:\r\n - `makeColumnActions`: Add items to menu in table column headers. Users can provide a `label`, and either `href` or `onClick` with full access to the metadata for the clicked column (name, type, misc. booleans)\r\n - `makeAboveTablePanelConfigs`: Add items to the panel. Each panel has a unique ID (namespaced within that plugin), a render function, and a string label.\r\n\r\nSee [this file](https://github.com/simonw/datasette/blob/2d92b9328022d86505261bcdac419b6ed9cb2236/datasette/static/table-example-plugins.js) for example plugin usage.\r\n\r\n### Core Developer Facing Changes\r\n\r\n- Modified `table.js` to make use of the `datasetteManager` API.\r\n- Added example plugins to the `demos/plugins` folder, and stored the test js in the `statics/` folder\r\n\r\n## Testing\r\n\r\nFor Datasette plugin developers, please see the [alpha-level documentation](https://github.com/simonw/datasette/pull/2052#issuecomment-1510423051) .\r\n\r\nTo run the examples:\r\n\r\n```bash\r\ndatasette serve fixtures.db --plugins-dir=demos/plugins/\r\n```\r\n\r\nOpen local server: `http://127.0.0.1:8001/fixtures/facetable`\r\n\r\nOpen to all feedback on this PR, from API design to variable naming, to what additional hooks might be useful for the future.\r\n\r\nMy focus was more on the general shape of the API for developers, rather than on the UX of the test plugins.\r\n\r\n## Design notes\r\n\r\n- The manager tab panel could be a separate plugin if the implementation is too custom.\r\n- The `makeColumnHeaderItems` benefits from hooking into the logic of `table.js`\r\n- I wanted to offer this to the Datasette core, since the `datasette-manager` would be more powerful if it were connected to lifecycle and JS events that are part of the existing table.js.\r\n- Non-goals:\r\n - Dependency management (for now) - there's no \"build\" step, we don't know when new plugins will be added. While there are some valid use cases (for example, allow multiple plugins to wait for a global leaflet object to be loaded), I don't see enough use-cases to justify doing this yet.\r\n - Enabling single-page-app features - for now, most datasette actions lead to a new page being loaded. SPA development offers some benefits (no page jumping after clicking on a link), but also complexity that doesn't need to be in the core Datasette project.\r\n\r\n## Research Notes\r\n\r\n- Relocated to a [comment](https://github.com/simonw/datasette/pull/2052#issuecomment-1510423215), as this isn't required to review when evaluating the plugin. Including it just for those who are curious.\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/2052/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": 1650984552, "node_id": "PR_kwDOJHON9s5NbyYN", "number": 13, "title": "use universal command", "user": {"value": 14314871, "label": "amlestin"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 0, "created_at": "2023-04-02T15:10:54Z", "updated_at": "2023-04-02T15:37:34Z", "closed_at": null, "author_association": "FIRST_TIME_CONTRIBUTOR", "pull_request": "dogsheep/apple-notes-to-sqlite/pulls/13", "body": null, "repo": {"value": 611552758, "label": "apple-notes-to-sqlite"}, "type": "pull", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/dogsheep/apple-notes-to-sqlite/issues/13/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": 1650981564, "node_id": "I_kwDOJHON9s5iZ_q8", "number": 12, "title": "Error running pytest", "user": {"value": 14314871, "label": "amlestin"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 0, "created_at": "2023-04-02T15:02:36Z", "updated_at": "2023-04-02T15:07:10Z", "closed_at": null, "author_association": "NONE", "pull_request": null, "body": "`______________________________________________________ ERROR collecting tests/test_apple_notes_to_sqlite.py _______________________________________________________\r\nImportError while importing test module '/Users/lol/development/apple-notes-to-sqlite/tests/test_apple_notes_to_sqlite.py'.\r\nHint: make sure your test modules/packages have valid Python names.\r\nTraceback:\r\n/opt/homebrew/Cellar/python@3.9/3.9.16/Frameworks/Python.framework/Versions/3.9/lib/python3.9/importlib/__init__.py:127: in import_module\r\n return _bootstrap._gcd_import(name[level:], package, level)\r\ntests/test_apple_notes_to_sqlite.py:2: in \r\n from apple_notes_to_sqlite.cli import cli, COUNT_SCRIPT, FOLDERS_SCRIPT\r\nE ModuleNotFoundError: No module named 'apple_notes_to_sqlite'`\r\n\r\nSolution:\r\nThis is likely a PYTHONPATH issue due to having pytest installed both globally and in the venv. We can guarantee the tests run by adding the current directory to sys.path automatically using\r\n\r\n`python -m pytest`\r\n\r\nThe alternative is to activate the venv, install pytest, deactivate, then activate the venv again (https://stackoverflow.com/questions/35045038/how-do-i-use-pytest-with-virtualenv)", "repo": {"value": 611552758, "label": "apple-notes-to-sqlite"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/dogsheep/apple-notes-to-sqlite/issues/12/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": null} {"id": 1649793525, "node_id": "I_kwDOBm6k_c5iVdn1", "number": 2051, "title": "`?_extra=row_urls` for table pages", "user": {"value": 9599, "label": "simonw"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 0, "created_at": "2023-03-31T17:58:36Z", "updated_at": "2023-03-31T17:58:36Z", "closed_at": null, "author_association": "OWNER", "pull_request": null, "body": "Provides URLs to the JSON version of those rows. Maybe it persists the `?_shape=` option too? Not sure about that.", "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/2051/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": null} {"id": 1649791661, "node_id": "I_kwDOBm6k_c5iVdKt", "number": 2050, "title": "Row page JSON should use new ?_extra= format", "user": {"value": 9599, "label": "simonw"}, "state": "open", "locked": 0, "assignee": null, "milestone": {"value": 8755003, "label": "Datasette 1.0a3"}, "comments": 1, "created_at": "2023-03-31T17:56:53Z", "updated_at": "2023-03-31T17:59:49Z", "closed_at": null, "author_association": "OWNER", "pull_request": null, "body": "https://latest.datasette.io/fixtures/facetable/2.json\r\n\r\nRelated:\r\n- #2049\r\n- #1709 ", "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/2050/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": null} {"id": 1646734246, "node_id": "I_kwDOBm6k_c5iJyum", "number": 2049, "title": "Custom SQL queries should use new JSON ?_extra= format", "user": {"value": 9599, "label": "simonw"}, "state": "open", "locked": 0, "assignee": null, "milestone": {"value": 8755003, "label": "Datasette 1.0a3"}, "comments": 4, "created_at": "2023-03-30T00:42:53Z", "updated_at": "2023-04-05T23:29:27Z", "closed_at": null, "author_association": "OWNER", "pull_request": null, "body": "Related:\r\n- #262\r\n\r\nI've made the change to the table view, now I need the new format to work for arbitrary SQL queries too.\r\n\r\nNote that this incorporates both arbitrary SQL queries and canned queries.", "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/2049/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": null} {"id": 1646068413, "node_id": "I_kwDOBm6k_c5iHQK9", "number": 2048, "title": "Test failures encountered while packaging for GNU Guix", "user": {"value": 8332263, "label": "Apteryks"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 0, "created_at": "2023-03-29T15:36:54Z", "updated_at": "2023-03-29T15:36:54Z", "closed_at": null, "author_association": "NONE", "pull_request": null, "body": "Hello,\r\n\r\nWhile reviewing a packaged submitted to Guix to add `datasette`, the test suite produces the following errors:\r\n```\r\n=================================== FAILURES ===================================\r\n_________________________ test_row_strange_table_name __________________________\r\n[gw21] linux -- Python 3.9.9 /gnu/store/slsh0qjv5j68xda2bb6h8gsxwyi1j25a-python-wrapper-3.9.9/bin/python\r\n\r\napp_client = \r\n\r\n def test_row_strange_table_name(app_client):\r\n response = app_client.get(\r\n \"/fixtures/table~2Fwith~2Fslashes~2Ecsv/3.json?_shape=objects\"\r\n )\r\n> assert response.status == 200\r\nE assert 400 == 200\r\nE + where 400 = .status\r\n\r\n/tmp/guix-build-datasette-0.64.2.drv-0/source/tests/test_api.py:701: AssertionError\r\n----------------------------- Captured stderr call -----------------------------\r\nERROR: conn=, sql = 'select rowid, * from [table%7E2Fwith%7E2Fslashes%7E2Ecsv] where \"rowid\"=:p0', params = {'p0': '3'}: no such table: table%7E2Fwith%7E2Fslashes%7E2Ecsv\r\n_______________ test_database_page_for_database_with_dot_in_name _______________\r\n[gw15] linux -- Python 3.9.9 /gnu/store/slsh0qjv5j68xda2bb6h8gsxwyi1j25a-python-wrapper-3.9.9/bin/python\r\n\r\napp_client_with_dot = \r\n\r\n def test_database_page_for_database_with_dot_in_name(app_client_with_dot):\r\n response = app_client_with_dot.get(\"/fixtures~2Edot.json\")\r\n> assert response.status == 200\r\nE assert 302 == 200\r\nE + where 302 = .status\r\n\r\n/tmp/guix-build-datasette-0.64.2.drv-0/source/tests/test_api.py:633: AssertionError\r\n___________________ test_tilde_encoded_database_names[fo%o] ____________________\r\n[gw6] linux -- Python 3.9.9 /gnu/store/slsh0qjv5j68xda2bb6h8gsxwyi1j25a-python-wrapper-3.9.9/bin/python\r\n\r\ndb_name = 'fo%o'\r\n\r\n @pytest.mark.asyncio\r\n @pytest.mark.parametrize(\"db_name\", (\"foo\", r\"fo%o\", \"f~/c.d\"))\r\n async def test_tilde_encoded_database_names(db_name):\r\n ds = Datasette()\r\n ds.add_memory_database(db_name)\r\n response = await ds.client.get(\"/.json\")\r\n assert db_name in response.json().keys()\r\n path = response.json()[db_name][\"path\"]\r\n # And the JSON for that database\r\n response2 = await ds.client.get(path + \".json\")\r\n> assert response2.status_code == 200\r\nE assert 302 == 200\r\nE + where 302 = .status_code\r\n\r\n/tmp/guix-build-datasette-0.64.2.drv-0/source/tests/test_api.py:983: AssertionError\r\n__________________ test_tilde_encoded_database_names[f~/c.d] ___________________\r\n[gw7] linux -- Python 3.9.9 /gnu/store/slsh0qjv5j68xda2bb6h8gsxwyi1j25a-python-wrapper-3.9.9/bin/python\r\n\r\ndb_name = 'f~/c.d'\r\n\r\n @pytest.mark.asyncio\r\n @pytest.mark.parametrize(\"db_name\", (\"foo\", r\"fo%o\", \"f~/c.d\"))\r\n async def test_tilde_encoded_database_names(db_name):\r\n ds = Datasette()\r\n ds.add_memory_database(db_name)\r\n response = await ds.client.get(\"/.json\")\r\n assert db_name in response.json().keys()\r\n path = response.json()[db_name][\"path\"]\r\n # And the JSON for that database\r\n response2 = await ds.client.get(path + \".json\")\r\n> assert response2.status_code == 200\r\nE assert 302 == 200\r\nE + where 302 = .status_code\r\n\r\n/tmp/guix-build-datasette-0.64.2.drv-0/source/tests/test_api.py:983: AssertionError\r\n______________ test_database_with_space_in_name[/searchable.json] ______________\r\n[gw21] linux -- Python 3.9.9 /gnu/store/slsh0qjv5j68xda2bb6h8gsxwyi1j25a-python-wrapper-3.9.9/bin/python\r\n\r\napp_client_two_attached_databases = \r\npath = '/searchable.json'\r\n\r\n @pytest.mark.parametrize(\r\n \"path\",\r\n (\r\n \"/\",\r\n \".json\",\r\n \"/searchable\",\r\n \"/searchable.json\",\r\n \"/searchable_view\",\r\n \"/searchable_view.json\",\r\n ),\r\n )\r\n def test_database_with_space_in_name(app_client_two_attached_databases, path):\r\n> response = app_client_two_attached_databases.get(\r\n \"/extra~20database\" + path, follow_redirects=True\r\n )\r\n\r\n/tmp/guix-build-datasette-0.64.2.drv-0/source/tests/test_api.py:920: \r\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \r\n/gnu/store/mcclmphjgbrgpa0v037a4nlq336482g8-python-asgiref-3.4.1/lib/python3.9/site-packages/asgiref/sync.py:223: in __call__\r\n return call_result.result()\r\n/gnu/store/65i3nhcwmz0p8rqbg48gaavyky4g4hwk-python-3.9.9/lib/python3.9/concurrent/futures/_base.py:438: in result\r\n return self.__get_result()\r\n/gnu/store/65i3nhcwmz0p8rqbg48gaavyky4g4hwk-python-3.9.9/lib/python3.9/concurrent/futures/_base.py:390: in __get_result\r\n raise self._exception\r\n/gnu/store/mcclmphjgbrgpa0v037a4nlq336482g8-python-asgiref-3.4.1/lib/python3.9/site-packages/asgiref/sync.py:292: in main_wrap\r\n result = await self.awaitable(*args, **kwargs)\r\n/tmp/guix-build-datasette-0.64.2.drv-0/source/datasette/utils/testing.py:66: in get\r\n return await self._request(\r\n/tmp/guix-build-datasette-0.64.2.drv-0/source/datasette/utils/testing.py:156: in _request\r\n httpx_response = await self.ds.client.request(\r\n/tmp/guix-build-datasette-0.64.2.drv-0/source/datasette/app.py:1602: in request\r\n return await client.request(\r\n/gnu/store/bj5lb299rfb4cbbq5kczq9imdk9a7y64-python-httpx-0.23.0/lib/python3.9/site-packages/httpx/_client.py:1527: in request\r\n return await self.send(request, auth=auth, follow_redirects=follow_redirects)\r\n/gnu/store/bj5lb299rfb4cbbq5kczq9imdk9a7y64-python-httpx-0.23.0/lib/python3.9/site-packages/httpx/_client.py:1614: in send\r\n response = await self._send_handling_auth(\r\n/gnu/store/bj5lb299rfb4cbbq5kczq9imdk9a7y64-python-httpx-0.23.0/lib/python3.9/site-packages/httpx/_client.py:1642: in _send_handling_auth\r\n response = await self._send_handling_redirects(\r\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \r\n\r\nself = \r\nrequest = \r\nfollow_redirects = True\r\nhistory = [, , , , , , ...]\r\n\r\n async def _send_handling_redirects(\r\n self,\r\n request: Request,\r\n follow_redirects: bool,\r\n history: typing.List[Response],\r\n ) -> Response:\r\n while True:\r\n if len(history) > self.max_redirects:\r\n> raise TooManyRedirects(\r\n \"Exceeded maximum allowed redirects.\", request=request\r\n )\r\nE httpx.TooManyRedirects: Exceeded maximum allowed redirects.\r\n\r\n/gnu/store/bj5lb299rfb4cbbq5kczq9imdk9a7y64-python-httpx-0.23.0/lib/python3.9/site-packages/httpx/_client.py:1672: TooManyRedirects\r\n___________________ test_database_with_space_in_name[.json] ____________________\r\n[gw19] linux -- Python 3.9.9 /gnu/store/slsh0qjv5j68xda2bb6h8gsxwyi1j25a-python-wrapper-3.9.9/bin/python\r\n\r\napp_client_two_attached_databases = \r\npath = '.json'\r\n\r\n @pytest.mark.parametrize(\r\n \"path\",\r\n (\r\n \"/\",\r\n \".json\",\r\n \"/searchable\",\r\n \"/searchable.json\",\r\n \"/searchable_view\",\r\n \"/searchable_view.json\",\r\n ),\r\n )\r\n def test_database_with_space_in_name(app_client_two_attached_databases, path):\r\n> response = app_client_two_attached_databases.get(\r\n \"/extra~20database\" + path, follow_redirects=True\r\n )\r\n\r\n/tmp/guix-build-datasette-0.64.2.drv-0/source/tests/test_api.py:920: \r\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \r\n/gnu/store/mcclmphjgbrgpa0v037a4nlq336482g8-python-asgiref-3.4.1/lib/python3.9/site-packages/asgiref/sync.py:223: in __call__\r\n return call_result.result()\r\n/gnu/store/65i3nhcwmz0p8rqbg48gaavyky4g4hwk-python-3.9.9/lib/python3.9/concurrent/futures/_base.py:438: in result\r\n return self.__get_result()\r\n/gnu/store/65i3nhcwmz0p8rqbg48gaavyky4g4hwk-python-3.9.9/lib/python3.9/concurrent/futures/_base.py:390: in __get_result\r\n raise self._exception\r\n/gnu/store/mcclmphjgbrgpa0v037a4nlq336482g8-python-asgiref-3.4.1/lib/python3.9/site-packages/asgiref/sync.py:292: in main_wrap\r\n result = await self.awaitable(*args, **kwargs)\r\n/tmp/guix-build-datasette-0.64.2.drv-0/source/datasette/utils/testing.py:66: in get\r\n return await self._request(\r\n/tmp/guix-build-datasette-0.64.2.drv-0/source/datasette/utils/testing.py:156: in _request\r\n httpx_response = await self.ds.client.request(\r\n/tmp/guix-build-datasette-0.64.2.drv-0/source/datasette/app.py:1602: in request\r\n return await client.request(\r\n/gnu/store/bj5lb299rfb4cbbq5kczq9imdk9a7y64-python-httpx-0.23.0/lib/python3.9/site-packages/httpx/_client.py:1527: in request\r\n return await self.send(request, auth=auth, follow_redirects=follow_redirects)\r\n/gnu/store/bj5lb299rfb4cbbq5kczq9imdk9a7y64-python-httpx-0.23.0/lib/python3.9/site-packages/httpx/_client.py:1614: in send\r\n response = await self._send_handling_auth(\r\n/gnu/store/bj5lb299rfb4cbbq5kczq9imdk9a7y64-python-httpx-0.23.0/lib/python3.9/site-packages/httpx/_client.py:1642: in _send_handling_auth\r\n response = await self._send_handling_redirects(\r\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \r\n\r\nself = \r\nrequest = \r\nfollow_redirects = True\r\nhistory = [, , , , , , ...]\r\n\r\n async def _send_handling_redirects(\r\n self,\r\n request: Request,\r\n follow_redirects: bool,\r\n history: typing.List[Response],\r\n ) -> Response:\r\n while True:\r\n if len(history) > self.max_redirects:\r\n> raise TooManyRedirects(\r\n \"Exceeded maximum allowed redirects.\", request=request\r\n )\r\nE httpx.TooManyRedirects: Exceeded maximum allowed redirects.\r\n\r\n/gnu/store/bj5lb299rfb4cbbq5kczq9imdk9a7y64-python-httpx-0.23.0/lib/python3.9/site-packages/httpx/_client.py:1672: TooManyRedirects\r\n______________ test_database_with_space_in_name[/searchable_view] ______________\r\n[gw22] linux -- Python 3.9.9 /gnu/store/slsh0qjv5j68xda2bb6h8gsxwyi1j25a-python-wrapper-3.9.9/bin/python\r\n\r\napp_client_two_attached_databases = \r\npath = '/searchable_view'\r\n\r\n @pytest.mark.parametrize(\r\n \"path\",\r\n (\r\n \"/\",\r\n \".json\",\r\n \"/searchable\",\r\n \"/searchable.json\",\r\n \"/searchable_view\",\r\n \"/searchable_view.json\",\r\n ),\r\n )\r\n def test_database_with_space_in_name(app_client_two_attached_databases, path):\r\n> response = app_client_two_attached_databases.get(\r\n \"/extra~20database\" + path, follow_redirects=True\r\n )\r\n\r\n/tmp/guix-build-datasette-0.64.2.drv-0/source/tests/test_api.py:920: \r\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \r\n/gnu/store/mcclmphjgbrgpa0v037a4nlq336482g8-python-asgiref-3.4.1/lib/python3.9/site-packages/asgiref/sync.py:223: in __call__\r\n return call_result.result()\r\n/gnu/store/65i3nhcwmz0p8rqbg48gaavyky4g4hwk-python-3.9.9/lib/python3.9/concurrent/futures/_base.py:438: in result\r\n return self.__get_result()\r\n/gnu/store/65i3nhcwmz0p8rqbg48gaavyky4g4hwk-python-3.9.9/lib/python3.9/concurrent/futures/_base.py:390: in __get_result\r\n raise self._exception\r\n/gnu/store/mcclmphjgbrgpa0v037a4nlq336482g8-python-asgiref-3.4.1/lib/python3.9/site-packages/asgiref/sync.py:292: in main_wrap\r\n result = await self.awaitable(*args, **kwargs)\r\n/tmp/guix-build-datasette-0.64.2.drv-0/source/datasette/utils/testing.py:66: in get\r\n return await self._request(\r\n/tmp/guix-build-datasette-0.64.2.drv-0/source/datasette/utils/testing.py:156: in _request\r\n httpx_response = await self.ds.client.request(\r\n/tmp/guix-build-datasette-0.64.2.drv-0/source/datasette/app.py:1602: in request\r\n return await client.request(\r\n/gnu/store/bj5lb299rfb4cbbq5kczq9imdk9a7y64-python-httpx-0.23.0/lib/python3.9/site-packages/httpx/_client.py:1527: in request\r\n return await self.send(request, auth=auth, follow_redirects=follow_redirects)\r\n/gnu/store/bj5lb299rfb4cbbq5kczq9imdk9a7y64-python-httpx-0.23.0/lib/python3.9/site-packages/httpx/_client.py:1614: in send\r\n response = await self._send_handling_auth(\r\n/gnu/store/bj5lb299rfb4cbbq5kczq9imdk9a7y64-python-httpx-0.23.0/lib/python3.9/site-packages/httpx/_client.py:1642: in _send_handling_auth\r\n response = await self._send_handling_redirects(\r\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \r\n\r\nself = \r\nrequest = \r\nfollow_redirects = True\r\nhistory = [, , , , , , ...]\r\n\r\n async def _send_handling_redirects(\r\n self,\r\n request: Request,\r\n follow_redirects: bool,\r\n history: typing.List[Response],\r\n ) -> Response:\r\n while True:\r\n if len(history) > self.max_redirects:\r\n> raise TooManyRedirects(\r\n \"Exceeded maximum allowed redirects.\", request=request\r\n )\r\nE httpx.TooManyRedirects: Exceeded maximum allowed redirects.\r\n\r\n/gnu/store/bj5lb299rfb4cbbq5kczq9imdk9a7y64-python-httpx-0.23.0/lib/python3.9/site-packages/httpx/_client.py:1672: TooManyRedirects\r\n_____________________ test_database_with_space_in_name[/] ______________________\r\n[gw18] linux -- Python 3.9.9 /gnu/store/slsh0qjv5j68xda2bb6h8gsxwyi1j25a-python-wrapper-3.9.9/bin/python\r\n\r\napp_client_two_attached_databases = \r\npath = '/'\r\n\r\n @pytest.mark.parametrize(\r\n \"path\",\r\n (\r\n \"/\",\r\n \".json\",\r\n \"/searchable\",\r\n \"/searchable.json\",\r\n \"/searchable_view\",\r\n \"/searchable_view.json\",\r\n ),\r\n )\r\n def test_database_with_space_in_name(app_client_two_attached_databases, path):\r\n> response = app_client_two_attached_databases.get(\r\n \"/extra~20database\" + path, follow_redirects=True\r\n )\r\n\r\n/tmp/guix-build-datasette-0.64.2.drv-0/source/tests/test_api.py:920: \r\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \r\n/gnu/store/mcclmphjgbrgpa0v037a4nlq336482g8-python-asgiref-3.4.1/lib/python3.9/site-packages/asgiref/sync.py:223: in __call__\r\n return call_result.result()\r\n/gnu/store/65i3nhcwmz0p8rqbg48gaavyky4g4hwk-python-3.9.9/lib/python3.9/concurrent/futures/_base.py:438: in result\r\n return self.__get_result()\r\n/gnu/store/65i3nhcwmz0p8rqbg48gaavyky4g4hwk-python-3.9.9/lib/python3.9/concurrent/futures/_base.py:390: in __get_result\r\n raise self._exception\r\n/gnu/store/mcclmphjgbrgpa0v037a4nlq336482g8-python-asgiref-3.4.1/lib/python3.9/site-packages/asgiref/sync.py:292: in main_wrap\r\n result = await self.awaitable(*args, **kwargs)\r\n/tmp/guix-build-datasette-0.64.2.drv-0/source/datasette/utils/testing.py:66: in get\r\n return await self._request(\r\n/tmp/guix-build-datasette-0.64.2.drv-0/source/datasette/utils/testing.py:156: in _request\r\n httpx_response = await self.ds.client.request(\r\n/tmp/guix-build-datasette-0.64.2.drv-0/source/datasette/app.py:1602: in request\r\n return await client.request(\r\n/gnu/store/bj5lb299rfb4cbbq5kczq9imdk9a7y64-python-httpx-0.23.0/lib/python3.9/site-packages/httpx/_client.py:1527: in request\r\n return await self.send(request, auth=auth, follow_redirects=follow_redirects)\r\n/gnu/store/bj5lb299rfb4cbbq5kczq9imdk9a7y64-python-httpx-0.23.0/lib/python3.9/site-packages/httpx/_client.py:1614: in send\r\n response = await self._send_handling_auth(\r\n/gnu/store/bj5lb299rfb4cbbq5kczq9imdk9a7y64-python-httpx-0.23.0/lib/python3.9/site-packages/httpx/_client.py:1642: in _send_handling_auth\r\n response = await self._send_handling_redirects(\r\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \r\n\r\nself = \r\nrequest = \r\nfollow_redirects = True\r\nhistory = [, , , , , , ...]\r\n\r\n async def _send_handling_redirects(\r\n self,\r\n request: Request,\r\n follow_redirects: bool,\r\n history: typing.List[Response],\r\n ) -> Response:\r\n while True:\r\n if len(history) > self.max_redirects:\r\n> raise TooManyRedirects(\r\n \"Exceeded maximum allowed redirects.\", request=request\r\n )\r\nE httpx.TooManyRedirects: Exceeded maximum allowed redirects.\r\n\r\n/gnu/store/bj5lb299rfb4cbbq5kczq9imdk9a7y64-python-httpx-0.23.0/lib/python3.9/site-packages/httpx/_client.py:1672: TooManyRedirects\r\n________________ test_database_with_space_in_name[/searchable] _________________\r\n[gw20] linux -- Python 3.9.9 /gnu/store/slsh0qjv5j68xda2bb6h8gsxwyi1j25a-python-wrapper-3.9.9/bin/python\r\n\r\napp_client_two_attached_databases = \r\npath = '/searchable'\r\n\r\n @pytest.mark.parametrize(\r\n \"path\",\r\n (\r\n \"/\",\r\n \".json\",\r\n \"/searchable\",\r\n \"/searchable.json\",\r\n \"/searchable_view\",\r\n \"/searchable_view.json\",\r\n ),\r\n )\r\n def test_database_with_space_in_name(app_client_two_attached_databases, path):\r\n> response = app_client_two_attached_databases.get(\r\n \"/extra~20database\" + path, follow_redirects=True\r\n )\r\n\r\n/tmp/guix-build-datasette-0.64.2.drv-0/source/tests/test_api.py:920: \r\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \r\n/gnu/store/mcclmphjgbrgpa0v037a4nlq336482g8-python-asgiref-3.4.1/lib/python3.9/site-packages/asgiref/sync.py:223: in __call__\r\n return call_result.result()\r\n/gnu/store/65i3nhcwmz0p8rqbg48gaavyky4g4hwk-python-3.9.9/lib/python3.9/concurrent/futures/_base.py:438: in result\r\n return self.__get_result()\r\n/gnu/store/65i3nhcwmz0p8rqbg48gaavyky4g4hwk-python-3.9.9/lib/python3.9/concurrent/futures/_base.py:390: in __get_result\r\n raise self._exception\r\n/gnu/store/mcclmphjgbrgpa0v037a4nlq336482g8-python-asgiref-3.4.1/lib/python3.9/site-packages/asgiref/sync.py:292: in main_wrap\r\n result = await self.awaitable(*args, **kwargs)\r\n/tmp/guix-build-datasette-0.64.2.drv-0/source/datasette/utils/testing.py:66: in get\r\n return await self._request(\r\n/tmp/guix-build-datasette-0.64.2.drv-0/source/datasette/utils/testing.py:156: in _request\r\n httpx_response = await self.ds.client.request(\r\n/tmp/guix-build-datasette-0.64.2.drv-0/source/datasette/app.py:1602: in request\r\n return await client.request(\r\n/gnu/store/bj5lb299rfb4cbbq5kczq9imdk9a7y64-python-httpx-0.23.0/lib/python3.9/site-packages/httpx/_client.py:1527: in request\r\n return await self.send(request, auth=auth, follow_redirects=follow_redirects)\r\n/gnu/store/bj5lb299rfb4cbbq5kczq9imdk9a7y64-python-httpx-0.23.0/lib/python3.9/site-packages/httpx/_client.py:1614: in send\r\n response = await self._send_handling_auth(\r\n/gnu/store/bj5lb299rfb4cbbq5kczq9imdk9a7y64-python-httpx-0.23.0/lib/python3.9/site-packages/httpx/_client.py:1642: in _send_handling_auth\r\n response = await self._send_handling_redirects(\r\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \r\n\r\nself = \r\nrequest = \r\nfollow_redirects = True\r\nhistory = [, , , , , , ...]\r\n\r\n async def _send_handling_redirects(\r\n self,\r\n request: Request,\r\n follow_redirects: bool,\r\n history: typing.List[Response],\r\n ) -> Response:\r\n while True:\r\n if len(history) > self.max_redirects:\r\n> raise TooManyRedirects(\r\n \"Exceeded maximum allowed redirects.\", request=request\r\n )\r\nE httpx.TooManyRedirects: Exceeded maximum allowed redirects.\r\n\r\n/gnu/store/bj5lb299rfb4cbbq5kczq9imdk9a7y64-python-httpx-0.23.0/lib/python3.9/site-packages/httpx/_client.py:1672: TooManyRedirects\r\n___________ test_database_with_space_in_name[/searchable_view.json] ____________\r\n[gw23] linux -- Python 3.9.9 /gnu/store/slsh0qjv5j68xda2bb6h8gsxwyi1j25a-python-wrapper-3.9.9/bin/python\r\n\r\napp_client_two_attached_databases = \r\npath = '/searchable_view.json'\r\n\r\n @pytest.mark.parametrize(\r\n \"path\",\r\n (\r\n \"/\",\r\n \".json\",\r\n \"/searchable\",\r\n \"/searchable.json\",\r\n \"/searchable_view\",\r\n \"/searchable_view.json\",\r\n ),\r\n )\r\n def test_database_with_space_in_name(app_client_two_attached_databases, path):\r\n> response = app_client_two_attached_databases.get(\r\n \"/extra~20database\" + path, follow_redirects=True\r\n )\r\n\r\n/tmp/guix-build-datasette-0.64.2.drv-0/source/tests/test_api.py:920: \r\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \r\n/gnu/store/mcclmphjgbrgpa0v037a4nlq336482g8-python-asgiref-3.4.1/lib/python3.9/site-packages/asgiref/sync.py:223: in __call__\r\n return call_result.result()\r\n/gnu/store/65i3nhcwmz0p8rqbg48gaavyky4g4hwk-python-3.9.9/lib/python3.9/concurrent/futures/_base.py:438: in result\r\n return self.__get_result()\r\n/gnu/store/65i3nhcwmz0p8rqbg48gaavyky4g4hwk-python-3.9.9/lib/python3.9/concurrent/futures/_base.py:390: in __get_result\r\n raise self._exception\r\n/gnu/store/mcclmphjgbrgpa0v037a4nlq336482g8-python-asgiref-3.4.1/lib/python3.9/site-packages/asgiref/sync.py:292: in main_wrap\r\n result = await self.awaitable(*args, **kwargs)\r\n/tmp/guix-build-datasette-0.64.2.drv-0/source/datasette/utils/testing.py:66: in get\r\n return await self._request(\r\n/tmp/guix-build-datasette-0.64.2.drv-0/source/datasette/utils/testing.py:156: in _request\r\n httpx_response = await self.ds.client.request(\r\n/tmp/guix-build-datasette-0.64.2.drv-0/source/datasette/app.py:1602: in request\r\n return await client.request(\r\n/gnu/store/bj5lb299rfb4cbbq5kczq9imdk9a7y64-python-httpx-0.23.0/lib/python3.9/site-packages/httpx/_client.py:1527: in request\r\n return await self.send(request, auth=auth, follow_redirects=follow_redirects)\r\n/gnu/store/bj5lb299rfb4cbbq5kczq9imdk9a7y64-python-httpx-0.23.0/lib/python3.9/site-packages/httpx/_client.py:1614: in send\r\n response = await self._send_handling_auth(\r\n/gnu/store/bj5lb299rfb4cbbq5kczq9imdk9a7y64-python-httpx-0.23.0/lib/python3.9/site-packages/httpx/_client.py:1642: in _send_handling_auth\r\n response = await self._send_handling_redirects(\r\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \r\n\r\nself = \r\nrequest = \r\nfollow_redirects = True\r\nhistory = [, , , , , , ...]\r\n\r\n async def _send_handling_redirects(\r\n self,\r\n request: Request,\r\n follow_redirects: bool,\r\n history: typing.List[Response],\r\n ) -> Response:\r\n while True:\r\n if len(history) > self.max_redirects:\r\n> raise TooManyRedirects(\r\n \"Exceeded maximum allowed redirects.\", request=request\r\n )\r\nE httpx.TooManyRedirects: Exceeded maximum allowed redirects.\r\n\r\n/gnu/store/bj5lb299rfb4cbbq5kczq9imdk9a7y64-python-httpx-0.23.0/lib/python3.9/site-packages/httpx/_client.py:1672: TooManyRedirects\r\n________________ test_weird_database_names[database (1).sqlite] ________________\r\n[gw7] linux -- Python 3.9.9 /gnu/store/slsh0qjv5j68xda2bb6h8gsxwyi1j25a-python-wrapper-3.9.9/bin/python\r\n\r\ntmpdir = local('/tmp/guix-build-datasette-0.64.2.drv-0/pytest-of-nixbld/pytest-0/popen-gw7/test_weird_database_names_data0')\r\nfilename = 'database (1).sqlite'\r\n\r\n @pytest.mark.parametrize(\r\n \"filename\", [\"test-database (1).sqlite\", \"database (1).sqlite\"]\r\n )\r\n def test_weird_database_names(tmpdir, filename):\r\n # https://github.com/simonw/datasette/issues/1181\r\n runner = CliRunner()\r\n db_path = str(tmpdir / filename)\r\n sqlite3.connect(db_path).execute(\"vacuum\")\r\n result1 = runner.invoke(cli, [db_path, \"--get\", \"/\"])\r\n assert result1.exit_code == 0, result1.output\r\n filename_no_stem = filename.rsplit(\".\", 1)[0]\r\n expected_link = '{}'.format(\r\n tilde_encode(filename_no_stem), filename_no_stem\r\n )\r\n assert expected_link in result1.output\r\n # Now try hitting that database page\r\n result2 = runner.invoke(\r\n cli, [db_path, \"--get\", \"/{}\".format(tilde_encode(filename_no_stem))]\r\n )\r\n> assert result2.exit_code == 0, result2.output\r\nE AssertionError: \r\nE \r\nE assert 1 == 0\r\nE + where 1 = .exit_code\r\n\r\n/tmp/guix-build-datasette-0.64.2.drv-0/source/tests/test_cli.py:321: AssertionError\r\n_____________ test_weird_database_names[test-database (1).sqlite] ______________\r\n[gw6] linux -- Python 3.9.9 /gnu/store/slsh0qjv5j68xda2bb6h8gsxwyi1j25a-python-wrapper-3.9.9/bin/python\r\n\r\ntmpdir = local('/tmp/guix-build-datasette-0.64.2.drv-0/pytest-of-nixbld/pytest-0/popen-gw6/test_weird_database_names_test0')\r\nfilename = 'test-database (1).sqlite'\r\n\r\n @pytest.mark.parametrize(\r\n \"filename\", [\"test-database (1).sqlite\", \"database (1).sqlite\"]\r\n )\r\n def test_weird_database_names(tmpdir, filename):\r\n # https://github.com/simonw/datasette/issues/1181\r\n runner = CliRunner()\r\n db_path = str(tmpdir / filename)\r\n sqlite3.connect(db_path).execute(\"vacuum\")\r\n result1 = runner.invoke(cli, [db_path, \"--get\", \"/\"])\r\n assert result1.exit_code == 0, result1.output\r\n filename_no_stem = filename.rsplit(\".\", 1)[0]\r\n expected_link = '{}'.format(\r\n tilde_encode(filename_no_stem), filename_no_stem\r\n )\r\n assert expected_link in result1.output\r\n # Now try hitting that database page\r\n result2 = runner.invoke(\r\n cli, [db_path, \"--get\", \"/{}\".format(tilde_encode(filename_no_stem))]\r\n )\r\n> assert result2.exit_code == 0, result2.output\r\nE AssertionError: \r\nE \r\nE assert 1 == 0\r\nE + where 1 = .exit_code\r\n\r\n/tmp/guix-build-datasette-0.64.2.drv-0/source/tests/test_cli.py:321: AssertionError\r\n_ test_row_html_compound_primary_key[/fixtures/compound_primary_key/a~2Fb,~2Ec~2Dd-expected1] _\r\n[gw11] linux -- Python 3.9.9 /gnu/store/slsh0qjv5j68xda2bb6h8gsxwyi1j25a-python-wrapper-3.9.9/bin/python\r\n\r\napp_client = \r\npath = '/fixtures/compound_primary_key/a~2Fb,~2Ec~2Dd'\r\nexpected = [['
', '', '']]\r\n\r\n @pytest.mark.parametrize(\r\n \"path,expected\",\r\n (\r\n (\r\n \"/fixtures/compound_primary_key/a,b\",\r\n [\r\n [\r\n '',\r\n '',\r\n '',\r\n ]\r\n ],\r\n ),\r\n (\r\n \"/fixtures/compound_primary_key/a~2Fb,~2Ec~2Dd\",\r\n [\r\n [\r\n '',\r\n '',\r\n '',\r\n ]\r\n ],\r\n ),\r\n ),\r\n )\r\n def test_row_html_compound_primary_key(app_client, path, expected):\r\n response = app_client.get(path)\r\n> assert response.status == 200\r\nE assert 302 == 200\r\nE + where 302 = .status\r\n\r\n/tmp/guix-build-datasette-0.64.2.drv-0/source/tests/test_html.py:370: AssertionError\r\n_ test_css_classes_on_body[/fixtures/table~2Fwith~2Fslashes~2Ecsv-expected_classes5] _\r\n[gw3] linux -- Python 3.9.9 /gnu/store/slsh0qjv5j68xda2bb6h8gsxwyi1j25a-python-wrapper-3.9.9/bin/python\r\n\r\napp_client = \r\npath = '/fixtures/table~2Fwith~2Fslashes~2Ecsv'\r\nexpected_classes = ['table', 'db-fixtures', 'table-tablewithslashescsv-fa7563']\r\n\r\n @pytest.mark.parametrize(\r\n \"path,expected_classes\",\r\n [\r\n (\"/\", [\"index\"]),\r\n (\"/fixtures\", [\"db\", \"db-fixtures\"]),\r\n (\"/fixtures?sql=select+1\", [\"query\", \"db-fixtures\"]),\r\n (\r\n \"/fixtures/simple_primary_key\",\r\n [\"table\", \"db-fixtures\", \"table-simple_primary_key\"],\r\n ),\r\n (\r\n \"/fixtures/neighborhood_search\",\r\n [\"query\", \"db-fixtures\", \"query-neighborhood_search\"],\r\n ),\r\n (\r\n \"/fixtures/table~2Fwith~2Fslashes~2Ecsv\",\r\n [\"table\", \"db-fixtures\", \"table-tablewithslashescsv-fa7563\"],\r\n ),\r\n (\r\n \"/fixtures/simple_primary_key/1\",\r\n [\"row\", \"db-fixtures\", \"table-simple_primary_key\"],\r\n ),\r\n ],\r\n )\r\n def test_css_classes_on_body(app_client, path, expected_classes):\r\n response = app_client.get(path)\r\n> assert response.status == 200\r\nE assert 302 == 200\r\nE + where 302 = .status\r\n\r\n/tmp/guix-build-datasette-0.64.2.drv-0/source/tests/test_html.py:238: AssertionError\r\n_ test_templates_considered[/fixtures/table~2Fwith~2Fslashes~2Ecsv-table-fixtures-tablewithslashescsv-fa7563.html, *table.html] _\r\n[gw3] linux -- Python 3.9.9 /gnu/store/slsh0qjv5j68xda2bb6h8gsxwyi1j25a-python-wrapper-3.9.9/bin/python\r\n\r\napp_client = \r\npath = '/fixtures/table~2Fwith~2Fslashes~2Ecsv'\r\nexpected_considered = 'table-fixtures-tablewithslashescsv-fa7563.html, *table.html'\r\n\r\n @pytest.mark.parametrize(\r\n \"path,expected_considered\",\r\n [\r\n (\"/\", \"*index.html\"),\r\n (\"/fixtures\", \"database-fixtures.html, *database.html\"),\r\n (\r\n \"/fixtures/simple_primary_key\",\r\n \"table-fixtures-simple_primary_key.html, *table.html\",\r\n ),\r\n (\r\n \"/fixtures/table~2Fwith~2Fslashes~2Ecsv\",\r\n \"table-fixtures-tablewithslashescsv-fa7563.html, *table.html\",\r\n ),\r\n (\r\n \"/fixtures/simple_primary_key/1\",\r\n \"row-fixtures-simple_primary_key.html, *row.html\",\r\n ),\r\n ],\r\n )\r\n def test_templates_considered(app_client, path, expected_considered):\r\n response = app_client.get(path)\r\n> assert response.status == 200\r\nE assert 302 == 200\r\nE + where 302 = .status\r\n\r\n/tmp/guix-build-datasette-0.64.2.drv-0/source/tests/test_html.py:264: AssertionError\r\n_ test_alternate_url_json[/fixtures/table~2Fwith~2Fslashes~2Ecsv-http://localhost/fixtures/table~2Fwith~2Fslashes~2Ecsv.json] _\r\n[gw21] linux -- Python 3.9.9 /gnu/store/slsh0qjv5j68xda2bb6h8gsxwyi1j25a-python-wrapper-3.9.9/bin/python\r\n\r\napp_client = \r\npath = '/fixtures/table~2Fwith~2Fslashes~2Ecsv'\r\nexpected = 'http://localhost/fixtures/table~2Fwith~2Fslashes~2Ecsv.json'\r\n\r\n @pytest.mark.parametrize(\r\n \"path,expected\",\r\n (\r\n # Instance index page\r\n (\"/\", \"http://localhost/.json\"),\r\n # Table page\r\n (\"/fixtures/facetable\", \"http://localhost/fixtures/facetable.json\"),\r\n (\r\n \"/fixtures/table~2Fwith~2Fslashes~2Ecsv\",\r\n \"http://localhost/fixtures/table~2Fwith~2Fslashes~2Ecsv.json\",\r\n ),\r\n # Row page\r\n (\r\n \"/fixtures/no_primary_key/1\",\r\n \"http://localhost/fixtures/no_primary_key/1.json\",\r\n ),\r\n # Database index page\r\n (\r\n \"/fixtures\",\r\n \"http://localhost/fixtures.json\",\r\n ),\r\n # Custom query page\r\n (\r\n \"/fixtures?sql=select+*+from+facetable\",\r\n \"http://localhost/fixtures.json?sql=select+*+from+facetable\",\r\n ),\r\n # Canned query page\r\n (\r\n \"/fixtures/neighborhood_search?text=town\",\r\n \"http://localhost/fixtures/neighborhood_search.json?text=town\",\r\n ),\r\n # /-/ pages\r\n (\r\n \"/-/plugins\",\r\n \"http://localhost/-/plugins.json\",\r\n ),\r\n ),\r\n )\r\n def test_alternate_url_json(app_client, path, expected):\r\n response = app_client.get(path)\r\n> assert response.status == 200\r\nE assert 302 == 200\r\nE + where 302 = .status\r\n\r\n/tmp/guix-build-datasette-0.64.2.drv-0/source/tests/test_html.py:948: AssertionError\r\n_ test_edit_sql_link_on_canned_queries[/fixtures/~F0~9D~90~9C~F0~9D~90~A2~F0~9D~90~AD~F0~9D~90~A2~F0~9D~90~9E~F0~9D~90~AC-/fixtures?sql=select+id%2C+name+from+facet_cities+order+by+id+limit+1%3B] _\r\n[gw18] linux -- Python 3.9.9 /gnu/store/slsh0qjv5j68xda2bb6h8gsxwyi1j25a-python-wrapper-3.9.9/bin/python\r\n\r\napp_client = \r\npath = '/fixtures/~F0~9D~90~9C~F0~9D~90~A2~F0~9D~90~AD~F0~9D~90~A2~F0~9D~90~9E~F0~9D~90~AC'\r\nexpected = '/fixtures?sql=select+id%2C+name+from+facet_cities+order+by+id+limit+1%3B'\r\n\r\n @pytest.mark.parametrize(\r\n \"path,expected\",\r\n [\r\n (\r\n \"/fixtures/neighborhood_search\",\r\n \"/fixtures?sql=%0Aselect+_neighborhood%2C+facet_cities.name%2C+state%0Afrom+facetable%0A++++join+facet_cities%0A++++++++on+facetable._city_id+%3D+facet_cities.id%0Awhere+_neighborhood+like+%27%25%27+%7C%7C+%3Atext+%7C%7C+%27%25%27%0Aorder+by+_neighborhood%3B%0A&text=\",\r\n ),\r\n (\r\n \"/fixtures/neighborhood_search?text=ber\",\r\n \"/fixtures?sql=%0Aselect+_neighborhood%2C+facet_cities.name%2C+state%0Afrom+facetable%0A++++join+facet_cities%0A++++++++on+facetable._city_id+%3D+facet_cities.id%0Awhere+_neighborhood+like+%27%25%27+%7C%7C+%3Atext+%7C%7C+%27%25%27%0Aorder+by+_neighborhood%3B%0A&text=ber\",\r\n ),\r\n (\"/fixtures/pragma_cache_size\", None),\r\n (\r\n # /fixtures/\ud835\udc1c\ud835\udc22\ud835\udc2d\ud835\udc22\ud835\udc1e\ud835\udc2c\r\n \"/fixtures/~F0~9D~90~9C~F0~9D~90~A2~F0~9D~90~AD~F0~9D~90~A2~F0~9D~90~9E~F0~9D~90~AC\",\r\n \"/fixtures?sql=select+id%2C+name+from+facet_cities+order+by+id+limit+1%3B\",\r\n ),\r\n (\"/fixtures/magic_parameters\", None),\r\n ],\r\n )\r\n def test_edit_sql_link_on_canned_queries(app_client, path, expected):\r\n response = app_client.get(path)\r\n> assert response.status == 200\r\nE assert 302 == 200\r\nE + where 302 = .status\r\n\r\n/tmp/guix-build-datasette-0.64.2.drv-0/source/tests/test_html.py:841: AssertionError\r\n_______________________ test_table_with_slashes_in_name ________________________\r\n[gw9] linux -- Python 3.9.9 /gnu/store/slsh0qjv5j68xda2bb6h8gsxwyi1j25a-python-wrapper-3.9.9/bin/python\r\n\r\napp_client = \r\n\r\n def test_table_with_slashes_in_name(app_client):\r\n response = app_client.get(\r\n \"/fixtures/table~2Fwith~2Fslashes~2Ecsv.json?_shape=objects\"\r\n )\r\n> assert response.status == 200\r\nE assert 302 == 200\r\nE + where 302 = .status\r\n\r\n/tmp/guix-build-datasette-0.64.2.drv-0/source/tests/test_table_api.py:141: AssertionError\r\n__________________ test_custom_query_with_unicode_characters ___________________\r\n[gw8] linux -- Python 3.9.9 /gnu/store/slsh0qjv5j68xda2bb6h8gsxwyi1j25a-python-wrapper-3.9.9/bin/python\r\n\r\napp_client = \r\n\r\n def test_custom_query_with_unicode_characters(app_client):\r\n # /fixtures/\ud835\udc1c\ud835\udc22\ud835\udc2d\ud835\udc22\ud835\udc1e\ud835\udc2c.json\r\n response = app_client.get(\r\n \"/fixtures/~F0~9D~90~9C~F0~9D~90~A2~F0~9D~90~AD~F0~9D~90~A2~F0~9D~90~9E~F0~9D~90~AC.json?_shape=array\"\r\n )\r\n> assert [{\"id\": 1, \"name\": \"San Francisco\"}] == response.json\r\n\r\n/tmp/guix-build-datasette-0.64.2.drv-0/source/tests/test_table_api.py:1042: \r\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \r\n/tmp/guix-build-datasette-0.64.2.drv-0/source/datasette/utils/testing.py:40: in json\r\n return json.loads(self.text)\r\n/gnu/store/65i3nhcwmz0p8rqbg48gaavyky4g4hwk-python-3.9.9/lib/python3.9/json/__init__.py:346: in loads\r\n return _default_decoder.decode(s)\r\n/gnu/store/65i3nhcwmz0p8rqbg48gaavyky4g4hwk-python-3.9.9/lib/python3.9/json/decoder.py:337: in decode\r\n obj, end = self.raw_decode(s, idx=_w(s, 0).end())\r\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \r\n\r\nself = , s = '', idx = 0\r\n\r\n def raw_decode(self, s, idx=0):\r\n \"\"\"Decode a JSON document from ``s`` (a ``str`` beginning with\r\n a JSON document) and return a 2-tuple of the Python\r\n representation and the index in ``s`` where the document ended.\r\n \r\n This can be used to decode a JSON document from a string that may\r\n have extraneous data at the end.\r\n \r\n \"\"\"\r\n try:\r\n obj, end = self.scan_once(s, idx)\r\n except StopIteration as err:\r\n> raise JSONDecodeError(\"Expecting value\", s, err.value) from None\r\nE json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)\r\n\r\n/gnu/store/65i3nhcwmz0p8rqbg48gaavyky4g4hwk-python-3.9.9/lib/python3.9/json/decoder.py:355: JSONDecodeError\r\n_ test_searchable[/fixtures/searchable.json?_search=te*+AND+do*&_searchmode=raw-expected_rows3] _\r\n[gw13] linux -- Python 3.9.9 /gnu/store/slsh0qjv5j68xda2bb6h8gsxwyi1j25a-python-wrapper-3.9.9/bin/python\r\n\r\napp_client = \r\npath = '/fixtures/searchable.json?_search=te*+AND+do*&_searchmode=raw'\r\nexpected_rows = [[1, 'barry cat', 'terry dog', 'panther'], [2, 'terry dog', 'sara weasel', 'puma']]\r\n\r\n @pytest.mark.parametrize(\r\n \"path,expected_rows\",\r\n [\r\n (\r\n \"/fixtures/searchable.json?_search=dog\",\r\n [\r\n [1, \"barry cat\", \"terry dog\", \"panther\"],\r\n [2, \"terry dog\", \"sara weasel\", \"puma\"],\r\n ],\r\n ),\r\n (\r\n # Special keyword shouldn't break FTS query\r\n \"/fixtures/searchable.json?_search=AND\",\r\n [],\r\n ),\r\n (\r\n # Without _searchmode=raw this should return no results\r\n \"/fixtures/searchable.json?_search=te*+AND+do*\",\r\n [],\r\n ),\r\n (\r\n # _searchmode=raw\r\n \"/fixtures/searchable.json?_search=te*+AND+do*&_searchmode=raw\",\r\n [\r\n [1, \"barry cat\", \"terry dog\", \"panther\"],\r\n [2, \"terry dog\", \"sara weasel\", \"puma\"],\r\n ],\r\n ),\r\n (\r\n # _searchmode=raw combined with _search_COLUMN\r\n \"/fixtures/searchable.json?_search_text2=te*&_searchmode=raw\",\r\n [\r\n [1, \"barry cat\", \"terry dog\", \"panther\"],\r\n ],\r\n ),\r\n (\r\n \"/fixtures/searchable.json?_search=weasel\",\r\n [[2, \"terry dog\", \"sara weasel\", \"puma\"]],\r\n ),\r\n (\r\n \"/fixtures/searchable.json?_search_text2=dog\",\r\n [[1, \"barry cat\", \"terry dog\", \"panther\"]],\r\n ),\r\n (\r\n \"/fixtures/searchable.json?_search_name%20with%20.%20and%20spaces=panther\",\r\n [[1, \"barry cat\", \"terry dog\", \"panther\"]],\r\n ),\r\n ],\r\n )\r\n def test_searchable(app_client, path, expected_rows):\r\n response = app_client.get(path)\r\n> assert expected_rows == response.json[\"rows\"]\r\nE AssertionError: assert [[1, 'barry cat', 'terry dog', 'panther'],\\n [2, 'terry dog', 'sara weasel', 'puma']] == []\r\nE Left contains 2 more items, first extra item: [1, 'barry cat', 'terry dog', 'panther']\r\nE Full diff:\r\nE [\r\nE - ,\r\nE + [1,\r\nE + 'barry cat',\r\nE + 'terry dog',\r\nE + 'panther'],\r\nE + [2,\r\nE + 'terry dog',\r\nE + 'sara weasel',\r\nE + 'puma'],\r\nE ]\r\n\r\n/tmp/guix-build-datasette-0.64.2.drv-0/source/tests/test_table_api.py:402: AssertionError\r\n_____ test_searchmode[table_metadata1-_search=te*+AND+do*-expected_rows1] ______\r\n[gw20] linux -- Python 3.9.9 /gnu/store/slsh0qjv5j68xda2bb6h8gsxwyi1j25a-python-wrapper-3.9.9/bin/python\r\n\r\ntable_metadata = {'searchmode': 'raw'}, querystring = '_search=te*+AND+do*'\r\nexpected_rows = [[1, 'barry cat', 'terry dog', 'panther'], [2, 'terry dog', 'sara weasel', 'puma']]\r\n\r\n @pytest.mark.parametrize(\r\n \"table_metadata,querystring,expected_rows\",\r\n [\r\n (\r\n {},\r\n \"_search=te*+AND+do*\",\r\n [],\r\n ),\r\n (\r\n {\"searchmode\": \"raw\"},\r\n \"_search=te*+AND+do*\",\r\n _SEARCHMODE_RAW_RESULTS,\r\n ),\r\n (\r\n {},\r\n \"_search=te*+AND+do*&_searchmode=raw\",\r\n _SEARCHMODE_RAW_RESULTS,\r\n ),\r\n # Can be over-ridden with _searchmode=escaped\r\n (\r\n {\"searchmode\": \"raw\"},\r\n \"_search=te*+AND+do*&_searchmode=escaped\",\r\n [],\r\n ),\r\n ],\r\n )\r\n def test_searchmode(table_metadata, querystring, expected_rows):\r\n with make_app_client(\r\n metadata={\"databases\": {\"fixtures\": {\"tables\": {\"searchable\": table_metadata}}}}\r\n ) as client:\r\n response = client.get(\"/fixtures/searchable.json?\" + querystring)\r\n> assert expected_rows == response.json[\"rows\"]\r\nE AssertionError: assert [[1, 'barry cat', 'terry dog', 'panther'],\\n [2, 'terry dog', 'sara weasel', 'puma']] == []\r\nE Left contains 2 more items, first extra item: [1, 'barry cat', 'terry dog', 'panther']\r\nE Full diff:\r\nE [\r\nE - ,\r\nE + [1,\r\nE + 'barry cat',\r\nE + 'terry dog',\r\nE + 'panther'],\r\nE + [2,\r\nE + 'terry dog',\r\nE + 'sara weasel',\r\nE + 'puma'],\r\nE ]\r\n\r\n/tmp/guix-build-datasette-0.64.2.drv-0/source/tests/test_table_api.py:442: AssertionError\r\n_ test_searchmode[table_metadata2-_search=te*+AND+do*&_searchmode=raw-expected_rows2] _\r\n[gw20] linux -- Python 3.9.9 /gnu/store/slsh0qjv5j68xda2bb6h8gsxwyi1j25a-python-wrapper-3.9.9/bin/python\r\n\r\ntable_metadata = {}, querystring = '_search=te*+AND+do*&_searchmode=raw'\r\nexpected_rows = [[1, 'barry cat', 'terry dog', 'panther'], [2, 'terry dog', 'sara weasel', 'puma']]\r\n\r\n @pytest.mark.parametrize(\r\n \"table_metadata,querystring,expected_rows\",\r\n [\r\n (\r\n {},\r\n \"_search=te*+AND+do*\",\r\n [],\r\n ),\r\n (\r\n {\"searchmode\": \"raw\"},\r\n \"_search=te*+AND+do*\",\r\n _SEARCHMODE_RAW_RESULTS,\r\n ),\r\n (\r\n {},\r\n \"_search=te*+AND+do*&_searchmode=raw\",\r\n _SEARCHMODE_RAW_RESULTS,\r\n ),\r\n # Can be over-ridden with _searchmode=escaped\r\n (\r\n {\"searchmode\": \"raw\"},\r\n \"_search=te*+AND+do*&_searchmode=escaped\",\r\n [],\r\n ),\r\n ],\r\n )\r\n def test_searchmode(table_metadata, querystring, expected_rows):\r\n with make_app_client(\r\n metadata={\"databases\": {\"fixtures\": {\"tables\": {\"searchable\": table_metadata}}}}\r\n ) as client:\r\n response = client.get(\"/fixtures/searchable.json?\" + querystring)\r\n> assert expected_rows == response.json[\"rows\"]\r\nE AssertionError: assert [[1, 'barry cat', 'terry dog', 'panther'],\\n [2, 'terry dog', 'sara weasel', 'puma']] == []\r\nE Left contains 2 more items, first extra item: [1, 'barry cat', 'terry dog', 'panther']\r\nE Full diff:\r\nE [\r\nE - ,\r\nE + [1,\r\nE + 'barry cat',\r\nE + 'terry dog',\r\nE + 'panther'],\r\nE + [2,\r\nE + 'terry dog',\r\nE + 'sara weasel',\r\nE + 'puma'],\r\nE ]\r\n\r\n/tmp/guix-build-datasette-0.64.2.drv-0/source/tests/test_table_api.py:442: AssertionError\r\n=========================== short test summary info ============================\r\nFAILED tests/test_api.py::test_row_strange_table_name - assert 400 == 200\r\nFAILED tests/test_api.py::test_database_page_for_database_with_dot_in_name - ...\r\nFAILED tests/test_api.py::test_tilde_encoded_database_names[fo%o] - assert 30...\r\nFAILED tests/test_api.py::test_tilde_encoded_database_names[f~/c.d] - assert ...\r\nFAILED tests/test_api.py::test_database_with_space_in_name[/searchable.json]\r\nFAILED tests/test_api.py::test_database_with_space_in_name[.json] - httpx.Too...\r\nFAILED tests/test_api.py::test_database_with_space_in_name[/searchable_view]\r\nFAILED tests/test_api.py::test_database_with_space_in_name[/] - httpx.TooMany...\r\nFAILED tests/test_api.py::test_database_with_space_in_name[/searchable] - htt...\r\nFAILED tests/test_api.py::test_database_with_space_in_name[/searchable_view.json]\r\nFAILED tests/test_cli.py::test_weird_database_names[database (1).sqlite] - As...\r\nFAILED tests/test_cli.py::test_weird_database_names[test-database (1).sqlite]\r\nFAILED tests/test_html.py::test_row_html_compound_primary_key[/fixtures/compound_primary_key/a~2Fb,~2Ec~2Dd-expected1]\r\nFAILED tests/test_html.py::test_css_classes_on_body[/fixtures/table~2Fwith~2Fslashes~2Ecsv-expected_classes5]\r\nFAILED tests/test_html.py::test_templates_considered[/fixtures/table~2Fwith~2Fslashes~2Ecsv-table-fixtures-tablewithslashescsv-fa7563.html, *table.html]\r\nFAILED tests/test_html.py::test_alternate_url_json[/fixtures/table~2Fwith~2Fslashes~2Ecsv-http://localhost/fixtures/table~2Fwith~2Fslashes~2Ecsv.json]\r\nFAILED tests/test_html.py::test_edit_sql_link_on_canned_queries[/fixtures/~F0~9D~90~9C~F0~9D~90~A2~F0~9D~90~AD~F0~9D~90~A2~F0~9D~90~9E~F0~9D~90~AC-/fixtures?sql=select+id%2C+name+from+facet_cities+order+by+id+limit+1%3B]\r\nFAILED tests/test_table_api.py::test_table_with_slashes_in_name - assert 302 ...\r\nFAILED tests/test_table_api.py::test_custom_query_with_unicode_characters - j...\r\nFAILED tests/test_table_api.py::test_searchable[/fixtures/searchable.json?_search=te*+AND+do*&_searchmode=raw-expected_rows3]\r\nFAILED tests/test_table_api.py::test_searchmode[table_metadata1-_search=te*+AND+do*-expected_rows1]\r\nFAILED tests/test_table_api.py::test_searchmode[table_metadata2-_search=te*+AND+do*&_searchmode=raw-expected_rows2]\r\n=========== 22 failed, 1049 passed, 3 skipped in 1522.28s (0:25:22) ============\r\nerror: in phase 'check': uncaught exception:\r\n%exception #<&invoke-error program: \"/gnu/store/ziqwkzz6znb5d3c245xn0cq5ra2ly0w3-python-pytest-7.1.3/bin/pytest\" arguments: (\"-vv\" \"-n\" \"24\" \"-m\" \"not serial\") exit-status: 1 term-signal: #f stop-signal: #f> \r\nphase `check' failed after 1523.3 seconds\r\n```\r\nThe tests run in a private namespace without internet connectivity, and the Python dependencies are at:\r\n```\r\npython-aiofiles@0.6.0 python-asgi-csrf@0.9 python-asgiref@3.4.1\r\n+ python-beautifulsoup4@4.11.1 python-black@22.3.0 python-click-default-group@1.2.2 python-click@8.1.3\r\n+ python-cogapp@3.3.0 python-httpx@0.23.0 python-hupper@1.10.3 python-itsdangerous@2.0.1\r\n+ python-janus@1.0.0 python-jinja2@3.1.1 python-mergedeep@1.3.4 python-pint@0.20.1 python-pluggy@1.0.0\r\n+ python-pytest-asyncio@0.17.2 python-pytest-runner@5.2 python-pytest-timeout@2.0.2\r\n+ python-pytest-xdist@2.5.0 python-pytest@7.1.3 python-pyyaml@6.0 python-setuptools@64.0.3\r\n+ python-trustme@0.9.0 python-uvicorn@0.17.6\r\n```\r\nWith Python 3.9.9.\r\n\r\nThank you!", "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/2048/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": null} {"id": 1645098678, "node_id": "PR_kwDOBm6k_c5NIQri", "number": 2047, "title": "Bump black from 22.12.0 to 23.3.0", "user": {"value": 49699333, "label": "dependabot[bot]"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 0, "created_at": "2023-03-29T06:09:06Z", "updated_at": "2023-03-29T06:12:21Z", "closed_at": "2023-03-29T06:12:05Z", "author_association": "CONTRIBUTOR", "pull_request": "simonw/datasette/pulls/2047", "body": "Bumps [black](https://github.com/psf/black) from 22.12.0 to 23.3.0.\n
\nRelease notes\n

Sourced from black's releases.

\n
\n

23.3.0

\n

Highlights

\n

This release fixes a longstanding confusing behavior in Black's GitHub action, where the\nversion of the action did not determine the version of Black being run (issue #3382). In\naddition, there is a small bug fix around imports and a number of improvements to the\npreview style.

\n

Please try out the\npreview style\nwith black --preview and tell us your feedback. All changes in the preview style are\nexpected to become part of Black's stable style in January 2024.

\n

Stable style

\n
    \n
  • Import lines with # fmt: skip and # fmt: off no longer have an extra blank line\nadded when they are right after another import line (#3610)
  • \n
\n

Preview style

\n
    \n
  • Add trailing commas to collection literals even if there's a comment after the last\nentry (#3393)
  • \n
  • async def, async for, and async with statements are now formatted consistently\ncompared to their non-async version. (#3609)
  • \n
  • with statements that contain two context managers will be consistently wrapped in\nparentheses (#3589)
  • \n
  • Let string splitters respect East Asian Width\n(#3445)
  • \n
  • Now long string literals can be split after East Asian commas and periods (\u3001 U+3001\nIDEOGRAPHIC COMMA, \u3002 U+3002 IDEOGRAPHIC FULL STOP, & \uff0c U+FF0C FULLWIDTH COMMA)\nbesides before spaces (#3445)
  • \n
  • For stubs, enforce one blank line after a nested class with a body other than just\n... (#3564)
  • \n
  • Improve handling of multiline strings by changing line split behavior (#1879)
  • \n
\n

Parser

\n
    \n
  • Added support for formatting files with invalid type comments (#3594)
  • \n
\n

Integrations

\n
    \n
  • Update GitHub Action to use the version of Black equivalent to action's version if\nversion input is not specified (#3543)
  • \n
  • Fix missing Python binary path in autoload script for vim (#3508)
  • \n
\n

Documentation

\n
    \n
  • Document that only the most recent release is supported for security issues;\nvulnerabilities should be reported through Tidelift (#3612)
  • \n
\n\n
\n

... (truncated)

\n
\n
\nChangelog\n

Sourced from black's changelog.

\n
\n

23.3.0

\n

Highlights

\n

This release fixes a longstanding confusing behavior in Black's GitHub action, where the\nversion of the action did not determine the version of Black being run (issue #3382). In\naddition, there is a small bug fix around imports and a number of improvements to the\npreview style.

\n

Please try out the\npreview style\nwith black --preview and tell us your feedback. All changes in the preview style are\nexpected to become part of Black's stable style in January 2024.

\n

Stable style

\n
    \n
  • Import lines with # fmt: skip and # fmt: off no longer have an extra blank line\nadded when they are right after another import line (#3610)
  • \n
\n

Preview style

\n
    \n
  • Add trailing commas to collection literals even if there's a comment after the last\nentry (#3393)
  • \n
  • async def, async for, and async with statements are now formatted consistently\ncompared to their non-async version. (#3609)
  • \n
  • with statements that contain two context managers will be consistently wrapped in\nparentheses (#3589)
  • \n
  • Let string splitters respect East Asian Width\n(#3445)
  • \n
  • Now long string literals can be split after East Asian commas and periods (\u3001 U+3001\nIDEOGRAPHIC COMMA, \u3002 U+3002 IDEOGRAPHIC FULL STOP, & \uff0c U+FF0C FULLWIDTH COMMA)\nbesides before spaces (#3445)
  • \n
  • For stubs, enforce one blank line after a nested class with a body other than just\n... (#3564)
  • \n
  • Improve handling of multiline strings by changing line split behavior (#1879)
  • \n
\n

Parser

\n
    \n
  • Added support for formatting files with invalid type comments (#3594)
  • \n
\n

Integrations

\n
    \n
  • Update GitHub Action to use the version of Black equivalent to action's version if\nversion input is not specified (#3543)
  • \n
  • Fix missing Python binary path in autoload script for vim (#3508)
  • \n
\n

Documentation

\n
    \n
  • Document that only the most recent release is supported for security issues;\nvulnerabilities should be reported through Tidelift (#3612)
  • \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=black&package-manager=pip&previous-version=22.12.0&new-version=23.3.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--2047.org.readthedocs.build/en/2047/\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/2047/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": 1644018605, "node_id": "PR_kwDOBm6k_c5NEqBO", "number": 2046, "title": "Bump furo from 2022.12.7 to 2023.3.27", "user": {"value": 49699333, "label": "dependabot[bot]"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 0, "created_at": "2023-03-28T13:58:14Z", "updated_at": "2023-03-29T06:08:02Z", "closed_at": "2023-03-29T06:08:01Z", "author_association": "CONTRIBUTOR", "pull_request": "simonw/datasette/pulls/2046", "body": "Bumps [furo](https://github.com/pradyunsg/furo) from 2022.12.7 to 2023.3.27.\n
\nChangelog\n

Sourced from furo's changelog.

\n
\n

Changelog

\n\n

2023.03.27 -- Tasty Tangerine

\n
    \n
  • Regenerate with newer version of sphinx-theme-builder, to fix RECORD hashes.
  • \n
  • Add missing class to Font Awesome examples
  • \n
\n

2023.03.23 -- Sassy Saffron

\n
    \n
  • Update Python version classifiers.
  • \n
  • Increase the icon size in mobile header.
  • \n
  • Increase admonition title bg opacity.
  • \n
  • Change the default API background to transparent.
  • \n
  • Transition the API background change.
  • \n
  • Remove the "indent" of API entries which have a background.
  • \n
  • Break long inline code literals.
  • \n
\n

2022.12.07 -- Reverent Raspberry

\n
    \n
  • \u2728 Add support for Sphinx 6.
  • \n
  • \u2728 Improve footnote presentation with docutils 0.18+.
  • \n
  • Drop support for Sphinx 4.
  • \n
  • Improve documentation about what the edit button does.
  • \n
  • Improve handling of empty-flexboxes for better print experience on Chrome.
  • \n
  • Improve styling for inline signatures.
  • \n
  • Replace the meta generator tag with a comment.
  • \n
  • Tweak labels with icons to prevent users selecting icons as text on touch.
  • \n
\n

2022.09.29 -- Quaint Quartz

\n
    \n
  • Add ability to set arbitrary URLs for edit button.
  • \n
  • Add support for aligning text in MyST-parser generated tables.
  • \n
\n

2022.09.15 -- Pragmatic Pistachio

\n
    \n
  • Add a minimum version constraint on pygments.
  • \n
  • Add an explicit dependency on sass.
  • \n
  • Change right sidebar title from "Contents" to "On this page".
  • \n
  • Correctly position sidebars on small screens.
  • \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=furo&package-manager=pip&previous-version=2022.12.7&new-version=2023.3.27)](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--2046.org.readthedocs.build/en/2046/\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/2046/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": 1641117021, "node_id": "PR_kwDODtX3eM5M66op", "number": 6, "title": "Add permalink virtual field to items table", "user": {"value": 1231935, "label": "xavdid"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 1, "created_at": "2023-03-26T22:22:38Z", "updated_at": "2023-03-29T18:38:52Z", "closed_at": null, "author_association": "FIRST_TIME_CONTRIBUTOR", "pull_request": "dogsheep/hacker-news-to-sqlite/pulls/6", "body": "I added a virtual column (no storage overhead) to the output that easily links back to the source. It works nicely out of the box with datasette:\r\n\r\n![](https://cdn.zappy.app/faf43661d539ee0fee02c0421de22d65.png)\r\n\r\nI got bit a bit by https://github.com/simonw/sqlite-utils/issues/411, so I went with a manual `table_xinfo` and creating the table via execute. Happy to adjust if that issue moves, but this seems like it works.\r\n\r\nI also added my best-guess instructions for local development on this package. I'm shooting in the dark, so feel free to replace with how you work on it locally.", "repo": {"value": 248903544, "label": "hacker-news-to-sqlite"}, "type": "pull", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/dogsheep/hacker-news-to-sqlite/issues/6/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": 1641013220, "node_id": "I_kwDOBm6k_c5hz9_k", "number": 2045, "title": "First column on a view page has no facet option in cog menu", "user": {"value": 9599, "label": "simonw"}, "state": "open", "locked": 0, "assignee": null, "milestone": {"value": 3268330, "label": "Datasette 1.0"}, "comments": 0, "created_at": "2023-03-26T18:02:47Z", "updated_at": "2023-03-26T18:02:48Z", "closed_at": null, "author_association": "OWNER", "pull_request": null, "body": "e.g. first column on this page - cog menu has no option to facet.\r\n\r\nhttps://datasette.io/content/tools\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/2045/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": null} {"id": 1639873822, "node_id": "PR_kwDOBm6k_c5M29tt", "number": 2044, "title": "Expand labels in row view as well (patch for 0.64.x branch)", "user": {"value": 82332573, "label": "tmcl-it"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 0, "created_at": "2023-03-24T18:44:44Z", "updated_at": "2023-03-24T18:44:57Z", "closed_at": null, "author_association": "FIRST_TIME_CONTRIBUTOR", "pull_request": "simonw/datasette/pulls/2044", "body": "This is a version of #2031 for the 0.64.x branch.\r\n\r\n\r\n----\n:books: Documentation preview :books:: https://datasette--2044.org.readthedocs.build/en/2044/\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/2044/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": 1639446870, "node_id": "PR_kwDOBm6k_c5M1izI", "number": 2043, "title": "Bump furo from 2022.12.7 to 2023.3.23", "user": {"value": 49699333, "label": "dependabot[bot]"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 2, "created_at": "2023-03-24T13:58:08Z", "updated_at": "2023-03-28T13:58:24Z", "closed_at": "2023-03-28T13:58:21Z", "author_association": "CONTRIBUTOR", "pull_request": "simonw/datasette/pulls/2043", "body": "Bumps [furo](https://github.com/pradyunsg/furo) from 2022.12.7 to 2023.3.23.\n
\nChangelog\n

Sourced from furo's changelog.

\n
\n

Changelog

\n\n

2023.03.23 -- Sassy Saffron

\n
    \n
  • Regenerate with newer version of sphinx-theme-builder, to fix RECORD hashes.
  • \n
  • Update Python version classifiers.
  • \n
  • Increase the icon size in mobile header.
  • \n
  • Increase admonition title bg opacity.
  • \n
  • Change the default API background to transparent.
  • \n
  • Transition the API background change.
  • \n
  • Remove the "indent" of API entries which have a background.
  • \n
  • Break long inline code literals.
  • \n
\n

2022.12.07 -- Reverent Raspberry

\n
    \n
  • \u2728 Add support for Sphinx 6.
  • \n
  • \u2728 Improve footnote presentation with docutils 0.18+.
  • \n
  • Drop support for Sphinx 4.
  • \n
  • Improve documentation about what the edit button does.
  • \n
  • Improve handling of empty-flexboxes for better print experience on Chrome.
  • \n
  • Improve styling for inline signatures.
  • \n
  • Replace the meta generator tag with a comment.
  • \n
  • Tweak labels with icons to prevent users selecting icons as text on touch.
  • \n
\n

2022.09.29 -- Quaint Quartz

\n
    \n
  • Add ability to set arbitrary URLs for edit button.
  • \n
  • Add support for aligning text in MyST-parser generated tables.
  • \n
\n

2022.09.15 -- Pragmatic Pistachio

\n
    \n
  • Add a minimum version constraint on pygments.
  • \n
  • Add an explicit dependency on sass.
  • \n
  • Change right sidebar title from "Contents" to "On this page".
  • \n
  • Correctly position sidebars on small screens.
  • \n
  • Correctly select only Furo's own svg in related pages nav.
  • \n
  • Make numpy-style documentation headers consistent.
  • \n
  • Retitle the reference section.
  • \n
  • Update npm dependencies.
  • \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=furo&package-manager=pip&previous-version=2022.12.7&new-version=2023.3.23)](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--2043.org.readthedocs.build/en/2043/\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/2043/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": 1636616315, "node_id": "I_kwDOBm6k_c5hjMh7", "number": 2042, "title": "Gather feedback on new ?_extra= design", "user": {"value": 9599, "label": "simonw"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 0, "created_at": "2023-03-22T23:07:43Z", "updated_at": "2023-03-22T23:08:19Z", "closed_at": null, "author_association": "OWNER", "pull_request": null, "body": "Now that I've landed:\r\n- #1999\r\n\r\nSee also:\r\n- #262\r\n\r\nI want to get some feedback from people on the design of the new `?_extra=` feature, before freezing it into Datasette 1.0.\r\n\r\nThe big change is that the default JSON representation is now MUCH slimmer - it only gives you keys for `\"next\"` and `\"rows\"`, where rows is a list of JSON objects (not a list of arrays as was previously the default) - for example https://latest.datasette.io/fixtures/sortable.json\r\n\r\nIf you want extra stuff you can ask for it with the new `?_extra=` parameter - e.g. https://latest.datasette.io/fixtures/sortable.json?_extra=columns&_extra=suggested_facets\r\n\r\nYou can use `?_extra=extras` to see a list of available extras: https://latest.datasette.io/fixtures/sortable.json?_extra=extras\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/2042/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": null} {"id": 1633077183, "node_id": "I_kwDOBm6k_c5hVse_", "number": 2041, "title": "Remove obsolete table POST code", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": {"value": 8755003, "label": "Datasette 1.0a3"}, "comments": 2, "created_at": "2023-03-21T01:01:40Z", "updated_at": "2023-03-21T01:17:44Z", "closed_at": "2023-03-21T01:17:43Z", "author_association": "OWNER", "pull_request": null, "body": "Spotted this in:\r\n- #1999\r\n\r\n`POST /db/table` currently executes obsolete code for inserting a row - I replaced that with `/db/table/-/insert` in \r\nhttps://github.com/simonw/datasette/commit/6e788b49edf4f842c0817f006eb9d865778eea5e but forgot to remove the old code.", "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/2041/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": 1622640374, "node_id": "I_kwDOCGYnMM5gt4b2", "number": 534, "title": " ResourceWarning: unclosed file", "user": {"value": 1244826, "label": "djhenderson"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 1, "created_at": "2023-03-14T03:02:18Z", "updated_at": "2023-05-08T19:56:29Z", "closed_at": "2023-05-08T19:56:29Z", "author_association": "NONE", "pull_request": null, "body": "Issuing either\r\n\r\n```\r\npy -Wdefault -m sqlite_utils insert dogs.db dogs dogs0.csv --csv\r\n [#############-----------------------] 36%\r\n [####################################] 100%C:\\Users\\Doug\\AppData\\Local\\Programs\\Python\\Python311\\Lib\\site-packages\\sqlite_utils\\cli.py:1187: ResourceWarning: unclosed file <_io.TextIOWrapper name='dogs0.csv' encoding='utf-8-sig'>\r\n insert_upsert_implementation(\r\nResourceWarning: Enable tracemalloc to get the object allocation traceback\r\n```\r\nor\r\n```\r\nset pythonwarnings=default\r\nsqlite-utils insert dogs.db dogs dogs0.csv --csv\r\n [#############-----------------------] 36%\r\n [####################################] 100%C:\\Users\\Doug\\AppData\\Local\\Programs\\Python\\Python311\\Lib\\site-packages\\sqlite_utils\\cli.py:1187: ResourceWarning: unclosed file <_io.TextIOWrapper name='dogs0.csv' encoding='utf-8-sig'>\r\n insert_upsert_implementation(\r\nResourceWarning: Enable tracemalloc to get the object allocation traceback\r\n```\r\n\r\nexhibits a ResourceWarning indicating that the CSV file being loaded is not closed.\r\n\r\nsqlite-utils --version\r\nsqlite-utils, version 3.30\r\npy --version\r\nPython 3.11.2\r\nWindows Version 10.0.19045 Build 19045\r\nSQLite version 3.41.0 2023-02-21 18:09:37\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/534/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": 1620516340, "node_id": "I_kwDOCGYnMM5glx30", "number": 533, "title": "ReadTheDocs error: not all arguments converted during string formatting", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": null, "comments": 2, "created_at": "2023-03-12T21:21:05Z", "updated_at": "2023-03-12T21:25:33Z", "closed_at": "2023-03-12T21:25:33Z", "author_association": "OWNER", "pull_request": null, "body": "This came up as a failure running tests for:\r\n- #531\r\n\r\nTraceback on https://readthedocs.org/projects/sqlite-utils/builds/19749348/\r\n\r\n```\r\n File \"/home/docs/checkouts/readthedocs.org/user_builds/sqlite-utils/envs/531/lib/python3.8/site-packages/docutils/parsers/rst/states.py\", line 889, in interpreted\r\n nodes, messages2 = role_fn(role, rawsource, text, lineno, self)\r\n File \"/home/docs/checkouts/readthedocs.org/user_builds/sqlite-utils/envs/531/lib/python3.8/site-packages/sphinx/ext/extlinks.py\", line 103, in role\r\n title = caption % part\r\nTypeError: not all arguments converted during string formatting\r\n\r\nException occurred:\r\n File \"/home/docs/checkouts/readthedocs.org/user_builds/sqlite-utils/envs/531/lib/python3.8/site-packages/sphinx/ext/extlinks.py\", line 103, in role\r\n title = caption % part\r\nTypeError: not all arguments converted during string formatting\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/533/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"}
a/b.c-dcabca/b.c-dc