{"id": 1052247023, "node_id": "I_kwDOBm6k_c4-uAPv", "number": 1505, "title": "Datasette should have an option to output CSV with semicolons", "user": {"value": 9599, "label": "simonw"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 1, "created_at": "2021-11-12T18:02:21Z", "updated_at": "2021-11-16T11:40:52Z", "closed_at": null, "author_association": "OWNER", "pull_request": null, "body": null, "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/1505/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": 344654623, "node_id": "MDU6SXNzdWUzNDQ2NTQ2MjM=", "number": 347, "title": "Rename \"datasette package\" to \"datasette publish docker\"", "user": {"value": 9599, "label": "simonw"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 0, "created_at": "2018-07-26T00:42:46Z", "updated_at": "2018-07-26T00:42:46Z", "closed_at": null, "author_association": "OWNER", "pull_request": null, "body": "", "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/347/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": 465003070, "node_id": "MDU6SXNzdWU0NjUwMDMwNzA=", "number": 551, "title": "Ship many-to-many faceting support (and facet-by-delimiter)", "user": {"value": 9599, "label": "simonw"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 2, "created_at": "2019-07-07T23:11:45Z", "updated_at": "2019-07-08T15:45:23Z", "closed_at": null, "author_association": "OWNER", "pull_request": null, "body": "", "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/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": null}
{"id": 574021194, "node_id": "MDU6SXNzdWU1NzQwMjExOTQ=", "number": 691, "title": "--reload sould reload server if code in --plugins-dir changes", "user": {"value": 9599, "label": "simonw"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 1, "created_at": "2020-03-02T14:42:21Z", "updated_at": "2020-06-14T02:35:17Z", "closed_at": null, "author_association": "OWNER", "pull_request": null, "body": "", "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/691/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": 718395987, "node_id": "MDExOlB1bGxSZXF1ZXN0NTAwNzk4MDkx", "number": 1008, "title": "Add json_loads and json_dumps jinja2 filters", "user": {"value": 649467, "label": "mhalle"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 1, "created_at": "2020-10-09T20:11:34Z", "updated_at": "2020-12-15T02:30:28Z", "closed_at": null, "author_association": "FIRST_TIME_CONTRIBUTOR", "pull_request": "simonw/datasette/pulls/1008", "body": "", "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/1008/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": 871304967, "node_id": "MDU6SXNzdWU4NzEzMDQ5Njc=", "number": 1315, "title": "settings.json should be picked up by \"datasette publish cloudrun\"", "user": {"value": 9599, "label": "simonw"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 0, "created_at": "2021-04-29T18:16:41Z", "updated_at": "2021-04-29T18:16:41Z", "closed_at": null, "author_association": "OWNER", "pull_request": null, "body": "", "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/1315/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": 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": 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-08-10T13:15:41Z", "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": 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\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\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": 718540751, "node_id": "MDU6SXNzdWU3MTg1NDA3NTE=", "number": 1012, "title": "For 1.0 update trove classifier in setup.py", "user": {"value": 9599, "label": "simonw"}, "state": "open", "locked": 0, "assignee": null, "milestone": {"value": 3268330, "label": "Datasette 1.0"}, "comments": 5, "created_at": "2020-10-10T05:52:08Z", "updated_at": "2021-11-16T13:18:36Z", "closed_at": null, "author_association": "OWNER", "pull_request": null, "body": " Development Status :: 5 - Production/Stable", "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/1012/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": 913900374, "node_id": "MDU6SXNzdWU5MTM5MDAzNzQ=", "number": 1369, "title": "Don't show foreign key IDs twice if no label", "user": {"value": 9599, "label": "simonw"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 1, "created_at": "2021-06-07T19:47:02Z", "updated_at": "2021-06-07T19:47:24Z", "closed_at": null, "author_association": "OWNER", "pull_request": null, "body": "![B5B54D94-A768-4544-A88D-CDCAB417CD3C](https://user-images.githubusercontent.com/9599/121078979-6e9d0600-c78e-11eb-8b70-20e6d29b48b1.jpeg)\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/1369/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": 1564769997, "node_id": "I_kwDOBm6k_c5dRH7N", "number": 2011, "title": "Applied facet did not result in an \"x\" icon to dismiss it", "user": {"value": 9599, "label": "simonw"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 1, "created_at": "2023-01-31T17:57:44Z", "updated_at": "2023-01-31T17:58:54Z", "closed_at": null, "author_association": "OWNER", "pull_request": null, "body": "![CleanShot 2023-01-31 at 09 55 56@2x](https://user-images.githubusercontent.com/9599/215843684-1761a230-d490-4f87-be6d-186319366794.png)\r\n\r\nThat's against this data https://data.sfgov.org/City-Management-and-Ethics/Supplier-Contracts/cqi5-hm2d imported using https://datasette.io/plugins/datasette-socrata\r\n\r\nIt's for `Contract Type` of `Non-Purchasing Contract (Rents, etc.)` - so possible that some of the spaces or punctuation in either the name of the value tripped up the code that decides if the X icon should be displayed.", "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/2011/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": 1198822563, "node_id": "I_kwDOBm6k_c5HdJSj", "number": 1706, "title": "[feature] immutable mode for a directory, not just individual sqlite file", "user": {"value": 9020979, "label": "hydrosquall"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 4, "created_at": "2022-04-10T00:50:57Z", "updated_at": "2022-12-09T19:11:40Z", "closed_at": null, "author_association": "CONTRIBUTOR", "pull_request": null, "body": "## Motivation\r\n\r\n- I have a directory of sqlite databases\r\n- I'd like to use immutable mode when opening them for better performance [docs](https://docs.datasette.io/en/0.54/performance.html#immutable-mode)\r\n- Currently using this flag throws the following error\r\n\r\n IsADirectoryError: [Errno 21] Is a directory: '/name-of-directory'\r\n\r\n## Proposal\r\n\r\nImmutable flag works for both single files and directories\r\n\r\n datasette -i /folder-of-sqlite-files", "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/1706/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": 1182227211, "node_id": "I_kwDOBm6k_c5Gd1sL", "number": 1692, "title": "[plugins][feature request]: Support additional script tag attributes when loading custom JS", "user": {"value": 9020979, "label": "hydrosquall"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 2, "created_at": "2022-03-27T01:16:03Z", "updated_at": "2022-03-30T06:14:51Z", "closed_at": null, "author_association": "CONTRIBUTOR", "pull_request": null, "body": "## Motivation\r\n\r\n- The build system for my new [plugin](https://github.com/hydrosquall/datasette-nteract-data-explorer) has two output JS files, one for browsers that support ES modules, one for browsers that don't. At present, I'm only passing one of them into Datasette.\r\n- I'd like to specify the non-es-module script as a fallback for older browsers. I don't want to load it by default, because browsers will only need one, and it's heavy, so for now I'm only supporting modern browsers. \r\n\r\nTo be able to support legacy browsers without slowing down users with modern browsers, I would like to be able to set additional HTML attributes on the tag fallback script, `nomodule` and `defer`. My injected scripts should look something like this:\r\n\r\n```html\r\n\r\n\r\n```\r\n\r\n## Proposal\r\n\r\nTo achieve this, I propose additional optional properties to the API accepted by the `extra_js_urls` hook and custom JS field the `metadata.json` [described here](https://docs.datasette.io/en/stable/custom_templates.html#custom-css-and-javascript). \r\n\r\nUnder this API, I'd write something like this to get the above HTML rendered in Datasette.\r\n\r\n```json\r\n{\r\n \"extra_js_urls\": [\r\n {\r\n \"url\": \"/index.my-es-module-bundle.js\",\r\n \"module\": true,\r\n },\r\n {\r\n \"url\": \"/index.my-legacy-fallback-bundle.js\",\r\n \"nomodule\": \"\",\r\n \"defer\": true\r\n }\r\n ]\r\n}\r\n```\r\n\r\n## Resources\r\n\r\n- [MDN on the script tag](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script)\r\n - There may be other properties that could be added that are potentially valuable, like `async` or `referrerpolicy`, but I don't have an immediate need for those.", "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/1692/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": 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\r\n\r\nI think it is a potential bug.\r\n\r\n## Reproduce\r\n\r\nmetadata.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\ncommands
\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 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
This data as\r\n> json,\r\n> CSV\r\n>
\r\n> ```\r\nThose CSV and JSON links are incorrect.\r\n\r\n_Originally posted by @simonw in https://github.com/simonw/datasette-publish-vercel/issues/48#issuecomment-900497579_", "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/1438/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": 1433576351, "node_id": "I_kwDOBm6k_c5VcqOf", "number": 1880, "title": "Datasette with many and large databases > Memory use", "user": {"value": 525934, "label": "amitkoth"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 4, "created_at": "2022-11-02T18:10:27Z", "updated_at": "2022-11-16T17:50:29Z", "closed_at": null, "author_association": "NONE", "pull_request": null, "body": "> Datasette maintains an in-memory SQLite database with details of the the databases, tables and columns for all of the attached databases.\r\n\r\nThe above is from the docs ^. There's two problems here - the number of datasette \"instances\" in a single server/VM and the size of the database itself. We want the **opposite** of in-memory, including what happens on SQLlite - documented in https://www.sqlite.org/inmemorydb.html\r\n\r\nFrom the context in https://github.com/simonw/datasette/issues/1150 - does it mean datasette is memory-bound to the size of the dataset - which might be a deal-breaker for many large-scale use cases?\r\n\r\nIn an extreme case - let's say a single server had 100 SQLlite databases, which would enable 100 \"instances\" of datasette to run, one per client (e.g. in a SaaS multi-tenant environment). How could we achieve all these goals:\r\n\r\n1. Allow any _one_ of these 100 databases to grow to say 2Tb in size \r\n2. Have one datasette instance, which connects to 1 of the 100 instances, based on incoming credentials/tenant ID\r\n3. Minimize memory use entirely - both by datasette and SQLlite, such that almost all operations are executed in real-time on-disk with little to no memory consumption per-tenant, or per-database.\r\n\r\nAny ideas appreciated - we're looking to use this in a SaaS type of setting - many instances, single server.\r\n\r\n@simonw great work on datasette, in general! Possibly related to https://github.com/simonw/datasette/issues/1480 but we don't want use any kind of serverless infra - this is a long-running VM/server.", "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/1880/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": 1082584499, "node_id": "I_kwDOBm6k_c5Ahu2z", "number": 1558, "title": "Redesign `facet_results` JSON structure prior to Datasette 1.0", "user": {"value": 9599, "label": "simonw"}, "state": "open", "locked": 0, "assignee": null, "milestone": {"value": 3268330, "label": "Datasette 1.0"}, "comments": 3, "created_at": "2021-12-16T19:45:10Z", "updated_at": "2023-01-09T15:31:17Z", "closed_at": null, "author_association": "OWNER", "pull_request": null, "body": "> Decision: as an initial fix I'm going to de-duplicate those keys by using `tags__array` etc - with a `_2` on the end if that key is already used.\r\n>\r\n> I'll open a separate issue to redesign this better for Datasette 1.0.\r\n\r\n_Originally posted by @simonw in https://github.com/simonw/datasette/issues/625#issuecomment-996130862_", "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/1558/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": 687694947, "node_id": "MDU6SXNzdWU2ODc2OTQ5NDc=", "number": 954, "title": "Remove old register_output_renderer dict mechanism in Datasette 1.0", "user": {"value": 9599, "label": "simonw"}, "state": "open", "locked": 0, "assignee": null, "milestone": {"value": 3268330, "label": "Datasette 1.0"}, "comments": 1, "created_at": "2020-08-28T04:04:23Z", "updated_at": "2020-08-28T04:56:31Z", "closed_at": null, "author_association": "OWNER", "pull_request": null, "body": "> Documentation says that the old dictionary mechanism will be deprecated by 1.0:\r\n> \r\n> https://github.com/simonw/datasette/blob/799ecae94824640bdff21f86997f69844048d5c3/docs/plugin_hooks.rst#L460\r\n_Originally posted by @simonw in https://github.com/simonw/datasette/issues/953#issuecomment-682312494_", "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/954/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": 1454532488, "node_id": "I_kwDOBm6k_c5WsmeI", "number": 1902, "title": "Document {% block crumbs %} for plugin authors", "user": {"value": 9599, "label": "simonw"}, "state": "open", "locked": 0, "assignee": null, "milestone": {"value": 3268330, "label": "Datasette 1.0"}, "comments": 0, "created_at": "2022-11-18T06:16:30Z", "updated_at": "2022-11-18T06:16:39Z", "closed_at": null, "author_association": "OWNER", "pull_request": null, "body": "> For `datasette-copyable` I want to show breadcrumbs that take database/instance permissions into account, so I'm removing `{% block nav %}` entirely and replacing it with this:\r\n>\r\n> ```html+jinja\r\n> {% block crumbs %}\r\n> {{ crumbs.nav(request=request, database=database, table=table) }}\r\n> {% endblock %}\r\n> ```\r\n\r\n_Originally posted by @simonw in https://github.com/simonw/datasette/issues/1901#issuecomment-1319588163_\r\n\r\nI should document 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/1902/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": 990367646, "node_id": "MDU6SXNzdWU5OTAzNjc2NDY=", "number": 1462, "title": "Separate out \"debug\" options from \"root\" options", "user": {"value": 9599, "label": "simonw"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 1, "created_at": "2021-09-07T21:27:34Z", "updated_at": "2021-09-07T21:34:33Z", "closed_at": null, "author_association": "OWNER", "pull_request": null, "body": "> I ditched \"root\" for \"admin\" because root by default gives you a whole bunch of stuff which I think could be confusing:\r\n> \r\n> \r\n>\r\n> Maybe the real problem here is that I'm conflating \"root\" permissions with \"debug\" options. Perhaps there should be an extra Datasette mode that unlocks debug tools for the root user?\r\n\r\n_Originally posted by @simonw in https://github.com/simonw/datasette-app-support/issues/8#issuecomment-914638998_", "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/1462/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": 1468495358, "node_id": "I_kwDOBm6k_c5Xh3X-", "number": 1910, "title": "Check incoming column types on various write APIs", "user": {"value": 9599, "label": "simonw"}, "state": "open", "locked": 0, "assignee": null, "milestone": {"value": 8755003, "label": "Datasette 1.0a-next"}, "comments": 0, "created_at": "2022-11-29T18:09:10Z", "updated_at": "2022-12-13T05:29:09Z", "closed_at": null, "author_association": "OWNER", "pull_request": null, "body": "> I do think this needs type checking - I just tried and you really can send a string to an integer column and have it work, which feels bad.\r\n\r\n_Originally posted by @simonw in https://github.com/simonw/datasette/issues/1863#issuecomment-1331089156_\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/1910/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": 1529707837, "node_id": "I_kwDOBm6k_c5bLX09", "number": 1988, "title": "Reconsider pattern where plugins could break existing template context", "user": {"value": 9599, "label": "simonw"}, "state": "open", "locked": 0, "assignee": null, "milestone": {"value": 3268330, "label": "Datasette 1.0"}, "comments": 4, "created_at": "2023-01-11T21:13:43Z", "updated_at": "2023-01-11T21:25:05Z", "closed_at": null, "author_association": "OWNER", "pull_request": null, "body": "> I hadn't run into an issue with plugins like `datasette-template-sql` interfering with the existing context for other features before! Definitely not a good thing.\r\n\r\n_Originally posted by @simonw in https://github.com/simonw/datasette-write/issues/6#issuecomment-1379490596_\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/1988/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": 1378636455, "node_id": "I_kwDOBm6k_c5SLFKn", "number": 1815, "title": "`datasette publish provider .` to publish whole directory, similar to configuration directory mode", "user": {"value": 9599, "label": "simonw"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 0, "created_at": "2022-09-19T23:28:59Z", "updated_at": "2022-09-19T23:29:11Z", "closed_at": null, "author_association": "OWNER", "pull_request": null, "body": "> I haven't done this with any of my other `datasette publish` tools, but I do think it's a good idea. Being able to publish the entire directory - with templates and plugins and metadata - does seem very useful to me.\r\n\r\n_Originally posted by @simonw in https://github.com/simonw/datasette-publish-fly/issues/23#issuecomment-1251673489_", "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/1815/reactions\", \"total_count\": 2, \"+1\": 2, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": null} {"id": 1174697144, "node_id": "I_kwDOBm6k_c5GBHS4", "number": 1672, "title": "Refactor CSV handling code out of DataView", "user": {"value": 9599, "label": "simonw"}, "state": "open", "locked": 0, "assignee": null, "milestone": {"value": 3268330, "label": "Datasette 1.0"}, "comments": 1, "created_at": "2022-03-20T21:47:00Z", "updated_at": "2022-03-20T21:52:39Z", "closed_at": null, "author_association": "OWNER", "pull_request": null, "body": "> I think the way to get rid of most of the remaining complexity in `DataView` is to refactor how CSV stuff works - pulling it in line with other export factors and extracting the streaming mechanism. Opening a fresh issue for that.\r\n\r\n_Originally posted by @simonw in https://github.com/simonw/datasette/issues/1660#issuecomment-1073355032_", "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/1672/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": 749283032, "node_id": "MDU6SXNzdWU3NDkyODMwMzI=", "number": 1101, "title": "register_output_renderer() should support streaming data", "user": {"value": 9599, "label": "simonw"}, "state": "open", "locked": 0, "assignee": null, "milestone": {"value": 3268330, "label": "Datasette 1.0"}, "comments": 13, "created_at": "2020-11-24T02:17:09Z", "updated_at": "2023-01-21T22:07:19Z", "closed_at": null, "author_association": "OWNER", "pull_request": null, "body": "> I'd like to implement this by first extending the `register_output_renderer()` hook to support streaming huge responses, then switching CSV to use the plugin hook in addition to TSV using it.\r\n\r\n_Originally posted by @simonw in https://github.com/simonw/datasette/issues/1096#issuecomment-732542285_", "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/1101/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": 776635426, "node_id": "MDU6SXNzdWU3NzY2MzU0MjY=", "number": 1165, "title": "Mechanism for executing JavaScript unit tests", "user": {"value": 9599, "label": "simonw"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 9, "created_at": "2020-12-30T21:02:34Z", "updated_at": "2022-01-13T22:21:29Z", "closed_at": null, "author_association": "OWNER", "pull_request": null, "body": "> I'm going to need to add JavaScript unit tests for this new plugin system.\r\n\r\n_Originally posted by @simonw in https://github.com/simonw/datasette/issues/983#issuecomment-752757289_", "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/1165/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": 1865649347, "node_id": "I_kwDOBm6k_c5vM4zD", "number": 2156, "title": "datasette -s/--setting option for setting nested configuration options", "user": {"value": 9599, "label": "simonw"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 4, "created_at": "2023-08-24T18:09:27Z", "updated_at": "2023-08-28T19:33:05Z", "closed_at": null, "author_association": "OWNER", "pull_request": null, "body": "> I've been thinking about what it might look like to allow command-line arguments to be used to define _any_ of the configuration options in `datasette.yml`, as alternative and more convenient syntax.\r\n>\r\n> Here's what I've come up with:\r\n> ```\r\n> datasette \\\r\n> -s settings.sql_time_limit_ms 1000 \\\r\n> -s plugins.datasette-auth-tokens.manage_tokens true \\\r\n> -s plugins.datasette-auth-tokens.manage_tokens_database tokens \\\r\n> mydatabase.db tokens.db\r\n> ```\r\n> Which would be equivalent to `datasette.yml` containing this:\r\n> ```yaml\r\n> plugins:\r\n> datasette-auth-tokens:\r\n> manage_tokens: true\r\n> manage_tokens_database: tokens\r\n> settings:\r\n> sql_time_limit_ms: 1000\r\n> ```\r\nMore details in https://github.com/simonw/datasette/issues/2143#issuecomment-1690792514\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/2156/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": 1490576818, "node_id": "I_kwDOBm6k_c5Y2GWy", "number": 1943, "title": "`/-/permissions` should list available permissions", "user": {"value": 9599, "label": "simonw"}, "state": "open", "locked": 0, "assignee": null, "milestone": {"value": 8755003, "label": "Datasette 1.0a-next"}, "comments": 1, "created_at": "2022-12-11T23:38:03Z", "updated_at": "2022-12-15T00:41:37Z", "closed_at": null, "author_association": "OWNER", "pull_request": null, "body": "> Idea: a `/-/permissions` introspection endpoint for listing registered permissions\r\n\r\n_Originally posted by @simonw in https://github.com/simonw/datasette/issues/1939#issuecomment-1345691103_\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/1943/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": 957315684, "node_id": "MDU6SXNzdWU5NTczMTU2ODQ=", "number": 1410, "title": "Rename settings to `default_allow_facet` and `default_allow_download` and `default_allow_csv_stream`", "user": {"value": 9599, "label": "simonw"}, "state": "open", "locked": 0, "assignee": null, "milestone": {"value": 3268330, "label": "Datasette 1.0"}, "comments": 0, "created_at": "2021-07-31T20:27:12Z", "updated_at": "2021-07-31T20:27:49Z", "closed_at": null, "author_association": "OWNER", "pull_request": null, "body": "> If I was prone to over-thinking (which I am) I'd note that `allow_facet` and `allow_download` and `allow_csv_stream` are all settings that do NOT have an equivalent in the newer permissions system, which is itself a little weird and inconsistent.\r\n>\r\n> So maybe there's a future task where I introduce those as both permissions and metadata `\"allow_x\"` blocks, then rename the settings themselves to be called `default_allow_facet` and `default_allow_download` and `default_allow_csv_stream`.\r\n>\r\n> If I was going to do that I should get it in before Datasette 1.0.\r\n\r\n_Originally posted by @simonw in https://github.com/simonw/datasette/issues/1409#issuecomment-890400425_", "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/1410/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": 776634318, "node_id": "MDU6SXNzdWU3NzY2MzQzMTg=", "number": 1164, "title": "Mechanism for minifying JavaScript that ships with Datasette", "user": {"value": 9599, "label": "simonw"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 9, "created_at": "2020-12-30T20:59:06Z", "updated_at": "2022-01-13T22:21:29Z", "closed_at": null, "author_association": "OWNER", "pull_request": null, "body": "> If I'm going to minify it I'll need to figure out a build step in Datasette itself so that I can easily work on that minified version.\r\n\r\n_Originally posted by @simonw in https://github.com/simonw/datasette/issues/983#issuecomment-752748496_", "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/1164/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": 903902495, "node_id": "MDU6SXNzdWU5MDM5MDI0OTU=", "number": 1342, "title": "Improve `path_with_replaced_args()` and friends and document them", "user": {"value": 9599, "label": "simonw"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 3, "created_at": "2021-05-27T15:18:28Z", "updated_at": "2021-05-27T15:23:02Z", "closed_at": null, "author_association": "OWNER", "pull_request": null, "body": "> In order to cleanly implement this I need to expose the `path_with_replaced_args` utility function to Datasette's template engine. This is the first time this will become an exposed (and hence should-by-documented) API and I don't like its shape much.\r\n\r\n_Originally posted by @simonw in https://github.com/simonw/datasette/issues/1337#issuecomment-849721280_", "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/1342/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": 1251739062, "node_id": "I_kwDOBm6k_c5KnAW2", "number": 1752, "title": "Research if I can drop Janus", "user": {"value": 9599, "label": "simonw"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 0, "created_at": "2022-05-28T22:46:52Z", "updated_at": "2022-05-28T22:46:52Z", "closed_at": null, "author_association": "OWNER", "pull_request": null, "body": "> It seems to me Janus dependency is not necessary, `async with app.database_write_mutex(): out = await app.transaction(func)` may be enough.\r\n\r\nComment here: https://lobste.rs/s/fki4tj/architecture_notes_datasette#c_a2ihon", "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/1752/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": 1495716243, "node_id": "I_kwDOBm6k_c5ZJtGT", "number": 1952, "title": "Improvements to /-/create-token restrictions interface", "user": {"value": 9599, "label": "simonw"}, "state": "open", "locked": 0, "assignee": null, "milestone": {"value": 8755003, "label": "Datasette 1.0a-next"}, "comments": 1, "created_at": "2022-12-14T05:22:39Z", "updated_at": "2022-12-14T05:23:13Z", "closed_at": null, "author_association": "OWNER", "pull_request": null, "body": "> It would be neat not to show write permissions against immutable databases too - and not hard from a performance perspective since it doesn't involve hundreds more permission checks.\r\n>\r\n> That will need permissions to grow a flag for if they need a mutable database though, which is a bigger job.\r\n\r\n_Originally posted by @simonw in https://github.com/simonw/datasette/issues/1947#issuecomment-1350414402_\r\n\r\nAlso, DO show the `_memory` database there if Datasette was started in `--crossdb` mode.", "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/1952/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": 712260429, "node_id": "MDU6SXNzdWU3MTIyNjA0Mjk=", "number": 983, "title": "JavaScript plugin hooks mechanism similar to pluggy", "user": {"value": 9599, "label": "simonw"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 47, "created_at": "2020-09-30T20:32:43Z", "updated_at": "2021-01-25T04:43:58Z", "closed_at": null, "author_association": "OWNER", "pull_request": null, "body": "> It would be neat to provide a JavaScript plugin hook that plugins can use to add their own options to this menu. No idea what that would look like though.\r\n\r\n_Originally posted by @simonw in https://github.com/simonw/datasette/issues/981#issuecomment-701616922_", "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/983/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": 670209331, "node_id": "MDU6SXNzdWU2NzAyMDkzMzE=", "number": 913, "title": "Mechanism for passing additional options to `datasette my.db` that affect plugins", "user": {"value": 9599, "label": "simonw"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 5, "created_at": "2020-07-31T20:38:26Z", "updated_at": "2021-01-04T20:04:11Z", "closed_at": null, "author_association": "OWNER", "pull_request": null, "body": "> It's a shame there's no obvious mechanism for passing additional options to `datasette my.db` that affect how plugins work.\r\n>\r\n>The only way I can think of at the moment is via environment variables:\r\n>\r\n> DATASETTE_INSERT_UNSAFE=1 datasette my.db\r\n>\r\n>This will have to do for the moment - it's ugly enough that people will at least know they are doing something unsafe, which is the goal here.\r\n_Originally posted by @simonw in https://github.com/simonw/datasette-insert/issues/15#issuecomment-667346438_", "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/913/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": 837350092, "node_id": "MDU6SXNzdWU4MzczNTAwOTI=", "number": 1270, "title": "Try implementing SQLite timeouts using .interrupt() instead of using .set_progress_handler()", "user": {"value": 9599, "label": "simonw"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 3, "created_at": "2021-03-22T06:00:17Z", "updated_at": "2021-03-23T16:45:39Z", "closed_at": null, "author_association": "OWNER", "pull_request": null, "body": "> Maybe I could implement SQLite query timeouts using the `interrupt()` method instead of the progress handler hack I'm currently using?\r\n>\r\n> https://stackoverflow.com/questions/43240496/python-sqlite3-how-to-quickly-and-cleanly-interrupt-long-running-query-with-e has some tips.\r\n\r\n_Originally posted by @simonw in https://github.com/simonw/datasette/issues/1268#issuecomment-803764919_", "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/1270/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": 1177101697, "node_id": "I_kwDOBm6k_c5GKSWB", "number": 1681, "title": "Potential bug in numeric handling where_clause for filters", "user": {"value": 9599, "label": "simonw"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 2, "created_at": "2022-03-22T17:43:50Z", "updated_at": "2022-03-22T17:49:09Z", "closed_at": null, "author_association": "OWNER", "pull_request": null, "body": "> Note that Datasette does already have special logic to convert parameters to integers for numeric comparisons like `>`:\r\n>\r\n> https://github.com/simonw/datasette/blob/c4c9dbd0386e46d2bf199f0ed34e4895c98cb78c/datasette/filters.py#L203-L212\r\n> \r\n> Though... it looks like there's a bug in that? It doesn't account for `float` values - `\"3.5\".isdigit()` return `False` - probably for the best, because `int(3.5)` would break that value anyway.\r\n\r\n_Originally posted by @simonw in https://github.com/simonw/datasette/issues/1671#issuecomment-1075432283_", "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/1681/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": 1122557010, "node_id": "I_kwDOBm6k_c5C6NxS", "number": 1627, "title": "Get the tests passing against Windows", "user": {"value": 9599, "label": "simonw"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 0, "created_at": "2022-02-03T01:23:06Z", "updated_at": "2022-02-03T01:23:32Z", "closed_at": null, "author_association": "OWNER", "pull_request": null, "body": "> OK, the tests do NOT pass against Windows! https://github.com/simonw/datasette/runs/5044105941\r\n>\r\n> \r\n\r\n_Originally posted by @simonw in https://github.com/simonw/datasette/issues/1626#issuecomment-1028515161_", "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/1627/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": 913809802, "node_id": "MDU6SXNzdWU5MTM4MDk4MDI=", "number": 1366, "title": "Get rid of this `restore_working_directory` hack entirely", "user": {"value": 9599, "label": "simonw"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 2, "created_at": "2021-06-07T18:01:21Z", "updated_at": "2021-06-07T18:03:03Z", "closed_at": null, "author_association": "OWNER", "pull_request": null, "body": "> That seems to have fixed it. I'd love to get rid of this `restore_working_directory` hack entirely.\r\n\r\n_Originally posted by @simonw in https://github.com/simonw/datasette/issues/1361#issuecomment-855308811_", "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/1366/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": 770598024, "node_id": "MDU6SXNzdWU3NzA1OTgwMjQ=", "number": 1152, "title": "Efficiently calculate list of databases/tables a user can view", "user": {"value": 9599, "label": "simonw"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 12, "created_at": "2020-12-18T06:13:01Z", "updated_at": "2021-12-27T23:04:31Z", "closed_at": null, "author_association": "OWNER", "pull_request": null, "body": "> The homepage currently performs a massive flurry of permission checks - one for each, database, table and view: https://github.com/simonw/datasette/blob/0.53/datasette/views/index.py#L21-L75\r\n> \r\n> A paginated version of this is a little daunting as the permission checks would have to be carried out in every single table just to calculate the count that will be paginated.\r\n\r\n_Originally posted by @simonw in https://github.com/simonw/datasette/issues/1150#issuecomment-747864831_", "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/1152/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": 811505638, "node_id": "MDU6SXNzdWU4MTE1MDU2Mzg=", "number": 1234, "title": "Runtime support for ATTACHing multiple databases", "user": {"value": 9599, "label": "simonw"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 1, "created_at": "2021-02-18T22:06:47Z", "updated_at": "2021-02-22T21:06:28Z", "closed_at": null, "author_association": "OWNER", "pull_request": null, "body": "> The implementation in #1232 is ready to land. It's the simplest-thing-that-could-possibly-work: you can run `datasette one.db two.db three.db --crossdb` and then use the `/_memory` page to run joins across tables from multiple databases.\r\n>\r\n> It only works on the first 10 databases that were passed to the command-line. This means that if you have a Datasette instance with hundreds of attached databases (see [Datasette Library](https://github.com/simonw/datasette/issues/417)) this won't be particularly useful for you.\r\n>\r\n> So... a better, future version of this feature would be one that lets you join across databases on command - maybe by hitting `/_memory?attach=db1&attach=db2` to get a special connection.\r\n\r\n_Originally posted by @simonw in https://github.com/simonw/datasette/issues/283#issuecomment-781665560_", "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/1234/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": 1426080014, "node_id": "I_kwDOBm6k_c5VAEEO", "number": 1867, "title": "/db/table/-/rename API (also allows atomic replace)", "user": {"value": 9599, "label": "simonw"}, "state": "open", "locked": 0, "assignee": null, "milestone": {"value": 8755003, "label": "Datasette 1.0a-next"}, "comments": 1, "created_at": "2022-10-27T18:13:23Z", "updated_at": "2023-01-09T15:34:12Z", "closed_at": null, "author_association": "OWNER", "pull_request": null, "body": "> There's one catch with batched inserts: if your CLI tool fails half way through you could end up with a partially populated table - since a bunch of batches will have succeeded first.\r\n>\r\n> ...\r\n>\r\n> If people care about that kind of thing they could always push all of their inserts to a table called `_tablename` and then atomically rename that once they've uploaded all of the data (assuming I provide an atomic-rename-this-table mechanism).\r\n\r\n_Originally posted by @simonw in https://github.com/simonw/datasette/issues/1866#issuecomment-1293893789_\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/1867/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": 1456013930, "node_id": "I_kwDOBm6k_c5WyQJq", "number": 1906, "title": "Extract publish Heroku support to a plugin", "user": {"value": 9599, "label": "simonw"}, "state": "open", "locked": 0, "assignee": null, "milestone": {"value": 3268330, "label": "Datasette 1.0"}, "comments": 0, "created_at": "2022-11-19T00:02:51Z", "updated_at": "2022-11-19T00:03:10Z", "closed_at": null, "author_association": "OWNER", "pull_request": null, "body": "> This is a strong argument for extracting the Heroku support out to a plugin - it would allow this to be fixed with a plugin release without needing to push a full release of Datasette itself.\r\n\r\n_Originally posted by @simonw in https://github.com/simonw/datasette/issues/1905#issuecomment-1320678715_\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/1906/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": 1895266807, "node_id": "I_kwDOBm6k_c5w93n3", "number": 2184, "title": "Design decision - should configuration be exposed at /-/config ?", "user": {"value": 9599, "label": "simonw"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 0, "created_at": "2023-09-13T21:07:08Z", "updated_at": "2023-09-13T21:07:38Z", "closed_at": null, "author_association": "OWNER", "pull_request": null, "body": "> This made me think. That `{\"$env\": \"ENV_VAR\"}` hack was introduced back here:\r\n>\r\n> - https://github.com/simonw/datasette/issues/538\r\n>\r\n> The problem it was solving was that metadata was visible to everyone with access to the instance at `/-/metadata` but plugins clearly needed a way to set secret settings.\r\n>\r\n> Now that this stuff is moving to config, we have some decisions to make:\r\n>\r\n> 1. Add `/-/config` to let people see the configuration of their instance, and keep the `$env` trick for secret settings.\r\n> 2. Say all configuration aside from metadata is secret and make `$env` optional or ditch it entirely.\r\n> 3. Allow plugins to announce which of their configuration options are secret so we can automatically redact them from `/-/config`\r\n>\r\n> I've found `/-/metadata` extraordinarily useful as a user of Datasette - it really helps me understand exactly what's going on if I run into any problems with a plugin, if I can quickly check what the settings look like.\r\n>\r\n> So I'm leaning towards option 1 or 3.\r\n\r\n_Originally posted by @simonw in https://github.com/simonw/datasette/pull/2183#discussion_r1325076924_\r\n\r\nAlso refs:\r\n- #2093", "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/2184/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": 957302085, "node_id": "MDU6SXNzdWU5NTczMDIwODU=", "number": 1408, "title": "Review places in codebase that use os.chdir(), in particularly relating to tests", "user": {"value": 9599, "label": "simonw"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 2, "created_at": "2021-07-31T18:57:06Z", "updated_at": "2021-07-31T19:00:32Z", "closed_at": null, "author_association": "OWNER", "pull_request": null, "body": "> To clarify: the core problem here is that an error is thrown any time you call `os.getcwd()` but the directory you are currently in has been deleted.\r\n>\r\n> `runner.isolated_filesystem()` assumes that the current directory in has not been deleted. But the various temporary directory utilities in `pytest` work by creating directories and then deleting them.\r\n>\r\n> Maybe there's a larger problem here that I play a bit fast and loose with `os.chdir()` in both the test suite and in various lines of code in Datasette itself (in particular in the publish commands)?\r\n\r\n_Originally posted by @simonw in https://github.com/simonw/datasette/issues/1406#issuecomment-890390198_", "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/1408/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": 1175690070, "node_id": "I_kwDOBm6k_c5GE5tW", "number": 1676, "title": "Reconsider ensure_permissions() logic, can it be less confusing?", "user": {"value": 9599, "label": "simonw"}, "state": "open", "locked": 0, "assignee": null, "milestone": {"value": 3268330, "label": "Datasette 1.0"}, "comments": 3, "created_at": "2022-03-21T17:14:57Z", "updated_at": "2022-12-02T01:23:40Z", "closed_at": null, "author_association": "OWNER", "pull_request": null, "body": "> Updated documentation: https://github.com/simonw/datasette/blob/e627510b760198ccedba9e5af47a771e847785c9/docs/internals.rst#await-ensure_permissionsactor-permissions\r\n>\r\n>> This method allows multiple permissions to be checked at onced. It raises a `datasette.Forbidden` exception if any of the checks are denied before one of them is explicitly granted.\r\n>> \r\n>> This is useful when you need to check multiple permissions at once. For example, an actor should be able to view a table if either one of the following checks returns `True` or not a single one of them returns `False`:\r\n>\r\n> That's pretty hard to understand! I'm going to open a separate issue to reconsider if this is a useful enough abstraction given how confusing it is.\r\n\r\n_Originally posted by @simonw in https://github.com/simonw/datasette/issues/1675#issuecomment-1074177827_", "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/1676/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": 400340905, "node_id": "MDU6SXNzdWU0MDAzNDA5MDU=", "number": 402, "title": "Use SQLITE_DBCONFIG_DEFENSIVE plus other recommendations from SQLite security docs", "user": {"value": 9599, "label": "simonw"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 3, "created_at": "2019-01-17T15:52:28Z", "updated_at": "2019-01-17T16:15:21Z", "closed_at": null, "author_association": "OWNER", "pull_request": null, "body": "> Was just having a skim through the datasette source. Given that the vuln impacts shadow tables, wasn't sure whether these are also covered by the immutable flag. Latest release introduced a SQLITE_DBCONFIG_DEFENSIVE flag that they recommend setting: https://sqlite.org/security.html\r\n\r\nhttps://twitter.com/ignoredambience/status/1085926961413869568", "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/402/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": 969855774, "node_id": "MDU6SXNzdWU5Njk4NTU3NzQ=", "number": 1432, "title": "Rename Datasette.__init__(config=) parameter to settings=", "user": {"value": 9599, "label": "simonw"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 8, "created_at": "2021-08-13T01:00:27Z", "updated_at": "2021-10-19T01:16:41Z", "closed_at": null, "author_association": "OWNER", "pull_request": null, "body": "> While I'm doing this I should rename this internal variable to avoid confusion in the future:\r\n>\r\n> https://github.com/simonw/datasette/blob/e837095ef35ae155b4c78cc9a8b7133a48c94f03/datasette/app.py#L203\r\n\r\n_Originally posted by @simonw in https://github.com/simonw/datasette/issues/1431#issuecomment-898072940_", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/1432/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": null} {"id": 780153562, "node_id": "MDU6SXNzdWU3ODAxNTM1NjI=", "number": 1177, "title": "Ability to stream all rows as newline-delimited JSON", "user": {"value": 9599, "label": "simonw"}, "state": "open", "locked": 0, "assignee": null, "milestone": {"value": 3268330, "label": "Datasette 1.0"}, "comments": 1, "created_at": "2021-01-06T07:10:48Z", "updated_at": "2022-03-21T15:08:52Z", "closed_at": null, "author_association": "OWNER", "pull_request": null, "body": "> Yet another use-case for this: I want to be able to stream newline-delimited JSON in order to better import into Pandas:\r\n> \r\n> pandas.read_json(\"https://latest.datasette.io/fixtures/compound_three_primary_keys.json?_shape=array&_nl=on\", lines=True)\r\n_Originally posted by @simonw in https://github.com/simonw/datasette/issues/1101#issuecomment-755128038_", "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/1177/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": 1940346034, "node_id": "I_kwDOBm6k_c5zp1Sy", "number": 2199, "title": "Detailed upgrade instructions for metadata.yaml -> datasette.yaml", "user": {"value": 9599, "label": "simonw"}, "state": "open", "locked": 0, "assignee": null, "milestone": {"value": 3268330, "label": "Datasette 1.0"}, "comments": 7, "created_at": "2023-10-12T16:21:25Z", "updated_at": "2023-10-12T22:08:42Z", "closed_at": null, "author_association": "OWNER", "pull_request": null, "body": "> `Exception: Datasette no longer accepts plugin configuration in --metadata. Move your \"plugins\" configuration blocks to a separate file - we suggest calling that datasette..json - and start Datasette with datasette -c datasette..json. See https://docs.datasette.io/en/latest/configuration.html for more details.`\r\n>\r\n> I think we should link directly to documentation that tells people how to perform this upgrade.\r\n\r\n_Originally posted by @simonw in https://github.com/simonw/datasette/issues/2190#issuecomment-1759947021_\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/2199/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": 1840324765, "node_id": "I_kwDOBm6k_c5tsSCd", "number": 2129, "title": "CSV ?sql= should indicate errors", "user": {"value": 9599, "label": "simonw"}, "state": "open", "locked": 0, "assignee": null, "milestone": {"value": 3268330, "label": "Datasette 1.0"}, "comments": 1, "created_at": "2023-08-07T23:13:04Z", "updated_at": "2023-08-08T02:02:21Z", "closed_at": null, "author_association": "OWNER", "pull_request": null, "body": "> https://latest.datasette.io/_memory.csv?sql=select+blah is a blank page right now:\r\n\r\n```bash\r\ncurl -I 'https://latest.datasette.io/_memory.csv?sql=select+blah'\r\n```\r\n```\r\nHTTP/2 200 \r\naccess-control-allow-origin: *\r\naccess-control-allow-headers: Authorization, Content-Type\r\naccess-control-expose-headers: Link\r\naccess-control-allow-methods: GET, POST, HEAD, OPTIONS\r\naccess-control-max-age: 3600\r\ncontent-type: text/plain; charset=utf-8\r\nx-databases: _memory, _internal, fixtures, fixtures2, extra_database, ephemeral\r\ndate: Mon, 07 Aug 2023 23:12:15 GMT\r\nserver: Google Frontend\r\n```\r\n\r\n_Originally posted by @simonw in https://github.com/simonw/datasette/issues/2118#issuecomment-1668688947_", "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/2129/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": 930807135, "node_id": "MDU6SXNzdWU5MzA4MDcxMzU=", "number": 1384, "title": "Plugin hook for dynamic metadata", "user": {"value": 9599, "label": "simonw"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 22, "created_at": "2021-06-26T22:36:03Z", "updated_at": "2022-03-14T00:36:42Z", "closed_at": null, "author_association": "OWNER", "pull_request": null, "body": "@brandonrobertz contributed an implementation of this in PR #1368, which I just merged. Opening this ticket to track further work on this before it goes out in a Datasette release (likely preceded by an alpha).", "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/1384/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": 1247315144, "node_id": "I_kwDOBm6k_c5KWITI", "number": 1749, "title": "LDAP auth plugin", "user": {"value": 380241, "label": "benswift"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 0, "created_at": "2022-05-25T01:35:12Z", "updated_at": "2022-05-25T01:35:12Z", "closed_at": null, "author_association": "NONE", "pull_request": null, "body": "A [search of the plugins directory](https://datasette.io/plugins?q=ldap) doesn't turn up anything, but is is possible to set up a Datasette app which uses my organisation's LDAP for auth?\r\n\r\nIf not, how much work would it be to write one (I _may_ have some spare cycles on my team to do this, but we haven't written a datasette plugin before).", "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/1749/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": 1217014076, "node_id": "I_kwDOBm6k_c5Iiik8", "number": 1726, "title": "Security page in the documentation", "user": {"value": 9599, "label": "simonw"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 0, "created_at": "2022-04-27T08:43:30Z", "updated_at": "2022-04-27T08:43:30Z", "closed_at": null, "author_association": "OWNER", "pull_request": null, "body": "A page talking about how to run Datasette securely, and security concerns to take into account.", "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/1726/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": 953218043, "node_id": "MDU6SXNzdWU5NTMyMTgwNDM=", "number": 1403, "title": "Labels explaining what hidden tables are for", "user": {"value": 9599, "label": "simonw"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 0, "created_at": "2021-07-26T19:29:22Z", "updated_at": "2022-03-21T22:20:37Z", "closed_at": null, "author_association": "OWNER", "pull_request": null, "body": "A reasonable question: \"What are those hidden tables for?\"\r\n\r\nThis could be answered by adding a small piece of explanatory text to each table - based on if it's related to FTS or to SpatiaLite or configured to be hidden for some other reason.", "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/1403/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": 1618249044, "node_id": "I_kwDOBm6k_c5gdIVU", "number": 2038, "title": "Consider a `strict_templates` setting", "user": {"value": 9599, "label": "simonw"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 2, "created_at": "2023-03-10T02:09:13Z", "updated_at": "2023-03-10T02:11:06Z", "closed_at": null, "author_association": "OWNER", "pull_request": null, "body": "A setting which turns on Jinja strict mode, so any templates that access undefined variables raise a hard error.\r\n\r\nPrototype here:\r\n```diff\r\ndiff --git a/datasette/app.py b/datasette/app.py\r\nindex 40416713..1428a3f0 100644\r\n--- a/datasette/app.py\r\n+++ b/datasette/app.py\r\n@@ -200,6 +200,7 @@ SETTINGS = (\r\n \"Allow display of SQL trace debug information with ?_trace=1\",\r\n ),\r\n Setting(\"base_url\", \"/\", \"Datasette URLs should use this base path\"),\r\n+ Setting(\"strict_templates\", False, \"Raise errors for undefined template variables\"),\r\n )\r\n _HASH_URLS_REMOVED = \"The hash_urls setting has been removed, try the datasette-hashed-urls plugin instead\"\r\n OBSOLETE_SETTINGS = {\r\n@@ -399,11 +400,14 @@ class Datasette:\r\n ),\r\n ]\r\n )\r\n+ env_extras = {}\r\n+ if self.setting(\"strict_templates\"):\r\n+ env_extras[\"undefined\"] = StrictUndefined\r\n self.jinja_env = Environment(\r\n loader=template_loader,\r\n autoescape=True,\r\n enable_async=True,\r\n- undefined=StrictUndefined,\r\n+ **env_extras,\r\n )\r\n self.jinja_env.filters[\"escape_css_string\"] = escape_css_string\r\n self.jinja_env.filters[\"quote_plus\"] = urllib.parse.quote_plus\r\n```\r\nExplored this idea a bit in:\r\n- #1999", "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/2038/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": 355299310, "node_id": "MDExOlB1bGxSZXF1ZXN0MjExODYwNzA2", "number": 363, "title": "Search all apps during heroku publish", "user": {"value": 436032, "label": "kevboh"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 1, "created_at": "2018-08-29T19:25:10Z", "updated_at": "2018-08-31T14:39:45Z", "closed_at": null, "author_association": "FIRST_TIME_CONTRIBUTOR", "pull_request": "simonw/datasette/pulls/363", "body": "Adds the `-A` option to include apps from all organizations when searching app names for publish.", "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/363/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": 1197926598, "node_id": "I_kwDOBm6k_c5HZujG", "number": 1705, "title": "How to upgrade your plugin for 1.0 documentation", "user": {"value": 9599, "label": "simonw"}, "state": "open", "locked": 0, "assignee": null, "milestone": {"value": 8755003, "label": "Datasette 1.0a-next"}, "comments": 1, "created_at": "2022-04-08T23:16:47Z", "updated_at": "2022-12-13T05:29:05Z", "closed_at": null, "author_association": "OWNER", "pull_request": null, "body": "Among other things, needed by:\r\n- #1704", "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/1705/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": 924203783, "node_id": "MDU6SXNzdWU5MjQyMDM3ODM=", "number": 1379, "title": "Idea: ?_end=1 option for streaming CSV responses", "user": {"value": 9599, "label": "simonw"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 0, "created_at": "2021-06-17T18:11:21Z", "updated_at": "2021-06-17T18:11:30Z", "closed_at": null, "author_association": "OWNER", "pull_request": null, "body": "As discussed in this thread: https://twitter.com/simonw/status/1405554676993433605 - one of the disadvantages of Datasette's streaming CSV feature is that it's hard to tell if you got the whole file or if the connection ended early - or if an error occurred.\r\n\r\nIdea: offer an optional `?_end=1` parameter which, if enabled, adds a single row to the end of the CSV file that looks like this:\r\n\r\n`END,,,,,,,,,`\r\n\r\nFor however many columns the CSV file usually has.", "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/1379/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": 1197925865, "node_id": "I_kwDOBm6k_c5HZuXp", "number": 1704, "title": "File PRs against incompatible plugins pinning to datasette<1.0", "user": {"value": 9599, "label": "simonw"}, "state": "open", "locked": 0, "assignee": null, "milestone": {"value": 3268330, "label": "Datasette 1.0"}, "comments": 0, "created_at": "2022-04-08T23:15:30Z", "updated_at": "2022-04-08T23:15:30Z", "closed_at": null, "author_association": "OWNER", "pull_request": null, "body": "As part of the preparation for the 1.0 release, test all existing known plugins against the alpha.\r\n\r\nFor any that break, submit a PR suggesting they pin to a version <1.0 - and include a link to the documentation on how to upgrade the plugin for 1.0.", "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/1704/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": 1531991339, "node_id": "I_kwDOBm6k_c5bUFUr", "number": 1989, "title": "Suggestion: Hiding columns", "user": {"value": 116795, "label": "pax"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 3, "created_at": "2023-01-13T09:33:32Z", "updated_at": "2023-03-31T06:18:05Z", "closed_at": null, "author_association": "NONE", "pull_request": null, "body": "As there's the possibility of [hiding tables](https://docs.datasette.io/en/stable/metadata.html#hiding-tables) - I've run into the **need of hiding specific columns** - data that's either not relevant for public or can't be shown due to privacy reasons. ", "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/1989/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": 1174708375, "node_id": "I_kwDOBm6k_c5GBKCX", "number": 1673, "title": "Streaming CSV spends a lot of time in `table_column_details`", "user": {"value": 9599, "label": "simonw"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 1, "created_at": "2022-03-20T22:25:28Z", "updated_at": "2022-03-20T22:34:06Z", "closed_at": null, "author_association": "OWNER", "pull_request": null, "body": "At least I think it does. I tried running `py-spy top -p $PID` against a Datasette process that was trying to do:\r\n\r\n datasette covid.db --get '/covid/ny_times_us_counties.csv?_size=10&_stream=on'\r\n\r\nWhile investigating:\r\n- #1355\r\n\r\nAnd spotted this:\r\n```\r\ndatasette covid.db --get /covid/ny_times_us_counties.csv?_size=10&_stream=on' (python v3.10.2)\r\nTotal Samples 5800\r\nGIL: 71.00%, Active: 98.00%, Threads: 4\r\n\r\n %Own %Total OwnTime TotalTime Function (filename:line) \r\n 8.00% 8.00% 4.32s 4.38s sql_operation_in_thread (datasette/database.py:212)\r\n 5.00% 5.00% 3.77s 3.93s table_column_details (datasette/utils/__init__.py:614)\r\n 6.00% 6.00% 3.72s 3.72s _worker (concurrent/futures/thread.py:81)\r\n 7.00% 7.00% 2.98s 2.98s _read_from_self (asyncio/selector_events.py:120)\r\n 5.00% 6.00% 2.35s 2.49s detect_fts (datasette/utils/__init__.py:571)\r\n 4.00% 4.00% 1.34s 1.34s _write_to_self (asyncio/selector_events.py:140)\r\n```\r\nRelevant code: https://github.com/simonw/datasette/blob/798f075ef9b98819fdb564f9f79c78975a0f71e8/datasette/utils/__init__.py#L609-L625\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/1673/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": 275159710, "node_id": "MDU6SXNzdWUyNzUxNTk3MTA=", "number": 128, "title": "Every visualization should have an \"embed\" button", "user": {"value": 9599, "label": "simonw"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 0, "created_at": "2017-11-19T13:38:13Z", "updated_at": "2019-05-13T18:33:51Z", "closed_at": null, "author_association": "OWNER", "pull_request": null, "body": "At least for the first round of visualizations, any time you construct one using the UI the result should include an \"embed this\" button that returns source code to copy and paste\r\n\r\nThese examples should use unpkg.com (or similarl) urls with SRI hashes, eg https://www.srihash.org - and should load data from the datasette JSON API.", "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/128/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": 2028698018, "node_id": "I_kwDOBm6k_c5463mi", "number": 2213, "title": "feature request: gzip compression of database downloads", "user": {"value": 536941, "label": "fgregg"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 1, "created_at": "2023-12-06T14:35:03Z", "updated_at": "2023-12-06T15:05:46Z", "closed_at": null, "author_association": "CONTRIBUTOR", "pull_request": null, "body": "At the bottom of database pages, datasette gives users the opportunity to download the underlying sqlite database. It would be great if that could be served gzip compressed. \r\n\r\nthis is similar to #1213, but for me, i don't need datasette to compress html and json because my CDN layer does it for me, however, cloudflare at least, will not compress a mimetype of \"application\"\r\n\r\n(see list of mimetype: https://developers.cloudflare.com/speed/optimization/content/brotli/content-compression/)", "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/2213/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": 374953006, "node_id": "MDU6SXNzdWUzNzQ5NTMwMDY=", "number": 369, "title": "Interface should show same JSON shape options for custom SQL queries", "user": {"value": 416374, "label": "gfrmin"}, "state": "open", "locked": 0, "assignee": null, "milestone": {"value": 3268330, "label": "Datasette 1.0"}, "comments": 2, "created_at": "2018-10-29T10:39:15Z", "updated_at": "2020-05-30T17:24:06Z", "closed_at": null, "author_association": "CONTRIBUTOR", "pull_request": null, "body": "At the moment the page returning a custom SQL query shows the JSON and CSV APIs, but not the multiple JSON shapes. However, adding the `_shape` parameter to the JSON API URL manually still works, so perhaps there should be consistency in the interface by having the same \"Advanced Export\" box for custom SQL 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/369/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": 1237871948, "node_id": "I_kwDOBm6k_c5JyG1M", "number": 1743, "title": "`datasette.utils.to_css_class()` should be a documented internal", "user": {"value": 9599, "label": "simonw"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 0, "created_at": "2022-05-16T23:57:26Z", "updated_at": "2022-05-16T23:57:26Z", "closed_at": null, "author_association": "OWNER", "pull_request": null, "body": "Because I'm using it in this plugin:\r\n- https://github.com/simonw/datasette-upload-dbs/issues/1", "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/1743/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": 462117311, "node_id": "MDU6SXNzdWU0NjIxMTczMTE=", "number": 531, "title": "/database/-/inspect", "user": {"value": 9599, "label": "simonw"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 1, "created_at": "2019-06-28T16:33:41Z", "updated_at": "2019-07-08T15:43:57Z", "closed_at": null, "author_association": "OWNER", "pull_request": null, "body": "Build `/database/-/inspect` which shows tables, columns, column types and foreign keys\r\n\r\nIt won't show table counts. Or maybe it will include them optionally but only for `-i` databases, in a special area of the JSON reserved for immutable-only inspect details.\r\n\r\n_Originally posted by @simonw in https://github.com/simonw/datasette/issues/465#issuecomment-506797086_", "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/531/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": 1983600865, "node_id": "PR_kwDOBm6k_c5e7WH7", "number": 2206, "title": "Bump the python-packages group with 1 update", "user": {"value": 49699333, "label": "dependabot[bot]"}, "state": "open", "locked": 0, "assignee": null, "milestone": null, "comments": 1, "created_at": "2023-11-08T13:18:56Z", "updated_at": "2023-12-08T13:46:24Z", "closed_at": null, "author_association": "CONTRIBUTOR", "pull_request": "simonw/datasette/pulls/2206", "body": "Bumps the python-packages group with 1 update: [black](https://github.com/psf/black).\n\nSourced from black's releases.
\n\n\n23.11.0
\nHighlights
\n\n
\n- Support formatting ranges of lines with the new
\n--line-ranges
command-line option\n(#4020)Stable style
\n\n
\n- Fix crash on formatting bytes strings that look like docstrings (#4003)
\n- Fix crash when whitespace followed a backslash before newline in a docstring (#4008)
\n- Fix standalone comments inside complex blocks crashing Black (#4016)
\n- Fix crash on formatting code like
\nawait (a ** b)
(#3994)- No longer treat leading f-strings as docstrings. This matches Python's behaviour and\nfixes a crash (#4019)
\nPreview style
\n\n
\n- Multiline dicts and lists that are the sole argument to a function are now\nindented less (#3964)
\n- Multiline unpacked dicts and lists as the sole argument to a function are now also\nindented less (#3992)
\n- In f-string debug expressions, quote types that are visible in the final string\nare now preserved (#4005)
\n- Fix a bug where long
\ncase
blocks were not split into multiple lines. Also enable\ngeneral trailing comma rules oncase
blocks (#4024)- Keep requiring two empty lines between module-level docstring and first function or\nclass definition (#4028)
\n- Add support for single-line format skip with other comments on the same line (#3959)
\nConfiguration
\n\n
\n- Consistently apply force exclusion logic before resolving symlinks (#4015)
\n- Fix a bug in the matching of absolute path names in
\n--include
(#3976)Performance
\n\n
\n- Fix mypyc builds on arm64 on macOS (#4017)
\nIntegrations
\n\n
\n- Black's pre-commit integration will now run only on git hooks appropriate for a code\nformatter (#3940)
\n23.10.1
\nHighlights
\n\n
\n- Maintanence release to get a fix out for GitHub Action edge case (#3957)
\nPreview style
\n\n
... (truncated)
\nSourced from black's changelog.
\n\n\n23.11.0
\nHighlights
\n\n
\n- Support formatting ranges of lines with the new
\n--line-ranges
command-line option\n(#4020)Stable style
\n\n
\n- Fix crash on formatting bytes strings that look like docstrings (#4003)
\n- Fix crash when whitespace followed a backslash before newline in a docstring (#4008)
\n- Fix standalone comments inside complex blocks crashing Black (#4016)
\n- Fix crash on formatting code like
\nawait (a ** b)
(#3994)- No longer treat leading f-strings as docstrings. This matches Python's behaviour and\nfixes a crash (#4019)
\nPreview style
\n\n
\n- Multiline dicts and lists that are the sole argument to a function are now indented\nless (#3964)
\n- Multiline unpacked dicts and lists as the sole argument to a function are now also\nindented less (#3992)
\n- In f-string debug expressions, quote types that are visible in the final string are\nnow preserved (#4005)
\n- Fix a bug where long
\ncase
blocks were not split into multiple lines. Also enable\ngeneral trailing comma rules oncase
blocks (#4024)- Keep requiring two empty lines between module-level docstring and first function or\nclass definition (#4028)
\n- Add support for single-line format skip with other comments on the same line (#3959)
\nConfiguration
\n\n
\n- Consistently apply force exclusion logic before resolving symlinks (#4015)
\n- Fix a bug in the matching of absolute path names in
\n--include
(#3976)Performance
\n\n
\n- Fix mypyc builds on arm64 on macOS (#4017)
\nIntegrations
\n\n
\n- Black's pre-commit integration will now run only on git hooks appropriate for a code\nformatter (#3940)
\n23.10.1
\nHighlights
\n\n
\n\n- Maintenance release to get a fix out for GitHub Action edge case (#3957)
\n
... (truncated)
\n2a1c67e
Prepare release 23.11.0 (#4032)72e7a2e
Remove redundant condition from has_magic_trailing_comma
(#4023)1a7d9c2
Preserve visible quote types for f-string debug expressions (#4005)f4c7be5
docs: fix minor typo (#4030)2e4fac9
Apply force exclude logic before symlink resolution (#4015)66008fd
[563] Fix standalone comments inside complex blocks crashing Black (#4016)50ed622
Fix long case blocks not split into multiple lines (#4024)46be1f8
Support formatting specified lines (#4020)ecbd9e8
Fix crash with f-string docstrings (#4019)e808e61
Preview: Keep requiring two empty lines between module-level docstring and fi...