# issues

node_id: I_kwDOBm6k_c5dyI6-
title: Refactor out the keyset pagination code
state: open
created_at: 2023-02-06T23:04:00Z
updated_at: 2023-02-08T01:40:46Z
author_association: OWNER
type: issue
body:
  While working on:
  - #1999

  I noticed that some of the most complex code in the existing table view is the code that implements keyset pagination:

  https://github.com/simonw/datasette/blob/0b4a28691468b5c758df74fa1d72a823813c96bf/datasette/views/table.py#L417-L493

  Extracting that into a utility function would simplify that code a lot.

reactions:
  {"url": "https://api.github.com/repos/simonw/datasette/issues/2019/reactions", "total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0}


node_id: I_kwDOCGYnMM5d4ppZ
title: Repeated calls to `Table.convert()` fail
state: closed
created_at: 2023-02-07T22:40:47Z
updated_at: 2023-05-08T21:59:41Z
closed_at: 2023-05-08T21:54:02Z
author_association: CONTRIBUTOR
type: issue
state_reason: completed
body:
  ## Summary
  When using the API, repeated calls to `Table.convert()`  do not work correctly since all conversions quietly use the callable (function, lambda) from the first call to `convert()` only. Subsequent invocations with different callables use the callable from the first invocation only.

  ## Example
  ```python
  from sqlite_utils import Database

  db = Database(memory=True)
  table = db['table']
  col = 'x'
  table.insert_all([{col: 1}])
  print(table.get(1))

  table.convert(col, lambda x: x*2)
  print(table.get(1))

  def zeroize(x):
      return 0
  #zeroize = lambda x: 0
  #zeroize.__name__ = 'zeroize'
  table.convert(col, zeroize)
  print(table.get(1))
  ```

  Output:
  ```
  {'x': 1}
  {'x': 2}
  {'x': 4}
  ```
  Expected:
  ```
  {'x': 1}
  {'x': 2}
  {'x': 0}
  ```

  ## Explanation
  This is some relevant [documentation](https://github.com/simonw/sqlite-utils/blob/1491b66dd7439dd87cd5cd4c4684f46eb3c5751b/docs/python-api.rst#registering-custom-sql-functions:~:text=By%20default%20registering%20a%20function%20with%20the%20same%20name%20and%20number%20of%20arguments%20will%20have%20no%20effect).

   * `Table.convert()` takes a `Callable` to perform data conversion on a column
   * The `Callable` is passed to `Database.register_function()`
   * `Database.register_function()` uses the callable's `__name__` attribute for registration
   * (Aside: all lambdas have a `__name__` of `<lambda>`: I thought this was the problem, and it was close, but not quite)
   * However `convert()` first wraps the callable by local function [`convert_value()`](https://github.com/simonw/sqlite-utils/blob/fc221f9b62ed8624b1d2098e564f525c84497969/sqlite_utils/db.py#L2661)
   * Consequently `register_function()` sees name `convert_value` for all invocations from `convert()`
   * `register_function()` silently ignores registrations using the same name, retaining only the first such registration

  There's a mismatch between the comments and the code: https://github.com/simonw/sqlite-utils/blob/fc221f9b62ed8624b1d2098e564f525c84497969/sqlite_utils/db.py#L404

  but actually the existing function is returned/used instead (as the "registering custom sql functions" doc I linked above says too). Seems like this can be rectified to match the comment?

  ## Suggested fix
  I think there are four things:
  1. The call to `register_function()` from `convert()`should have an explicit `name=` parameter (to continue using `convert_value()` and the progress bar).
  2. For functions, this name can be the real function name. (I understand the sqlite api needs a name, and it's nice if those are recognizable names where possible). For lambdas would `'lambda-{uuid}'` or similar be acceptable? 
  3. `register_function()` really should throw an error on repeated attempts to register a duplicate (function, arity)-pair.
  4. A test? I haven't looked at the test framework here but seems this should be testable.

  ## See also 
  - #458 

reactions:
  {"url": "https://api.github.com/repos/simonw/sqlite-utils/issues/525/reactions", "total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0}


node_id: I_kwDOBm6k_c5d7giJ
title: Documentation refers to "off" setting; doesn't seem to work, "false" does
state: open
created_at: 2023-02-08T10:38:10Z
updated_at: 2023-02-08T10:38:10Z
author_association: NONE
type: issue
body:
  https://docs.datasette.io/en/stable/settings.html#suggest-facets, among others, suggests using "off" to disable the setting; however, this doesn't appear to work in the JSON config files, where it apparently needs to be a "JSON boolean" and have the values "true" or "false".  Perhaps the Python code is more flexible?...but either way, the documentation probably should mention it.

reactions:
  {"url": "https://api.github.com/repos/simonw/datasette/issues/2020/reactions", "total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0}


node_id: PR_kwDOCGYnMM5JkkED
title: Fix repeated calls to `Table.convert()`
state: closed
created_at: 2023-02-09T00:14:49Z
updated_at: 2023-05-08T21:56:05Z
closed_at: 2023-05-08T21:53:58Z
author_association: CONTRIBUTOR
pull_request: simonw/sqlite-utils/pulls/526
type: pull
body:
  Fixes #525. All tests pass.

  There's perhaps a better way to name lambdas? There could be a collision if a caller passes a function with name like `lambda_123456`.

  SQLite [documentation](https://www.sqlite.org/appfunc.html) is a little, ah, lite on function name specs. If there is a character that can be used in place of underscore in a SQLite function name that is not permitted in a Python function identifier then that could be a good way to prevent accidental collisions. (I tried dash, colon, dot, no joy).

  Otherwise, there is little chance of this happening and if it should happen the risk is mitigated by now throwing an exception in the case of a (name, arity) collision without `replace=True`.

  <!-- readthedocs-preview sqlite-utils start -->
  ----
  :books: Documentation preview :books:: https://sqlite-utils--526.org.readthedocs.build/en/526/

  <!-- readthedocs-preview sqlite-utils end -->

reactions:
  {"url": "https://api.github.com/repos/simonw/sqlite-utils/issues/526/reactions", "total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0}


node_id: I_kwDOBm6k_c5eB3sj
title: Docker images for 1.0 alphas?
state: open
created_at: 2023-02-09T09:35:52Z
updated_at: 2023-02-09T09:35:52Z
author_association: NONE
type: issue
body:
  Hi,
  would you consider putting 1.0alpha images on Dockerhub? 

  (Also, how usable are the alphas?)

reactions:
  {"url": "https://api.github.com/repos/simonw/datasette/issues/2021/reactions", "total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0}


node_id: I_kwDOBm6k_c5eF6v6
title: Error 500 - not clear the cause
state: closed
created_at: 2023-02-09T20:57:17Z
updated_at: 2023-02-09T21:13:50Z
closed_at: 2023-02-09T21:13:50Z
author_association: NONE
type: issue
state_reason: completed
body:
  On the database that I have sent via linkedIn, datasette works great, but the following URL gives a 500 error.

  http://127.0.0.1:8001/literature/authors_papers?authorId=100550354

  The cause of the error is not apparent.

  Is this expected behaviour?

  David

reactions:
  {"url": "https://api.github.com/repos/simonw/datasette/issues/2022/reactions", "total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0}


node_id: I_kwDOCGYnMM5eGmy2
title: `Table.convert()` skips falsey values
state: closed
created_at: 2023-02-10T00:00:52Z
updated_at: 2023-05-09T21:15:05Z
closed_at: 2023-05-08T21:03:24Z
author_association: CONTRIBUTOR
type: issue
state_reason: completed
body:
  # Summary

  By design, `Table.convert()` does [not attempt](https://github.com/simonw/sqlite-utils/blob/fc221f9b62ed8624b1d2098e564f525c84497969/sqlite_utils/db.py#L2663) conversion of falsey values (`None`, `""`, `0`, ...). This is surprising (directly contradicts the docstring) and `convert()` may quietly skip cells where the user assumed a conversion would take place. 

  # Example
  Increment a column of integers by one

  ``` python
  from sqlite_utils import Database

  db = Database(memory=True)
  table = db['table']
  col = 'x'
  table.insert_all([{col: 0}, {col:1}])
  print(table.get(1)) # 0
  print(table.get(2)) # 1
  print()

  table.convert(col, lambda x: x+1)
  print(table.get(1)) # got 0, expected 1 ⚠⚠⚠
  print(table.get(2)) # got 2, expected 2
  ```

  Another example might be, say, transforming cells containing empty string to `NULL`.

  # Discussion

  This was, I think, a pragmatic choice so that consumers can skip writing guard clauses for these falsey values (particularly from the CLI). But this surprising undocumented behavior can lead to incorrect data. I don't think this is a good trade-off between convenience and correctness.

  In the absence of this convenience users will either have to write guard clauses into their conversion expressions (or adapt the called function to do the same), so: 
  ``` python
      fn(value) if value else value
  ```
  instead of:
  ``` python
      fn(value)
  ```
  This is more typing and sometimes I will forget, and there will be errors. (But they will be noisy errors, which is a good thing).

  Such a change will certainly inconvenience some existing consumers; there will be some breakage. But I think this is worth it to avoid quietly not converting some values by default, which can lead to quietly bad data.

  I have a PR that I will attach, please take a look and see what you think.

reactions:
  {"url": "https://api.github.com/repos/simonw/sqlite-utils/issues/527/reactions", "total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0}


node_id: PR_kwDOCGYnMM5Jqn1u
title: Enable `Table.convert()` on falsey values
state: closed
created_at: 2023-02-10T00:04:09Z
updated_at: 2023-05-08T21:08:23Z
closed_at: 2023-05-08T21:08:23Z
author_association: CONTRIBUTOR
pull_request: simonw/sqlite-utils/pulls/528
type: pull
body:
  Fixes #527

  <!-- readthedocs-preview sqlite-utils start -->
  ----
  :books: Documentation preview :books:: https://sqlite-utils--528.org.readthedocs.build/en/528/

  <!-- readthedocs-preview sqlite-utils end -->

reactions:
  {"url": "https://api.github.com/repos/simonw/sqlite-utils/issues/528/reactions", "total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0}


node_id: I_kwDOBm6k_c5eKD7B
title: Error: Invalid setting 'hash_urls' in settings.json in 0.64.1
state: closed
created_at: 2023-02-10T13:35:01Z
updated_at: 2023-02-10T15:40:00Z
closed_at: 2023-02-10T15:39:59Z
author_association: NONE
type: issue
state_reason: completed
body:
  On a Debian machine, using datasette 0.64.1 installed with `pip3`, I am getting a `datasette[114272]: Error: Invalid setting 'hash_urls' in settings.json` in `journalctl -xe`. The same settings work on 0.54.1 on another Debian server.

  This is my `settings.json`:

  ```json
  {
      "default_page_size": 200,
      "max_returned_rows": 8000,
      "num_sql_threads": 3,
      "sql_time_limit_ms": 1000,
      "default_facet_size": 30,
      "facet_time_limit_ms": 200,
      "facet_suggest_time_limit_ms": 50,
      "hash_urls": false,
      "allow_facet": true,
      "allow_download": true,
      "suggest_facets": true,
      "default_cache_ttl": 5,
      "default_cache_ttl_hashed": 31536000,
      "cache_size_kb": 0,
      "allow_csv_stream": true,
      "max_csv_mb": 100,
      "truncate_cells_html": 2048,
      "force_https_urls": false,
      "template_debug": false,
      "base_url": "/pclim/db/"
  }
  ```

  This looks ok to me. Would you have any ideas?

reactions:
  {"url": "https://api.github.com/repos/simonw/datasette/issues/2023/reactions", "total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0}


node_id: I_kwDOBm6k_c5eLHpn
title: Mention WAL mode in documentation
state: open
created_at: 2023-02-10T16:11:10Z
updated_at: 2023-02-10T16:11:53Z
author_association: OWNER
type: issue
body:
  It's not currently obvious from the docs how you can ensure that Datasette runs well in situations where other processes may update the underlying SQLite files.

reactions:
  {"url": "https://api.github.com/repos/simonw/datasette/issues/2024/reactions", "total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0}


node_id: I_kwDOCGYnMM5ePYYX
title: Microsoft line endings
state: closed
created_at: 2023-02-12T02:20:48Z
updated_at: 2023-06-14T23:12:12Z
closed_at: 2023-06-14T23:11:47Z
author_association: CONTRIBUTOR
type: issue
state_reason: completed
body:
  sqlite-utils prints `\r\n` but [it should probably](https://devblogs.microsoft.com/commandline/extended-eol-in-notepad/) print `\n` (unless the platform is detected as Windows?)

  It has tripped me up a few times when piping the output of sqlite-utils to other programs:

  ```
  $ sqlite-utils --no-headers --csv  ~/lb/fs/d.db 'select path from media limit 1' | cat -A
  /mnt/d7/file^M$
  $ sqlite-utils --no-headers --csv  ~/lb/fs/d.db 'select path from media limit 1' | tr -d '\r' | cat -A
  /mnt/d7/file$
  ```

reactions:
  {"url": "https://api.github.com/repos/simonw/sqlite-utils/issues/529/reactions", "total_count": 1, "+1": 1, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0}


node_id: PR_kwDOBm6k_c5JyqPy
title: Add database metadata to index.html template context
state: open
created_at: 2023-02-12T11:16:58Z
updated_at: 2023-02-12T11:17:14Z
author_association: FIRST_TIME_CONTRIBUTOR
pull_request: simonw/datasette/pulls/2025
type: pull
body:
  Fixes #2016 

  <!-- readthedocs-preview datasette start -->
  ----
  :books: Documentation preview :books:: https://datasette--2025.org.readthedocs.build/en/2025/

  <!-- readthedocs-preview datasette end -->

reactions:
  {"url": "https://api.github.com/repos/simonw/datasette/issues/2025/reactions", "total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0}


node_id: PR_kwDOBm6k_c5KF-by
title: Avoid repeating primary key columns if included in _col args
state: open
created_at: 2023-02-16T04:16:25Z
updated_at: 2023-02-16T04:16:41Z
author_association: FIRST_TIME_CONTRIBUTOR
pull_request: simonw/datasette/pulls/2026
type: pull
body:
  ...while maintaining given order.

  Fixes #1975 (if I'm understanding correctly).

  <!-- readthedocs-preview datasette start -->
  ----
  :books: Documentation preview :books:: https://datasette--2026.org.readthedocs.build/en/2026/

  <!-- readthedocs-preview datasette end -->

reactions:
  {"url": "https://api.github.com/repos/simonw/datasette/issues/2026/reactions", "total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0}


node_id: I_kwDOBm6k_c5eyEVo
title: How to redirect from "/" to a specific db/table
state: open
created_at: 2023-02-18T03:14:01Z
updated_at: 2023-03-08T04:42:22Z
author_association: NONE
type: issue
body:
  Using nginx to redirect public IP to the local uvicorn server as 'normal'.  I can't figure out how to redirect such that '/' results in accessing the one db/table I want to serve; redirecting / to /db/table breaks some of the CSS; fooling with base_url doesn't seem to help.  Can someone explain this, if it's possible?

reactions:
  {"url": "https://api.github.com/repos/simonw/datasette/issues/2027/reactions", "total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0}


node_id: PR_kwDOBm6k_c5KSs9T
title: add Python 3.11 classifier
state: closed
created_at: 2023-02-19T20:16:03Z
updated_at: 2023-03-06T21:01:20Z
closed_at: 2023-03-06T21:01:19Z
author_association: CONTRIBUTOR
pull_request: simonw/datasette/pulls/2028
type: pull
body:
  Python 3.11 is tested in CI and is used in the docker image, so add the Python 3.11 Trove classifier.

  <!-- readthedocs-preview datasette start -->
  ----
  :books: Documentation preview :books:: https://datasette--2028.org.readthedocs.build/en/2028/

  <!-- readthedocs-preview datasette end -->

reactions:
  {"url": "https://api.github.com/repos/simonw/datasette/issues/2028/reactions", "total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0}


node_id: I_kwDOBm6k_c5e6Pyv
title: Sorry Simon, didn't know how else to contact you
state: open
created_at: 2023-02-20T19:02:53Z
updated_at: 2023-02-20T19:02:53Z
author_association: NONE
type: issue
body:
  Hi Simon,

  Would you be willing to chat with me about Datasette? I have some questions. I am working on a project to evaluate data ingestion tools for a research organization and I ran across Datasette. I have looked through a lot of your documentation, but still have some questions, which are very specific. If you would be willing to write me back about this, my email is laura@renci.org.

  Thanks,
  Laura

reactions:
  {"url": "https://api.github.com/repos/simonw/datasette/issues/2029/reactions", "total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0}


node_id: I_kwDOBm6k_c5fCFuw
title: How to use Datasette with apache webserver on GCP?
state: closed
created_at: 2023-02-22T03:08:49Z
updated_at: 2023-02-22T21:54:39Z
closed_at: 2023-02-22T21:54:39Z
author_association: NONE
type: issue
state_reason: completed
body:
  Hi Simon and Datasette team-

  I have installed apache2 webserver inside GCP VM using apt.

  I can see my "Hello World" index.html if I use the external IP of this GCP in a browser.

  However, when I try to run datasette with different combinations of -h and -p, I am still unable to access the webpage.

  I cannot invest Docker on this VM.

  Any pointers to use datasette with already existing apache2 webserver on GCP is appreciated.

  Thanks.

reactions:
  {"url": "https://api.github.com/repos/simonw/datasette/issues/2030/reactions", "total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0}


node_id: I_kwDOCGYnMM5fFveU
title: add ability to configure "on delete" and "on update" attributes of foreign keys:
state: open
created_at: 2023-02-22T15:44:14Z
updated_at: 2023-05-08T20:39:01Z
author_association: CONTRIBUTOR
type: issue
body:
  sqlite supports these, and it would be quite nice to be able to add them with sqlite-utils.

  https://www.sqlite.org/foreignkeys.html#fk_actions

reactions:
  {"url": "https://api.github.com/repos/simonw/sqlite-utils/issues/530/reactions", "total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0}


node_id: PR_kwDOBm6k_c5LDwrF
title: Expand foreign key references in row view as well
state: open
created_at: 2023-03-01T18:43:09Z
updated_at: 2023-03-24T18:35:25Z
author_association: FIRST_TIME_CONTRIBUTOR
pull_request: simonw/datasette/pulls/2031
type: pull
body:
  Unlike the table view, the single row view does not resolve foreign key references into labels. This patch extracts the foreign key reference expansion code from TableView.data() into a standalone function that is then called by both TableView.data() and RowView.data().

  <!-- readthedocs-preview datasette start -->
  ----
  :books: Documentation preview :books:: https://datasette--2031.org.readthedocs.build/en/2031/

  <!-- readthedocs-preview datasette end -->

reactions:
  {"url": "https://api.github.com/repos/simonw/datasette/issues/2031/reactions", "total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0}


node_id: I_kwDOBm6k_c5fuP4h
title: datasette errors when foreign key integrity is enabled
state: open
created_at: 2023-03-02T01:27:51Z
updated_at: 2023-03-02T01:31:58Z
author_association: CONTRIBUTOR
type: issue
body:
  By default, [SQLite does not enforce foreign key constraints](https://www.sqlite.org/foreignkeys.html#fk_enable). I typically enable these checks by running:

  ```sql
  PRAGMA foreign_keys = ON;
  ```

  inside of a `prepare_connection` hook.

  If a plugin causes the schema to change (eg datasette-scraper creating a new table, or datasette-edit-schema changing a column), then https://github.com/simonw/datasette/blob/0b4a28691468b5c758df74fa1d72a823813c96bf/datasette/utils/internal_db.py#L71-L77 will fail with:

  ```
  FOREIGN KEY constraint failed
  ```

  This could be resolved by either:
  - deleting from the `tables` column last
  - changing the schema so that the foreign keys have [ON DELETE CASCADE](https://www.sqlite.org/foreignkeys.html#fk_actions)

  Let me know if you'd be open to a PR that addresses this -- since foreign key constraints aren't enabled by default, I guess it's questionable whether this is a bug. I think I can workaround this by inspecting the database parameter in `prepare_connection` and trying not to enable fkey checks on the `_internal` database.

reactions:
  {"url": "https://api.github.com/repos/simonw/datasette/issues/2032/reactions", "total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0}


node_id: I_kwDOBm6k_c5gGbAS
title: `datasette install -r requirements.txt`
state: closed
created_at: 2023-03-06T22:17:17Z
updated_at: 2023-03-06T22:54:52Z
closed_at: 2023-03-06T22:27:34Z
author_association: OWNER
type: issue
state_reason: completed
body:
  Would be useful for cases where you want to install a whole set of plugins in one go, e.g. when running tutorials in GitHub Codespaces.

reactions:
  {"url": "https://api.github.com/repos/simonw/datasette/issues/2033/reactions", "total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0}


node_id: PR_kwDOBm6k_c5LgPS-
title: remove an unused `app` var in cli.py
state: open
created_at: 2023-03-07T18:19:05Z
updated_at: 2023-03-29T20:56:20Z
author_association: FIRST_TIME_CONTRIBUTOR
pull_request: simonw/datasette/pulls/2034
type: pull
body:
  this var `app` isn't actually used? unless init it does some side-effect outside of the event loop, idon't think it's necessary. 

  Feel free to ignore this PR if the deleted line actually does something.

  <!-- readthedocs-preview datasette start -->
  ----
  :books: Documentation preview :books:: https://datasette--2034.org.readthedocs.build/en/2034/

  <!-- readthedocs-preview datasette end -->

reactions:
  {"url": "https://api.github.com/repos/simonw/datasette/issues/2034/reactions", "total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0}


node_id: I_kwDOBm6k_c5gTYQS
title: Potential feature: special support for `?a=1&a=2` on the query page
state: open
created_at: 2023-03-08T18:05:03Z
updated_at: 2023-03-31T16:09:08Z
author_association: OWNER
type: issue
body:
  From a discussion on Discord: https://discord.com/channels/823971286308356157/996877076982415491/1082789517062320138

  The key idea is to make it easier for people to implement `where id in (...)` that's populated from query string arguments.

  What if you could add `?id=11&id=32&id=62` to the URL and have that made available as a list that can be used in the query?

reactions:
  {"url": "https://api.github.com/repos/simonw/datasette/issues/2035/reactions", "total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0}


node_id: I_kwDOBm6k_c5gUBoX
title: `publish cloudrun` reuses image tags, which can lead to very surprising deploy problems
state: closed
created_at: 2023-03-08T20:11:44Z
updated_at: 2023-03-08T20:57:34Z
closed_at: 2023-03-08T20:57:34Z
author_association: OWNER
body:
  See this issue:
  - https://github.com/simonw/datasette.io/issues/141

type: issue
state_reason: completed
reactions:
  {"url": "https://api.github.com/repos/simonw/datasette/issues/2036/reactions", "total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0}


node_id: I_kwDOBm6k_c5gUI1A
title: Test failure: FAILED tests/test_cli.py::test_install_requirements - FileNotFoundError
state: closed
created_at: 2023-03-08T20:30:06Z
updated_at: 2023-03-09T22:33:39Z
closed_at: 2023-03-09T22:33:39Z
author_association: OWNER
type: issue
state_reason: completed
body:
  > FAILED tests/test_cli.py::test_install_requirements - FileNotFoundError: [Errno 2] No such file or directory

  From https://github.com/simonw/datasette/actions/runs/4348548218/jobs/7597208191

  ```
  =================================== FAILURES ===================================
  __________________________ test_install_requirements ___________________________

  run_module = <MagicMock name='run_module' id='139768358191936'>

      @mock.patch("datasette.cli.run_module")
      def test_install_requirements(run_module):
          runner = CliRunner()
  >       with runner.isolated_filesystem():

  /home/runner/work/datasette/datasette/tests/test_cli.py:184: 
  _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
  /opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/contextlib.py:119: in __enter__
      return next(self.gen)
  _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

  self = <click.testing.CliRunner object at 0x7f1e5bfb9490>, temp_dir = None

      @contextlib.contextmanager
      def isolated_filesystem(
          self, temp_dir: t.Optional[t.Union[str, os.PathLike]] = None
      ) -> t.Iterator[str]:
          """A context manager that creates a temporary directory and
          changes the current working directory to it. This isolates tests
          that affect the contents of the CWD to prevent them from
          interfering with each other.
      
          :param temp_dir: Create the temporary directory under this
              directory. If given, the created directory is not removed
              when exiting.
      
          .. versionchanged:: 8.0
              Added the ``temp_dir`` parameter.
          """
  >       cwd = os.getcwd()
  E       FileNotFoundError: [Errno 2] No such file or directory

  /opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/site-packages/click/testing.py:466: FileNotFoundError
  ```
  Not sure why it only affected the "[Calculate test coverage](https://github.com/simonw/datasette/actions/workflows/test-coverage.yml)" one.

reactions:
  {"url": "https://api.github.com/repos/simonw/datasette/issues/2037/reactions", "total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0}


node_id: I_kwDOJHON9s5gV4G2
title: Initial proof of concept with ChatGPT
state: closed
created_at: 2023-03-09T03:44:39Z
updated_at: 2023-03-09T03:51:55Z
closed_at: 2023-03-09T03:51:55Z
author_association: MEMBER
body: I'm using ChatGPT to figure out enough AppleScript to get at my notes data.
type: issue
state_reason: completed
reactions:
  {"url": "https://api.github.com/repos/dogsheep/apple-notes-to-sqlite/issues/1/reactions", "total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0}


node_id: I_kwDOJHON9s5gV563
title: First working version
state: closed
created_at: 2023-03-09T03:53:00Z
updated_at: 2023-03-09T05:10:22Z
closed_at: 2023-03-09T05:10:22Z
author_association: MEMBER
type: issue
state_reason: completed
body:
  It's going to shell out to `osascript` as seen in:
  - #1

  I'm going with that option because https://appscript.sourceforge.io/status.html warns against the other potential methods:

  > Apple eliminated its Mac Automation department in 2016. The future of AppleScript and its related technologies is unclear. Caveat emptor.

  But `osascript` looks pretty stable to me.

reactions:
  {"url": "https://api.github.com/repos/dogsheep/apple-notes-to-sqlite/issues/2/reactions", "total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0}


node_id: I_kwDOJHON9s5gWKR9
title: `apple-notes-to-sqlite --dump` option
state: closed
created_at: 2023-03-09T05:05:49Z
updated_at: 2023-03-09T05:06:14Z
closed_at: 2023-03-09T05:06:14Z
author_association: MEMBER
type: issue
state_reason: completed
body:
  Option that doesn't write to the database at all, it just outputs all the notes to stdout as newline-delimited JSON.

reactions:
  {"url": "https://api.github.com/repos/dogsheep/apple-notes-to-sqlite/issues/3/reactions", "total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0}


node_id: I_kwDOJHON9s5gWMC0
title: Support incremental updates
state: open
created_at: 2023-03-09T05:14:00Z
updated_at: 2023-03-09T18:20:56Z
author_association: MEMBER
type: issue
body:
  Running this script can take several hours against a large notes database.

  Would be neat if it could run against just the notes that have been modified since it last ran. Could pull the max `updated` date and then keep on looping until it finds one modified before then.

  Problem is I don't actually know what order it iterates over the notes in.

reactions:
  {"url": "https://api.github.com/repos/dogsheep/apple-notes-to-sqlite/issues/4/reactions", "total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0}


node_id: I_kwDOJHON9s5gWO4Y
title: Configure full text search
state: open
created_at: 2023-03-09T05:20:46Z
updated_at: 2023-03-09T05:20:46Z
author_association: MEMBER
type: issue
body:
  FTS would be useful.

  Maybe even extract the plain text from the notes to make that index easier to create, rather than creating it against the HTML. Can use the `plaintext` property for that.

reactions:
  {"url": "https://api.github.com/repos/dogsheep/apple-notes-to-sqlite/issues/5/reactions", "total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0}


node_id: I_kwDOJHON9s5gaqk0
title: Character encoding problem
state: open
created_at: 2023-03-09T16:44:34Z
updated_at: 2023-04-14T15:22:09Z
author_association: MEMBER
type: issue
body:
  I ran against a recent note with this in it:

  > Or just "Actions ⚙️ "

  And got back:

  <img width="367" alt="image" src="https://user-images.githubusercontent.com/9599/224092586-e2475d8f-868c-489d-b495-2bfeb1a7db99.png">

  > `Actions ‚öôÔ∏è`

  Pasting that into https://ftfy.vercel.app/?s=Actions+%E2%80%9A%C3%B6%C3%B4%C3%94%E2%88%8F%C3%A8+ gives this:

  ```python
  s = 'Actions â\x80\x9aÃ¶Ã´Ã\x94â\x88\x8fÃ¨'
  s = s.encode('latin-1')
  s = s.decode('utf-8')
  s = s.encode('macroman')
  s = s.decode('utf-8')
  print(s)
  ```
  <img width="816" alt="image" src="https://user-images.githubusercontent.com/9599/224092864-2b796c40-7c68-40b1-ae38-d0c61721b742.png">

reactions:
  {"url": "https://api.github.com/repos/dogsheep/apple-notes-to-sqlite/issues/6/reactions", "total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0}


node_id: I_kwDOJHON9s5gbTV3
title: Folder support
state: closed
created_at: 2023-03-09T18:21:33Z
updated_at: 2023-03-09T20:48:18Z
closed_at: 2023-03-09T20:48:18Z
author_association: MEMBER
body: Notes can live in folders. These relationships should be exported too.
type: issue
state_reason: completed
reactions:
  {"url": "https://api.github.com/repos/dogsheep/apple-notes-to-sqlite/issues/7/reactions", "total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0}


node_id: I_kwDOJHON9s5gbgZN
title: Increase performance using macnotesapp
state: closed
created_at: 2023-03-09T18:51:05Z
updated_at: 2023-03-14T22:00:22Z
closed_at: 2023-03-14T22:00:21Z
author_association: NONE
type: issue
state_reason: completed
body:
  Neat project!  You can probably increase performance using my python interface to Notes, [macnotesapp](https://github.com/RhetTbull/macnotesapp), which uses Scripting Bridge and bulk queries for much better performance than AppleScript.

  Another related project is [PyXA](https://github.com/SKaplanOfficial/PyXA) which uses Scripting Bridge to access Notes (and many other apps) and can return all the notes at once as opposed to calling AppleScript for each note.  

  macnotesapp allows you to access multiple accounts and folders as well.

  ```python
  from macnotesapp import NotesApp

  # NotesApp() provides interface to Notes.app
  notesapp = NotesApp()

  # Get list of notes (Note objects for each note)
  notes = notesapp.notes()
  note = notes[0]
  print(
      note.id,
      note.account,
      note.folder,
      note.name,
      note.body,
      note.plaintext,
      note.password_protected,
  )

  print(note.asdict())

  ```

reactions:
  {"url": "https://api.github.com/repos/dogsheep/apple-notes-to-sqlite/issues/8/reactions", "total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0}


node_id: I_kwDOJHON9s5gb8kq
title: Default to just storing plaintext, store HTML if `--html` is passed
state: open
created_at: 2023-03-09T20:19:06Z
updated_at: 2023-03-09T20:19:06Z
author_association: MEMBER
type: issue
body:
  The full `body` version of the notes can get HUGE, due to embedded images. It turns out for my own purposes I'm usually happy with just the `plaintext` version.

  I'm tempted to say you don't get HTML unless you pass a `--html` option.

reactions:
  {"url": "https://api.github.com/repos/dogsheep/apple-notes-to-sqlite/issues/9/reactions", "total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0}


node_id: I_kwDOJHON9s5gcCWb
title: Include schema in README
state: closed
created_at: 2023-03-09T20:38:59Z
updated_at: 2023-03-09T20:48:18Z
closed_at: 2023-03-09T20:48:18Z
author_association: MEMBER
body: As seen in other tools like https://github.com/simonw/git-history
type: issue
state_reason: completed
reactions:
  {"url": "https://api.github.com/repos/dogsheep/apple-notes-to-sqlite/issues/10/reactions", "total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0}


node_id: I_kwDOJHON9s5gcrYC
title: Implement a SQL view to make it easier to query files in a nested folder
state: open
created_at: 2023-03-09T23:19:28Z
updated_at: 2023-03-09T23:24:01Z
author_association: MEMBER
body: Working with nested data in SQL is tricky, can I make it easier with a view or canned query?
type: issue
reactions:
  {"url": "https://api.github.com/repos/dogsheep/apple-notes-to-sqlite/issues/11/reactions", "total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0}


node_id: I_kwDOBm6k_c5gdIVU
title: Consider a `strict_templates` setting
state: open
created_at: 2023-03-10T02:09:13Z
updated_at: 2023-03-10T02:11:06Z
author_association: OWNER
type: issue
body:
  A setting which turns on Jinja strict mode, so any templates that access undefined variables raise a hard error.

  Prototype here:
  ```diff
  diff --git a/datasette/app.py b/datasette/app.py
  index 40416713..1428a3f0 100644
  --- a/datasette/app.py
  +++ b/datasette/app.py
  @@ -200,6 +200,7 @@ SETTINGS = (
           "Allow display of SQL trace debug information with ?_trace=1",
       ),
       Setting("base_url", "/", "Datasette URLs should use this base path"),
  +    Setting("strict_templates", False, "Raise errors for undefined template variables"),
   )
   _HASH_URLS_REMOVED = "The hash_urls setting has been removed, try the datasette-hashed-urls plugin instead"
   OBSOLETE_SETTINGS = {
  @@ -399,11 +400,14 @@ class Datasette:
                   ),
               ]
           )
  +        env_extras = {}
  +        if self.setting("strict_templates"):
  +            env_extras["undefined"] = StrictUndefined
           self.jinja_env = Environment(
               loader=template_loader,
               autoescape=True,
               enable_async=True,
  -            undefined=StrictUndefined,
  +            **env_extras,
           )
           self.jinja_env.filters["escape_css_string"] = escape_css_string
           self.jinja_env.filters["quote_plus"] = urllib.parse.quote_plus
  ```
  Explored this idea a bit in:
  - #1999

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}


node_id: PR_kwDOCGYnMM5L08O8
title: Add paths for homebrew on Apple silicon
state: closed
created_at: 2023-03-11T22:27:52Z
updated_at: 2023-04-09T01:49:44Z
closed_at: 2023-04-09T01:49:43Z
author_association: CONTRIBUTOR
pull_request: simonw/sqlite-utils/pulls/531
type: pull
body:
  This also passes in the extension path when specified in GIS methods. Wherever we know an extension path, we use `db.init_spatialite(find_spatialite() or load_extension)`.

  <!-- readthedocs-preview sqlite-utils start -->
  ----
  :books: Documentation preview :books:: https://sqlite-utils--531.org.readthedocs.build/en/531/

  <!-- readthedocs-preview sqlite-utils end -->

reactions:
  {"url": "https://api.github.com/repos/simonw/sqlite-utils/issues/531/reactions", "total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0}


node_id: I_kwDOCGYnMM5gkyEW
title: Show more information when JSON can't be imported with sqlite-utils insert
state: closed
created_at: 2023-03-12T06:41:44Z
updated_at: 2023-05-08T20:32:16Z
closed_at: 2023-05-08T20:32:02Z
author_association: NONE
type: issue
state_reason: completed
body:
  I am currently trying to import the [JSON export of my data from Discord](https://support.discord.com/hc/en-us/articles/360004027692-Requesting-a-Copy-of-your-Data), specifically `activity/reporting/events-*.json`

  ```
  sqlite-utils.exe insert test.db reporting events-2023-00000-of-00001.json
    [###################################-]   99%  00:00:00
  Error: Invalid JSON - use --csv for CSV or --tsv for TSV files
  ```

  Please show more information as to *why* this is invalid, if possible.

  I am using version 3.30 with Python 3.10 on Windows 11.

reactions:
  {"url": "https://api.github.com/repos/simonw/sqlite-utils/issues/532/reactions", "total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0}


node_id: I_kwDOBm6k_c5glxut
title: Subtle bug with `--load-extension` and `--static` flags with absolute Windows paths with`C:\`
state: open
created_at: 2023-03-12T21:18:52Z
updated_at: 2023-03-12T21:18:52Z
author_association: CONTRIBUTOR
type: issue
body:
  From the Datasette discord: A user tried running the following command on windows:

  ```
  datasette  --load-extension="C:\spatialite\mod_spatialite-5.0.1-win-x86\mod_spatialite.dll"
  ```
  This failed with `"The specified module could not be found"`, because the entrypoint option introduced in #1789 splits the input differently. Instead of loading the extension found at `"C:\spatialite\mod_spatialite-5.0.1-win-x86\mod_spatialite.dll"`, it instead tried to load the extension at `"C"` with entrypoint `"\spatialite\mod_spatialite-5.0.1-win-x86\mod_spatialite.dll". 

  This is hard because most absolute windows paths have a colon in them, like `C:\foo.txt` or `D:\bar.txt`.  I'd image the `--static` flag is also vulnerable to this type of bug.


  The "solution" is to use a relative path instead, but that doesn't feel that great. 

reactions:
  {"url": "https://api.github.com/repos/simonw/datasette/issues/2039/reactions", "total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0}


node_id: I_kwDOCGYnMM5glx30
title: ReadTheDocs error: not all arguments converted during string formatting
state: closed
created_at: 2023-03-12T21:21:05Z
updated_at: 2023-03-12T21:25:33Z
closed_at: 2023-03-12T21:25:33Z
author_association: OWNER
type: issue
state_reason: completed
body:
  This came up as a failure running tests for:
  - #531

  Traceback on https://readthedocs.org/projects/sqlite-utils/builds/19749348/

  ```
    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
      nodes, messages2 = role_fn(role, rawsource, text, lineno, self)
    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
      title = caption % part
  TypeError: not all arguments converted during string formatting

  Exception occurred:
    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
      title = caption % part
  TypeError: not all arguments converted during string formatting
  ```

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}


node_id: I_kwDOCGYnMM5gt4b2
title: ResourceWarning: unclosed file
state: closed
created_at: 2023-03-14T03:02:18Z
updated_at: 2023-05-08T19:56:29Z
closed_at: 2023-05-08T19:56:29Z
author_association: NONE
type: issue
state_reason: completed
body:
  Issuing either

  ```
  py -Wdefault -m sqlite_utils insert dogs.db dogs dogs0.csv --csv
    [#############-----------------------]   36%
    [####################################]  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'>
    insert_upsert_implementation(
  ResourceWarning: Enable tracemalloc to get the object allocation traceback
  ```
  or
  ```
  set pythonwarnings=default
  sqlite-utils insert dogs.db dogs dogs0.csv --csv
    [#############-----------------------]   36%
    [####################################]  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'>
    insert_upsert_implementation(
  ResourceWarning: Enable tracemalloc to get the object allocation traceback
  ```

  exhibits a ResourceWarning indicating that the CSV file being loaded is not closed.

  sqlite-utils --version
  sqlite-utils, version 3.30
  py --version
  Python 3.11.2
  Windows Version 10.0.19045 Build 19045
  SQLite version 3.41.0 2023-02-21 18:09:37

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}


node_id: I_kwDOBm6k_c5hVse_
title: Remove obsolete table POST code
state: closed
created_at: 2023-03-21T01:01:40Z
updated_at: 2023-03-21T01:17:44Z
closed_at: 2023-03-21T01:17:43Z
author_association: OWNER
type: issue
state_reason: completed
body:
  Spotted this in:
  - #1999

  `POST /db/table` currently executes obsolete code for inserting a row - I replaced that with `/db/table/-/insert` in 
  https://github.com/simonw/datasette/commit/6e788b49edf4f842c0817f006eb9d865778eea5e but forgot to remove the old code.

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}


node_id: I_kwDOBm6k_c5hjMh7
title: Gather feedback on new ?_extra= design
state: open
created_at: 2023-03-22T23:07:43Z
updated_at: 2023-03-22T23:08:19Z
author_association: OWNER
type: issue
body:
  Now that I've landed:
  - #1999

  See also:
  - #262

  I want to get some feedback from people on the design of the new `?_extra=` feature, before freezing it into Datasette 1.0.

  The 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

  If 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

  You can use `?_extra=extras` to see a list of available extras: https://latest.datasette.io/fixtures/sortable.json?_extra=extras

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}


node_id: PR_kwDOBm6k_c5M1izI
title: Bump furo from 2022.12.7 to 2023.3.23
state: closed
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
type: pull
body:
  Bumps [furo](https://github.com/pradyunsg/furo) from 2022.12.7 to 2023.3.23.
  <details>
  <summary>Changelog</summary>
  <p><em>Sourced from <a href="https://github.com/pradyunsg/furo/blob/main/docs/changelog.md">furo's changelog</a>.</em></p>
  <blockquote>
  <h1>Changelog</h1>
  <!-- raw HTML omitted -->
  <h2>2023.03.23 -- Sassy Saffron</h2>
  <ul>
  <li>Regenerate with newer version of sphinx-theme-builder, to fix RECORD hashes.</li>
  <li>Update Python version classifiers.</li>
  <li>Increase the icon size in mobile header.</li>
  <li>Increase admonition title bg opacity.</li>
  <li>Change the default API background to transparent.</li>
  <li>Transition the API background change.</li>
  <li>Remove the &quot;indent&quot; of API entries which have a background.</li>
  <li>Break long inline code literals.</li>
  </ul>
  <h2>2022.12.07 -- Reverent Raspberry</h2>
  <ul>
  <li>✨ Add support for Sphinx 6.</li>
  <li>✨ Improve footnote presentation with docutils 0.18+.</li>
  <li>Drop support for Sphinx 4.</li>
  <li>Improve documentation about what the edit button does.</li>
  <li>Improve handling of empty-flexboxes for better print experience on Chrome.</li>
  <li>Improve styling for inline signatures.</li>
  <li>Replace the <code>meta</code> generator tag with a comment.</li>
  <li>Tweak labels with icons to prevent users selecting icons as text on touch.</li>
  </ul>
  <h2>2022.09.29 -- Quaint Quartz</h2>
  <ul>
  <li>Add ability to set arbitrary URLs for edit button.</li>
  <li>Add support for aligning text in MyST-parser generated tables.</li>
  </ul>
  <h2>2022.09.15 -- Pragmatic Pistachio</h2>
  <ul>
  <li>Add a minimum version constraint on pygments.</li>
  <li>Add an explicit dependency on <code>sass</code>.</li>
  <li>Change right sidebar title from &quot;Contents&quot; to &quot;On this page&quot;.</li>
  <li>Correctly position sidebars on small screens.</li>
  <li>Correctly select only Furo's own <code>svg</code> in related pages <code>nav</code>.</li>
  <li>Make numpy-style documentation headers consistent.</li>
  <li>Retitle the reference section.</li>
  <li>Update npm dependencies.</li>
  </ul>
  <!-- raw HTML omitted -->
  </blockquote>
  <p>... (truncated)</p>
  </details>
  <details>
  <summary>Commits</summary>
  <ul>
  <li><a href="https://github.com/pradyunsg/furo/commit/81139dd37ed2f7634812eed274b3fb03b6a21a60"><code>81139dd</code></a> Prepare release: 2023.03.23</li>
  <li><a href="https://github.com/pradyunsg/furo/commit/dafa73a0bae8e52522f70fcbfcbde55cded954ea"><code>dafa73a</code></a> Update changelog</li>
  <li><a href="https://github.com/pradyunsg/furo/commit/82591efde2925e212d97c861ab881a21e8c18435"><code>82591ef</code></a> Allow all <code>pre</code> tags to have overflows</li>
  <li><a href="https://github.com/pradyunsg/furo/commit/55b32f0dd5ac9a055629a8fbb8914e9c62a8b072"><code>55b32f0</code></a> Update Python version classifiers (<a href="https://redirect.github.com/pradyunsg/furo/issues/626">#626</a>)</li>
  <li><a href="https://github.com/pradyunsg/furo/commit/cd6ecdd5d3292f547ceb0cc175b3acf59831cf34"><code>cd6ecdd</code></a> Update linters</li>
  <li><a href="https://github.com/pradyunsg/furo/commit/82a1cec456d5af4386caa46cd4db3a54950a45f4"><code>82a1cec</code></a> Drop the black pin in blacken-docs</li>
  <li><a href="https://github.com/pradyunsg/furo/commit/483b05c8ba74c59f151f17ecf415a7a984507d25"><code>483b05c</code></a> Increase the icon size in mobile header</li>
  <li><a href="https://github.com/pradyunsg/furo/commit/ab3ca77172738f9b2a000948513ddce09fc3b529"><code>ab3ca77</code></a> Revert &quot;Increase icon sizes (<a href="https://redirect.github.com/pradyunsg/furo/issues/554">#554</a>)&quot;</li>
  <li><a href="https://github.com/pradyunsg/furo/commit/82376d29fd5687a81fd9926b1c464c884919b1ab"><code>82376d2</code></a> Supply encoding. Fixes <a href="https://redirect.github.com/pradyunsg/furo/issues/621">#621</a>. (<a href="https://redirect.github.com/pradyunsg/furo/issues/622">#622</a>)</li>
  <li><a href="https://github.com/pradyunsg/furo/commit/193643fdb6787501195555244f4a9e953ef544bb"><code>193643f</code></a> Increase admonition title bg opacity (<a href="https://redirect.github.com/pradyunsg/furo/issues/555">#555</a>)</li>
  <li>Additional commits viewable in <a href="https://github.com/pradyunsg/furo/compare/2022.12.07...2023.03.23">compare view</a></li>
  </ul>
  </details>
  <br />


  [![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)

  Dependabot 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`.

  [//]: # (dependabot-automerge-start)
  [//]: # (dependabot-automerge-end)

  ---

  <details>
  <summary>Dependabot commands and options</summary>
  <br />

  You can trigger Dependabot actions by commenting on this PR:
  - `@dependabot rebase` will rebase this PR
  - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
  - `@dependabot merge` will merge this PR after your CI passes on it
  - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it
  - `@dependabot cancel merge` will cancel a previously requested merge and block automerging
  - `@dependabot reopen` will reopen this PR if it is closed
  - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
  - `@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)
  - `@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)
  - `@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)


  </details>

  <!-- readthedocs-preview datasette start -->
  ----
  :books: Documentation preview :books:: https://datasette--2043.org.readthedocs.build/en/2043/

  <!-- readthedocs-preview datasette end -->

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}


node_id: PR_kwDOBm6k_c5M29tt
title: Expand labels in row view as well (patch for 0.64.x branch)
state: open
created_at: 2023-03-24T18:44:44Z
updated_at: 2023-03-24T18:44:57Z
author_association: FIRST_TIME_CONTRIBUTOR
pull_request: simonw/datasette/pulls/2044
type: pull
body:
  This is a version of #2031 for the 0.64.x branch.

  <!-- readthedocs-preview datasette start -->
  ----
  :books: Documentation preview :books:: https://datasette--2044.org.readthedocs.build/en/2044/

  <!-- readthedocs-preview datasette end -->

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}


node_id: I_kwDOBm6k_c5hz9_k
title: First column on a view page has no facet option in cog menu
state: open
created_at: 2023-03-26T18:02:47Z
updated_at: 2023-03-26T18:02:48Z
author_association: OWNER
type: issue
body:
  e.g. first column on this page - cog menu has no option to facet.

  https://datasette.io/content/tools

  <img width="531" alt="image" src="https://user-images.githubusercontent.com/9599/227795084-1a36bec3-f274-4381-909d-c691317d803b.png">

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}


node_id: PR_kwDODtX3eM5M66op
title: Add permalink virtual field to items table
state: open
created_at: 2023-03-26T22:22:38Z
updated_at: 2023-03-29T18:38:52Z
author_association: FIRST_TIME_CONTRIBUTOR
pull_request: dogsheep/hacker-news-to-sqlite/pulls/6
type: pull
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:

  ![](https://cdn.zappy.app/faf43661d539ee0fee02c0421de22d65.png)

  I 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.

  I 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.

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}


node_id: PR_kwDOBm6k_c5NEqBO
title: Bump furo from 2022.12.7 to 2023.3.27
state: closed
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
type: pull
body:
  Bumps [furo](https://github.com/pradyunsg/furo) from 2022.12.7 to 2023.3.27.
  <details>
  <summary>Changelog</summary>
  <p><em>Sourced from <a href="https://github.com/pradyunsg/furo/blob/main/docs/changelog.md">furo's changelog</a>.</em></p>
  <blockquote>
  <h1>Changelog</h1>
  <!-- raw HTML omitted -->
  <h2>2023.03.27 -- Tasty Tangerine</h2>
  <ul>
  <li>Regenerate with newer version of sphinx-theme-builder, to fix RECORD hashes.</li>
  <li>Add missing class to Font Awesome examples</li>
  </ul>
  <h2>2023.03.23 -- Sassy Saffron</h2>
  <ul>
  <li>Update Python version classifiers.</li>
  <li>Increase the icon size in mobile header.</li>
  <li>Increase admonition title bg opacity.</li>
  <li>Change the default API background to transparent.</li>
  <li>Transition the API background change.</li>
  <li>Remove the &quot;indent&quot; of API entries which have a background.</li>
  <li>Break long inline code literals.</li>
  </ul>
  <h2>2022.12.07 -- Reverent Raspberry</h2>
  <ul>
  <li>✨ Add support for Sphinx 6.</li>
  <li>✨ Improve footnote presentation with docutils 0.18+.</li>
  <li>Drop support for Sphinx 4.</li>
  <li>Improve documentation about what the edit button does.</li>
  <li>Improve handling of empty-flexboxes for better print experience on Chrome.</li>
  <li>Improve styling for inline signatures.</li>
  <li>Replace the <code>meta</code> generator tag with a comment.</li>
  <li>Tweak labels with icons to prevent users selecting icons as text on touch.</li>
  </ul>
  <h2>2022.09.29 -- Quaint Quartz</h2>
  <ul>
  <li>Add ability to set arbitrary URLs for edit button.</li>
  <li>Add support for aligning text in MyST-parser generated tables.</li>
  </ul>
  <h2>2022.09.15 -- Pragmatic Pistachio</h2>
  <ul>
  <li>Add a minimum version constraint on pygments.</li>
  <li>Add an explicit dependency on <code>sass</code>.</li>
  <li>Change right sidebar title from &quot;Contents&quot; to &quot;On this page&quot;.</li>
  <li>Correctly position sidebars on small screens.</li>
  </ul>
  <!-- raw HTML omitted -->
  </blockquote>
  <p>... (truncated)</p>
  </details>
  <details>
  <summary>Commits</summary>
  <ul>
  <li><a href="https://github.com/pradyunsg/furo/commit/2f61e10319413adf533488bf4770df391e8a1b53"><code>2f61e10</code></a> Prepare release: 2023.03.27</li>
  <li><a href="https://github.com/pradyunsg/furo/commit/5c7aedd107ad8005c85ac7803ca13870408b3c46"><code>5c7aedd</code></a> Update changelog</li>
  <li><a href="https://github.com/pradyunsg/furo/commit/05350110cf02d033ebb57147eb54e9371a63545a"><code>0535011</code></a> Add missing class to Font Awesome examples (<a href="https://redirect.github.com/pradyunsg/furo/issues/629">#629</a>)</li>
  <li><a href="https://github.com/pradyunsg/furo/commit/811f1e7e7445e93f6210754db444a58b51741476"><code>811f1e7</code></a> Remove unused <code>templates_path</code> (<a href="https://redirect.github.com/pradyunsg/furo/issues/627">#627</a>)</li>
  <li><a href="https://github.com/pradyunsg/furo/commit/961d4e9ff2ef15015dc65b1fa095b4fbbc295387"><code>961d4e9</code></a> Add a inline-code as an example heading</li>
  <li><a href="https://github.com/pradyunsg/furo/commit/48af8eb8e7f53ec68ae9a623cf72f31a2ef1bb51"><code>48af8eb</code></a> Back to development</li>
  <li><a href="https://github.com/pradyunsg/furo/commit/81139dd37ed2f7634812eed274b3fb03b6a21a60"><code>81139dd</code></a> Prepare release: 2023.03.23</li>
  <li><a href="https://github.com/pradyunsg/furo/commit/dafa73a0bae8e52522f70fcbfcbde55cded954ea"><code>dafa73a</code></a> Update changelog</li>
  <li><a href="https://github.com/pradyunsg/furo/commit/82591efde2925e212d97c861ab881a21e8c18435"><code>82591ef</code></a> Allow all <code>pre</code> tags to have overflows</li>
  <li><a href="https://github.com/pradyunsg/furo/commit/55b32f0dd5ac9a055629a8fbb8914e9c62a8b072"><code>55b32f0</code></a> Update Python version classifiers (<a href="https://redirect.github.com/pradyunsg/furo/issues/626">#626</a>)</li>
  <li>Additional commits viewable in <a href="https://github.com/pradyunsg/furo/compare/2022.12.07...2023.03.27">compare view</a></li>
  </ul>
  </details>
  <br />


  [![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)

  Dependabot 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`.

  [//]: # (dependabot-automerge-start)
  [//]: # (dependabot-automerge-end)

  ---

  <details>
  <summary>Dependabot commands and options</summary>
  <br />

  You can trigger Dependabot actions by commenting on this PR:
  - `@dependabot rebase` will rebase this PR
  - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
  - `@dependabot merge` will merge this PR after your CI passes on it
  - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it
  - `@dependabot cancel merge` will cancel a previously requested merge and block automerging
  - `@dependabot reopen` will reopen this PR if it is closed
  - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
  - `@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)
  - `@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)
  - `@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)


  </details>

  <!-- readthedocs-preview datasette start -->
  ----
  :books: Documentation preview :books:: https://datasette--2046.org.readthedocs.build/en/2046/

  <!-- readthedocs-preview datasette end -->

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}


node_id: PR_kwDOBm6k_c5NIQri
title: Bump black from 22.12.0 to 23.3.0
state: closed
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
type: pull
body:
  Bumps [black](https://github.com/psf/black) from 22.12.0 to 23.3.0.
  <details>
  <summary>Release notes</summary>
  <p><em>Sourced from <a href="https://github.com/psf/black/releases">black's releases</a>.</em></p>
  <blockquote>
  <h2>23.3.0</h2>
  <h3>Highlights</h3>
  <p>This release fixes a longstanding confusing behavior in Black's GitHub action, where the
  version of the action did not determine the version of Black being run (issue <a href="https://redirect.github.com/psf/black/issues/3382">#3382</a>). In
  addition, there is a small bug fix around imports and a number of improvements to the
  preview style.</p>
  <p>Please try out the
  <a href="https://black.readthedocs.io/en/stable/the_black_code_style/future_style.html#preview-style">preview style</a>
  with <code>black --preview</code> and tell us your feedback. All changes in the preview style are
  expected to become part of Black's stable style in January 2024.</p>
  <h3>Stable style</h3>
  <ul>
  <li>Import lines with <code># fmt: skip</code> and <code># fmt: off</code> no longer have an extra blank line
  added when they are right after another import line (<a href="https://redirect.github.com/psf/black/issues/3610">#3610</a>)</li>
  </ul>
  <h3>Preview style</h3>
  <ul>
  <li>Add trailing commas to collection literals even if there's a comment after the last
  entry (<a href="https://redirect.github.com/psf/black/issues/3393">#3393</a>)</li>
  <li><code>async def</code>, <code>async for</code>, and <code>async with</code> statements are now formatted consistently
  compared to their non-async version. (<a href="https://redirect.github.com/psf/black/issues/3609">#3609</a>)</li>
  <li><code>with</code> statements that contain two context managers will be consistently wrapped in
  parentheses (<a href="https://redirect.github.com/psf/black/issues/3589">#3589</a>)</li>
  <li>Let string splitters respect <a href="https://www.unicode.org/reports/tr11/">East Asian Width</a>
  (<a href="https://redirect.github.com/psf/black/issues/3445">#3445</a>)</li>
  <li>Now long string literals can be split after East Asian commas and periods (<code>、</code> U+3001
  IDEOGRAPHIC COMMA, <code>。</code> U+3002 IDEOGRAPHIC FULL STOP, &amp; <code>，</code> U+FF0C FULLWIDTH COMMA)
  besides before spaces (<a href="https://redirect.github.com/psf/black/issues/3445">#3445</a>)</li>
  <li>For stubs, enforce one blank line after a nested class with a body other than just
  <code>...</code> (<a href="https://redirect.github.com/psf/black/issues/3564">#3564</a>)</li>
  <li>Improve handling of multiline strings by changing line split behavior (<a href="https://redirect.github.com/psf/black/issues/1879">#1879</a>)</li>
  </ul>
  <h3>Parser</h3>
  <ul>
  <li>Added support for formatting files with invalid type comments (<a href="https://redirect.github.com/psf/black/issues/3594">#3594</a>)</li>
  </ul>
  <h3>Integrations</h3>
  <ul>
  <li>Update GitHub Action to use the version of Black equivalent to action's version if
  version input is not specified (<a href="https://redirect.github.com/psf/black/issues/3543">#3543</a>)</li>
  <li>Fix missing Python binary path in autoload script for vim (<a href="https://redirect.github.com/psf/black/issues/3508">#3508</a>)</li>
  </ul>
  <h3>Documentation</h3>
  <ul>
  <li>Document that only the most recent release is supported for security issues;
  vulnerabilities should be reported through Tidelift (<a href="https://redirect.github.com/psf/black/issues/3612">#3612</a>)</li>
  </ul>
  <!-- raw HTML omitted -->
  </blockquote>
  <p>... (truncated)</p>
  </details>
  <details>
  <summary>Changelog</summary>
  <p><em>Sourced from <a href="https://github.com/psf/black/blob/main/CHANGES.md">black's changelog</a>.</em></p>
  <blockquote>
  <h2>23.3.0</h2>
  <h3>Highlights</h3>
  <p>This release fixes a longstanding confusing behavior in Black's GitHub action, where the
  version of the action did not determine the version of Black being run (issue <a href="https://redirect.github.com/psf/black/issues/3382">#3382</a>). In
  addition, there is a small bug fix around imports and a number of improvements to the
  preview style.</p>
  <p>Please try out the
  <a href="https://black.readthedocs.io/en/stable/the_black_code_style/future_style.html#preview-style">preview style</a>
  with <code>black --preview</code> and tell us your feedback. All changes in the preview style are
  expected to become part of Black's stable style in January 2024.</p>
  <h3>Stable style</h3>
  <ul>
  <li>Import lines with <code># fmt: skip</code> and <code># fmt: off</code> no longer have an extra blank line
  added when they are right after another import line (<a href="https://redirect.github.com/psf/black/issues/3610">#3610</a>)</li>
  </ul>
  <h3>Preview style</h3>
  <ul>
  <li>Add trailing commas to collection literals even if there's a comment after the last
  entry (<a href="https://redirect.github.com/psf/black/issues/3393">#3393</a>)</li>
  <li><code>async def</code>, <code>async for</code>, and <code>async with</code> statements are now formatted consistently
  compared to their non-async version. (<a href="https://redirect.github.com/psf/black/issues/3609">#3609</a>)</li>
  <li><code>with</code> statements that contain two context managers will be consistently wrapped in
  parentheses (<a href="https://redirect.github.com/psf/black/issues/3589">#3589</a>)</li>
  <li>Let string splitters respect <a href="https://www.unicode.org/reports/tr11/">East Asian Width</a>
  (<a href="https://redirect.github.com/psf/black/issues/3445">#3445</a>)</li>
  <li>Now long string literals can be split after East Asian commas and periods (<code>、</code> U+3001
  IDEOGRAPHIC COMMA, <code>。</code> U+3002 IDEOGRAPHIC FULL STOP, &amp; <code>，</code> U+FF0C FULLWIDTH COMMA)
  besides before spaces (<a href="https://redirect.github.com/psf/black/issues/3445">#3445</a>)</li>
  <li>For stubs, enforce one blank line after a nested class with a body other than just
  <code>...</code> (<a href="https://redirect.github.com/psf/black/issues/3564">#3564</a>)</li>
  <li>Improve handling of multiline strings by changing line split behavior (<a href="https://redirect.github.com/psf/black/issues/1879">#1879</a>)</li>
  </ul>
  <h3>Parser</h3>
  <ul>
  <li>Added support for formatting files with invalid type comments (<a href="https://redirect.github.com/psf/black/issues/3594">#3594</a>)</li>
  </ul>
  <h3>Integrations</h3>
  <ul>
  <li>Update GitHub Action to use the version of Black equivalent to action's version if
  version input is not specified (<a href="https://redirect.github.com/psf/black/issues/3543">#3543</a>)</li>
  <li>Fix missing Python binary path in autoload script for vim (<a href="https://redirect.github.com/psf/black/issues/3508">#3508</a>)</li>
  </ul>
  <h3>Documentation</h3>
  <ul>
  <li>Document that only the most recent release is supported for security issues;
  vulnerabilities should be reported through Tidelift (<a href="https://redirect.github.com/psf/black/issues/3612">#3612</a>)</li>
  </ul>
  <!-- raw HTML omitted -->
  </blockquote>
  <p>... (truncated)</p>
  </details>
  <details>
  <summary>Commits</summary>
  <ul>
  <li><a href="https://github.com/psf/black/commit/bf7a16254ec96b084a6caf3d435ec18f0f245cc7"><code>bf7a162</code></a> Fixup the changelog (<a href="https://redirect.github.com/psf/black/issues/3628">#3628</a>)</li>
  <li><a href="https://github.com/psf/black/commit/9b2b048692f0bd642f38230b4e61c778a4653f91"><code>9b2b048</code></a> Prepare release 23.3.0 (<a href="https://redirect.github.com/psf/black/issues/3625">#3625</a>)</li>
  <li><a href="https://github.com/psf/black/commit/bf5abdb0b6cf6644628977230736a0a6478c1bff"><code>bf5abdb</code></a> Specify Python exec path with minor version if available (<a href="https://redirect.github.com/psf/black/issues/3508">#3508</a>)</li>
  <li><a href="https://github.com/psf/black/commit/b542f589a5c4041f54847591104cd51684849f2e"><code>b542f58</code></a> Use GH action version when version argument not specified (<a href="https://redirect.github.com/psf/black/issues/3543">#3543</a>)</li>
  <li><a href="https://github.com/psf/black/commit/f3b1a3b9d2fc6de8f0845399cb80d8bdfd6400fd"><code>f3b1a3b</code></a> Bump furo from 2022.12.7 to 2023.3.23 in /docs (<a href="https://redirect.github.com/psf/black/issues/3624">#3624</a>)</li>
  <li><a href="https://github.com/psf/black/commit/ef6e079901d53a42dfae4ab10b081ce7a73a47b5"><code>ef6e079</code></a> Let string splitters respect <code>East_Asian_Width</code> property (<a href="https://redirect.github.com/psf/black/issues/3445">#3445</a>)</li>
  <li><a href="https://github.com/psf/black/commit/5c064a986c388e2be1e448c3e4b28e5f5ba7ce5a"><code>5c064a9</code></a> Bump sphinx from 5.3.0 to 6.1.3 in /docs (<a href="https://redirect.github.com/psf/black/issues/3499">#3499</a>)</li>
  <li><a href="https://github.com/psf/black/commit/3a9d6f0a5f9013b97676f3d24246bd34d93fce4c"><code>3a9d6f0</code></a> Bump myst-parser from 0.18.1 to 1.0.0 in /docs (<a href="https://redirect.github.com/psf/black/issues/3601">#3601</a>)</li>
  <li><a href="https://github.com/psf/black/commit/53c23e62df9b182edf9e7ccf726acdcf8c25846f"><code>53c23e6</code></a> Support files with type comment syntax errors (<a href="https://redirect.github.com/psf/black/issues/3594">#3594</a>)</li>
  <li><a href="https://github.com/psf/black/commit/dba3c2695c59fdb11825dbdf8f3b0ab6e0b368b2"><code>dba3c26</code></a> Fix bug introduced in <a href="https://redirect.github.com/psf/black/issues/3564">#3564</a>. (<a href="https://redirect.github.com/psf/black/issues/3615">#3615</a>)</li>
  <li>Additional commits viewable in <a href="https://github.com/psf/black/compare/22.12.0...23.3.0">compare view</a></li>
  </ul>
  </details>
  <br />


  [![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)

  Dependabot 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`.

  [//]: # (dependabot-automerge-start)
  [//]: # (dependabot-automerge-end)

  ---

  <details>
  <summary>Dependabot commands and options</summary>
  <br />

  You can trigger Dependabot actions by commenting on this PR:
  - `@dependabot rebase` will rebase this PR
  - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
  - `@dependabot merge` will merge this PR after your CI passes on it
  - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it
  - `@dependabot cancel merge` will cancel a previously requested merge and block automerging
  - `@dependabot reopen` will reopen this PR if it is closed
  - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
  - `@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)
  - `@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)
  - `@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)


  </details>

  <!-- readthedocs-preview datasette start -->
  ----
  :books: Documentation preview :books:: https://datasette--2047.org.readthedocs.build/en/2047/

  <!-- readthedocs-preview datasette end -->

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}


node_id: I_kwDOBm6k_c5iHQK9
title: Test failures encountered while packaging for GNU Guix
state: open
created_at: 2023-03-29T15:36:54Z
updated_at: 2023-03-29T15:36:54Z
author_association: NONE
type: issue
body:
  Hello,

  While reviewing a packaged submitted to Guix to add `datasette`, the test suite produces the following errors:
  ```
  =================================== FAILURES ===================================
  _________________________ test_row_strange_table_name __________________________
  [gw21] linux -- Python 3.9.9 /gnu/store/slsh0qjv5j68xda2bb6h8gsxwyi1j25a-python-wrapper-3.9.9/bin/python

  app_client = <datasette.utils.testing.TestClient object at 0x7fffef099be0>

      def test_row_strange_table_name(app_client):
          response = app_client.get(
              "/fixtures/table~2Fwith~2Fslashes~2Ecsv/3.json?_shape=objects"
          )
  >       assert response.status == 200
  E       assert 400 == 200
  E        +  where 400 = <datasette.utils.testing.TestResponse object at 0x7fffef236a30>.status

  /tmp/guix-build-datasette-0.64.2.drv-0/source/tests/test_api.py:701: AssertionError
  ----------------------------- Captured stderr call -----------------------------
  ERROR: conn=<sqlite3.Connection object at 0x7fffeedfe5d0>, sql = 'select rowid, * from [table%7E2Fwith%7E2Fslashes%7E2Ecsv] where "rowid"=:p0', params = {'p0': '3'}: no such table: table%7E2Fwith%7E2Fslashes%7E2Ecsv
  _______________ test_database_page_for_database_with_dot_in_name _______________
  [gw15] linux -- Python 3.9.9 /gnu/store/slsh0qjv5j68xda2bb6h8gsxwyi1j25a-python-wrapper-3.9.9/bin/python

  app_client_with_dot = <datasette.utils.testing.TestClient object at 0x7fffef3416a0>

      def test_database_page_for_database_with_dot_in_name(app_client_with_dot):
          response = app_client_with_dot.get("/fixtures~2Edot.json")
  >       assert response.status == 200
  E       assert 302 == 200
  E        +  where 302 = <datasette.utils.testing.TestResponse object at 0x7fffef089fa0>.status

  /tmp/guix-build-datasette-0.64.2.drv-0/source/tests/test_api.py:633: AssertionError
  ___________________ test_tilde_encoded_database_names[fo%o] ____________________
  [gw6] linux -- Python 3.9.9 /gnu/store/slsh0qjv5j68xda2bb6h8gsxwyi1j25a-python-wrapper-3.9.9/bin/python

  db_name = 'fo%o'

      @pytest.mark.asyncio
      @pytest.mark.parametrize("db_name", ("foo", r"fo%o", "f~/c.d"))
      async def test_tilde_encoded_database_names(db_name):
          ds = Datasette()
          ds.add_memory_database(db_name)
          response = await ds.client.get("/.json")
          assert db_name in response.json().keys()
          path = response.json()[db_name]["path"]
          # And the JSON for that database
          response2 = await ds.client.get(path + ".json")
  >       assert response2.status_code == 200
  E       assert 302 == 200
  E        +  where 302 = <Response [302 Found]>.status_code

  /tmp/guix-build-datasette-0.64.2.drv-0/source/tests/test_api.py:983: AssertionError
  __________________ test_tilde_encoded_database_names[f~/c.d] ___________________
  [gw7] linux -- Python 3.9.9 /gnu/store/slsh0qjv5j68xda2bb6h8gsxwyi1j25a-python-wrapper-3.9.9/bin/python

  db_name = 'f~/c.d'

      @pytest.mark.asyncio
      @pytest.mark.parametrize("db_name", ("foo", r"fo%o", "f~/c.d"))
      async def test_tilde_encoded_database_names(db_name):
          ds = Datasette()
          ds.add_memory_database(db_name)
          response = await ds.client.get("/.json")
          assert db_name in response.json().keys()
          path = response.json()[db_name]["path"]
          # And the JSON for that database
          response2 = await ds.client.get(path + ".json")
  >       assert response2.status_code == 200
  E       assert 302 == 200
  E        +  where 302 = <Response [302 Found]>.status_code

  /tmp/guix-build-datasette-0.64.2.drv-0/source/tests/test_api.py:983: AssertionError
  ______________ test_database_with_space_in_name[/searchable.json] ______________
  [gw21] linux -- Python 3.9.9 /gnu/store/slsh0qjv5j68xda2bb6h8gsxwyi1j25a-python-wrapper-3.9.9/bin/python

  app_client_two_attached_databases = <datasette.utils.testing.TestClient object at 0x7fffef11d730>
  path = '/searchable.json'

      @pytest.mark.parametrize(
          "path",
          (
              "/",
              ".json",
              "/searchable",
              "/searchable.json",
              "/searchable_view",
              "/searchable_view.json",
          ),
      )
      def test_database_with_space_in_name(app_client_two_attached_databases, path):
  >       response = app_client_two_attached_databases.get(
              "/extra~20database" + path, follow_redirects=True
          )

  /tmp/guix-build-datasette-0.64.2.drv-0/source/tests/test_api.py:920: 
  _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
  /gnu/store/mcclmphjgbrgpa0v037a4nlq336482g8-python-asgiref-3.4.1/lib/python3.9/site-packages/asgiref/sync.py:223: in __call__
      return call_result.result()
  /gnu/store/65i3nhcwmz0p8rqbg48gaavyky4g4hwk-python-3.9.9/lib/python3.9/concurrent/futures/_base.py:438: in result
      return self.__get_result()
  /gnu/store/65i3nhcwmz0p8rqbg48gaavyky4g4hwk-python-3.9.9/lib/python3.9/concurrent/futures/_base.py:390: in __get_result
      raise self._exception
  /gnu/store/mcclmphjgbrgpa0v037a4nlq336482g8-python-asgiref-3.4.1/lib/python3.9/site-packages/asgiref/sync.py:292: in main_wrap
      result = await self.awaitable(*args, **kwargs)
  /tmp/guix-build-datasette-0.64.2.drv-0/source/datasette/utils/testing.py:66: in get
      return await self._request(
  /tmp/guix-build-datasette-0.64.2.drv-0/source/datasette/utils/testing.py:156: in _request
      httpx_response = await self.ds.client.request(
  /tmp/guix-build-datasette-0.64.2.drv-0/source/datasette/app.py:1602: in request
      return await client.request(
  /gnu/store/bj5lb299rfb4cbbq5kczq9imdk9a7y64-python-httpx-0.23.0/lib/python3.9/site-packages/httpx/_client.py:1527: in request
      return await self.send(request, auth=auth, follow_redirects=follow_redirects)
  /gnu/store/bj5lb299rfb4cbbq5kczq9imdk9a7y64-python-httpx-0.23.0/lib/python3.9/site-packages/httpx/_client.py:1614: in send
      response = await self._send_handling_auth(
  /gnu/store/bj5lb299rfb4cbbq5kczq9imdk9a7y64-python-httpx-0.23.0/lib/python3.9/site-packages/httpx/_client.py:1642: in _send_handling_auth
      response = await self._send_handling_redirects(
  _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

  self = <httpx.AsyncClient object at 0x7fffef11d940>
  request = <Request('GET', 'http://localhost/extra%7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E20database/searchable%7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E2Ejson')>
  follow_redirects = True
  history = [<Response [302 Found]>, <Response [302 Found]>, <Response [302 Found]>, <Response [302 Found]>, <Response [302 Found]>, <Response [302 Found]>, ...]

      async def _send_handling_redirects(
          self,
          request: Request,
          follow_redirects: bool,
          history: typing.List[Response],
      ) -> Response:
          while True:
              if len(history) > self.max_redirects:
  >               raise TooManyRedirects(
                      "Exceeded maximum allowed redirects.", request=request
                  )
  E               httpx.TooManyRedirects: Exceeded maximum allowed redirects.

  /gnu/store/bj5lb299rfb4cbbq5kczq9imdk9a7y64-python-httpx-0.23.0/lib/python3.9/site-packages/httpx/_client.py:1672: TooManyRedirects
  ___________________ test_database_with_space_in_name[.json] ____________________
  [gw19] linux -- Python 3.9.9 /gnu/store/slsh0qjv5j68xda2bb6h8gsxwyi1j25a-python-wrapper-3.9.9/bin/python

  app_client_two_attached_databases = <datasette.utils.testing.TestClient object at 0x7fffef085a90>
  path = '.json'

      @pytest.mark.parametrize(
          "path",
          (
              "/",
              ".json",
              "/searchable",
              "/searchable.json",
              "/searchable_view",
              "/searchable_view.json",
          ),
      )
      def test_database_with_space_in_name(app_client_two_attached_databases, path):
  >       response = app_client_two_attached_databases.get(
              "/extra~20database" + path, follow_redirects=True
          )

  /tmp/guix-build-datasette-0.64.2.drv-0/source/tests/test_api.py:920: 
  _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
  /gnu/store/mcclmphjgbrgpa0v037a4nlq336482g8-python-asgiref-3.4.1/lib/python3.9/site-packages/asgiref/sync.py:223: in __call__
      return call_result.result()
  /gnu/store/65i3nhcwmz0p8rqbg48gaavyky4g4hwk-python-3.9.9/lib/python3.9/concurrent/futures/_base.py:438: in result
      return self.__get_result()
  /gnu/store/65i3nhcwmz0p8rqbg48gaavyky4g4hwk-python-3.9.9/lib/python3.9/concurrent/futures/_base.py:390: in __get_result
      raise self._exception
  /gnu/store/mcclmphjgbrgpa0v037a4nlq336482g8-python-asgiref-3.4.1/lib/python3.9/site-packages/asgiref/sync.py:292: in main_wrap
      result = await self.awaitable(*args, **kwargs)
  /tmp/guix-build-datasette-0.64.2.drv-0/source/datasette/utils/testing.py:66: in get
      return await self._request(
  /tmp/guix-build-datasette-0.64.2.drv-0/source/datasette/utils/testing.py:156: in _request
      httpx_response = await self.ds.client.request(
  /tmp/guix-build-datasette-0.64.2.drv-0/source/datasette/app.py:1602: in request
      return await client.request(
  /gnu/store/bj5lb299rfb4cbbq5kczq9imdk9a7y64-python-httpx-0.23.0/lib/python3.9/site-packages/httpx/_client.py:1527: in request
      return await self.send(request, auth=auth, follow_redirects=follow_redirects)
  /gnu/store/bj5lb299rfb4cbbq5kczq9imdk9a7y64-python-httpx-0.23.0/lib/python3.9/site-packages/httpx/_client.py:1614: in send
      response = await self._send_handling_auth(
  /gnu/store/bj5lb299rfb4cbbq5kczq9imdk9a7y64-python-httpx-0.23.0/lib/python3.9/site-packages/httpx/_client.py:1642: in _send_handling_auth
      response = await self._send_handling_redirects(
  _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

  self = <httpx.AsyncClient object at 0x7fffecd99ca0>
  request = <Request('GET', 'http://localhost/extra%7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E20database%7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E2Ejson')>
  follow_redirects = True
  history = [<Response [302 Found]>, <Response [302 Found]>, <Response [302 Found]>, <Response [302 Found]>, <Response [302 Found]>, <Response [302 Found]>, ...]

      async def _send_handling_redirects(
          self,
          request: Request,
          follow_redirects: bool,
          history: typing.List[Response],
      ) -> Response:
          while True:
              if len(history) > self.max_redirects:
  >               raise TooManyRedirects(
                      "Exceeded maximum allowed redirects.", request=request
                  )
  E               httpx.TooManyRedirects: Exceeded maximum allowed redirects.

  /gnu/store/bj5lb299rfb4cbbq5kczq9imdk9a7y64-python-httpx-0.23.0/lib/python3.9/site-packages/httpx/_client.py:1672: TooManyRedirects
  ______________ test_database_with_space_in_name[/searchable_view] ______________
  [gw22] linux -- Python 3.9.9 /gnu/store/slsh0qjv5j68xda2bb6h8gsxwyi1j25a-python-wrapper-3.9.9/bin/python

  app_client_two_attached_databases = <datasette.utils.testing.TestClient object at 0x7fffeeab4c70>
  path = '/searchable_view'

      @pytest.mark.parametrize(
          "path",
          (
              "/",
              ".json",
              "/searchable",
              "/searchable.json",
              "/searchable_view",
              "/searchable_view.json",
          ),
      )
      def test_database_with_space_in_name(app_client_two_attached_databases, path):
  >       response = app_client_two_attached_databases.get(
              "/extra~20database" + path, follow_redirects=True
          )

  /tmp/guix-build-datasette-0.64.2.drv-0/source/tests/test_api.py:920: 
  _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
  /gnu/store/mcclmphjgbrgpa0v037a4nlq336482g8-python-asgiref-3.4.1/lib/python3.9/site-packages/asgiref/sync.py:223: in __call__
      return call_result.result()
  /gnu/store/65i3nhcwmz0p8rqbg48gaavyky4g4hwk-python-3.9.9/lib/python3.9/concurrent/futures/_base.py:438: in result
      return self.__get_result()
  /gnu/store/65i3nhcwmz0p8rqbg48gaavyky4g4hwk-python-3.9.9/lib/python3.9/concurrent/futures/_base.py:390: in __get_result
      raise self._exception
  /gnu/store/mcclmphjgbrgpa0v037a4nlq336482g8-python-asgiref-3.4.1/lib/python3.9/site-packages/asgiref/sync.py:292: in main_wrap
      result = await self.awaitable(*args, **kwargs)
  /tmp/guix-build-datasette-0.64.2.drv-0/source/datasette/utils/testing.py:66: in get
      return await self._request(
  /tmp/guix-build-datasette-0.64.2.drv-0/source/datasette/utils/testing.py:156: in _request
      httpx_response = await self.ds.client.request(
  /tmp/guix-build-datasette-0.64.2.drv-0/source/datasette/app.py:1602: in request
      return await client.request(
  /gnu/store/bj5lb299rfb4cbbq5kczq9imdk9a7y64-python-httpx-0.23.0/lib/python3.9/site-packages/httpx/_client.py:1527: in request
      return await self.send(request, auth=auth, follow_redirects=follow_redirects)
  /gnu/store/bj5lb299rfb4cbbq5kczq9imdk9a7y64-python-httpx-0.23.0/lib/python3.9/site-packages/httpx/_client.py:1614: in send
      response = await self._send_handling_auth(
  /gnu/store/bj5lb299rfb4cbbq5kczq9imdk9a7y64-python-httpx-0.23.0/lib/python3.9/site-packages/httpx/_client.py:1642: in _send_handling_auth
      response = await self._send_handling_redirects(
  _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

  self = <httpx.AsyncClient object at 0x7fffec5b3580>
  request = <Request('GET', 'http://localhost/extra%7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E20database/searchable_view')>
  follow_redirects = True
  history = [<Response [302 Found]>, <Response [302 Found]>, <Response [302 Found]>, <Response [302 Found]>, <Response [302 Found]>, <Response [302 Found]>, ...]

      async def _send_handling_redirects(
          self,
          request: Request,
          follow_redirects: bool,
          history: typing.List[Response],
      ) -> Response:
          while True:
              if len(history) > self.max_redirects:
  >               raise TooManyRedirects(
                      "Exceeded maximum allowed redirects.", request=request
                  )
  E               httpx.TooManyRedirects: Exceeded maximum allowed redirects.

  /gnu/store/bj5lb299rfb4cbbq5kczq9imdk9a7y64-python-httpx-0.23.0/lib/python3.9/site-packages/httpx/_client.py:1672: TooManyRedirects
  _____________________ test_database_with_space_in_name[/] ______________________
  [gw18] linux -- Python 3.9.9 /gnu/store/slsh0qjv5j68xda2bb6h8gsxwyi1j25a-python-wrapper-3.9.9/bin/python

  app_client_two_attached_databases = <datasette.utils.testing.TestClient object at 0x7fffef085be0>
  path = '/'

      @pytest.mark.parametrize(
          "path",
          (
              "/",
              ".json",
              "/searchable",
              "/searchable.json",
              "/searchable_view",
              "/searchable_view.json",
          ),
      )
      def test_database_with_space_in_name(app_client_two_attached_databases, path):
  >       response = app_client_two_attached_databases.get(
              "/extra~20database" + path, follow_redirects=True
          )

  /tmp/guix-build-datasette-0.64.2.drv-0/source/tests/test_api.py:920: 
  _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
  /gnu/store/mcclmphjgbrgpa0v037a4nlq336482g8-python-asgiref-3.4.1/lib/python3.9/site-packages/asgiref/sync.py:223: in __call__
      return call_result.result()
  /gnu/store/65i3nhcwmz0p8rqbg48gaavyky4g4hwk-python-3.9.9/lib/python3.9/concurrent/futures/_base.py:438: in result
      return self.__get_result()
  /gnu/store/65i3nhcwmz0p8rqbg48gaavyky4g4hwk-python-3.9.9/lib/python3.9/concurrent/futures/_base.py:390: in __get_result
      raise self._exception
  /gnu/store/mcclmphjgbrgpa0v037a4nlq336482g8-python-asgiref-3.4.1/lib/python3.9/site-packages/asgiref/sync.py:292: in main_wrap
      result = await self.awaitable(*args, **kwargs)
  /tmp/guix-build-datasette-0.64.2.drv-0/source/datasette/utils/testing.py:66: in get
      return await self._request(
  /tmp/guix-build-datasette-0.64.2.drv-0/source/datasette/utils/testing.py:156: in _request
      httpx_response = await self.ds.client.request(
  /tmp/guix-build-datasette-0.64.2.drv-0/source/datasette/app.py:1602: in request
      return await client.request(
  /gnu/store/bj5lb299rfb4cbbq5kczq9imdk9a7y64-python-httpx-0.23.0/lib/python3.9/site-packages/httpx/_client.py:1527: in request
      return await self.send(request, auth=auth, follow_redirects=follow_redirects)
  /gnu/store/bj5lb299rfb4cbbq5kczq9imdk9a7y64-python-httpx-0.23.0/lib/python3.9/site-packages/httpx/_client.py:1614: in send
      response = await self._send_handling_auth(
  /gnu/store/bj5lb299rfb4cbbq5kczq9imdk9a7y64-python-httpx-0.23.0/lib/python3.9/site-packages/httpx/_client.py:1642: in _send_handling_auth
      response = await self._send_handling_redirects(
  _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

  self = <httpx.AsyncClient object at 0x7fffec5f1370>
  request = <Request('GET', 'http://localhost/extra%7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E20database/')>
  follow_redirects = True
  history = [<Response [302 Found]>, <Response [302 Found]>, <Response [302 Found]>, <Response [302 Found]>, <Response [302 Found]>, <Response [302 Found]>, ...]

      async def _send_handling_redirects(
          self,
          request: Request,
          follow_redirects: bool,
          history: typing.List[Response],
      ) -> Response:
          while True:
              if len(history) > self.max_redirects:
  >               raise TooManyRedirects(
                      "Exceeded maximum allowed redirects.", request=request
                  )
  E               httpx.TooManyRedirects: Exceeded maximum allowed redirects.

  /gnu/store/bj5lb299rfb4cbbq5kczq9imdk9a7y64-python-httpx-0.23.0/lib/python3.9/site-packages/httpx/_client.py:1672: TooManyRedirects
  ________________ test_database_with_space_in_name[/searchable] _________________
  [gw20] linux -- Python 3.9.9 /gnu/store/slsh0qjv5j68xda2bb6h8gsxwyi1j25a-python-wrapper-3.9.9/bin/python

  app_client_two_attached_databases = <datasette.utils.testing.TestClient object at 0x7fffef099f10>
  path = '/searchable'

      @pytest.mark.parametrize(
          "path",
          (
              "/",
              ".json",
              "/searchable",
              "/searchable.json",
              "/searchable_view",
              "/searchable_view.json",
          ),
      )
      def test_database_with_space_in_name(app_client_two_attached_databases, path):
  >       response = app_client_two_attached_databases.get(
              "/extra~20database" + path, follow_redirects=True
          )

  /tmp/guix-build-datasette-0.64.2.drv-0/source/tests/test_api.py:920: 
  _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
  /gnu/store/mcclmphjgbrgpa0v037a4nlq336482g8-python-asgiref-3.4.1/lib/python3.9/site-packages/asgiref/sync.py:223: in __call__
      return call_result.result()
  /gnu/store/65i3nhcwmz0p8rqbg48gaavyky4g4hwk-python-3.9.9/lib/python3.9/concurrent/futures/_base.py:438: in result
      return self.__get_result()
  /gnu/store/65i3nhcwmz0p8rqbg48gaavyky4g4hwk-python-3.9.9/lib/python3.9/concurrent/futures/_base.py:390: in __get_result
      raise self._exception
  /gnu/store/mcclmphjgbrgpa0v037a4nlq336482g8-python-asgiref-3.4.1/lib/python3.9/site-packages/asgiref/sync.py:292: in main_wrap
      result = await self.awaitable(*args, **kwargs)
  /tmp/guix-build-datasette-0.64.2.drv-0/source/datasette/utils/testing.py:66: in get
      return await self._request(
  /tmp/guix-build-datasette-0.64.2.drv-0/source/datasette/utils/testing.py:156: in _request
      httpx_response = await self.ds.client.request(
  /tmp/guix-build-datasette-0.64.2.drv-0/source/datasette/app.py:1602: in request
      return await client.request(
  /gnu/store/bj5lb299rfb4cbbq5kczq9imdk9a7y64-python-httpx-0.23.0/lib/python3.9/site-packages/httpx/_client.py:1527: in request
      return await self.send(request, auth=auth, follow_redirects=follow_redirects)
  /gnu/store/bj5lb299rfb4cbbq5kczq9imdk9a7y64-python-httpx-0.23.0/lib/python3.9/site-packages/httpx/_client.py:1614: in send
      response = await self._send_handling_auth(
  /gnu/store/bj5lb299rfb4cbbq5kczq9imdk9a7y64-python-httpx-0.23.0/lib/python3.9/site-packages/httpx/_client.py:1642: in _send_handling_auth
      response = await self._send_handling_redirects(
  _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

  self = <httpx.AsyncClient object at 0x7fffecd8c790>
  request = <Request('GET', 'http://localhost/extra%7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E20database/searchable')>
  follow_redirects = True
  history = [<Response [302 Found]>, <Response [302 Found]>, <Response [302 Found]>, <Response [302 Found]>, <Response [302 Found]>, <Response [302 Found]>, ...]

      async def _send_handling_redirects(
          self,
          request: Request,
          follow_redirects: bool,
          history: typing.List[Response],
      ) -> Response:
          while True:
              if len(history) > self.max_redirects:
  >               raise TooManyRedirects(
                      "Exceeded maximum allowed redirects.", request=request
                  )
  E               httpx.TooManyRedirects: Exceeded maximum allowed redirects.

  /gnu/store/bj5lb299rfb4cbbq5kczq9imdk9a7y64-python-httpx-0.23.0/lib/python3.9/site-packages/httpx/_client.py:1672: TooManyRedirects
  ___________ test_database_with_space_in_name[/searchable_view.json] ____________
  [gw23] linux -- Python 3.9.9 /gnu/store/slsh0qjv5j68xda2bb6h8gsxwyi1j25a-python-wrapper-3.9.9/bin/python

  app_client_two_attached_databases = <datasette.utils.testing.TestClient object at 0x7fffef341520>
  path = '/searchable_view.json'

      @pytest.mark.parametrize(
          "path",
          (
              "/",
              ".json",
              "/searchable",
              "/searchable.json",
              "/searchable_view",
              "/searchable_view.json",
          ),
      )
      def test_database_with_space_in_name(app_client_two_attached_databases, path):
  >       response = app_client_two_attached_databases.get(
              "/extra~20database" + path, follow_redirects=True
          )

  /tmp/guix-build-datasette-0.64.2.drv-0/source/tests/test_api.py:920: 
  _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
  /gnu/store/mcclmphjgbrgpa0v037a4nlq336482g8-python-asgiref-3.4.1/lib/python3.9/site-packages/asgiref/sync.py:223: in __call__
      return call_result.result()
  /gnu/store/65i3nhcwmz0p8rqbg48gaavyky4g4hwk-python-3.9.9/lib/python3.9/concurrent/futures/_base.py:438: in result
      return self.__get_result()
  /gnu/store/65i3nhcwmz0p8rqbg48gaavyky4g4hwk-python-3.9.9/lib/python3.9/concurrent/futures/_base.py:390: in __get_result
      raise self._exception
  /gnu/store/mcclmphjgbrgpa0v037a4nlq336482g8-python-asgiref-3.4.1/lib/python3.9/site-packages/asgiref/sync.py:292: in main_wrap
      result = await self.awaitable(*args, **kwargs)
  /tmp/guix-build-datasette-0.64.2.drv-0/source/datasette/utils/testing.py:66: in get
      return await self._request(
  /tmp/guix-build-datasette-0.64.2.drv-0/source/datasette/utils/testing.py:156: in _request
      httpx_response = await self.ds.client.request(
  /tmp/guix-build-datasette-0.64.2.drv-0/source/datasette/app.py:1602: in request
      return await client.request(
  /gnu/store/bj5lb299rfb4cbbq5kczq9imdk9a7y64-python-httpx-0.23.0/lib/python3.9/site-packages/httpx/_client.py:1527: in request
      return await self.send(request, auth=auth, follow_redirects=follow_redirects)
  /gnu/store/bj5lb299rfb4cbbq5kczq9imdk9a7y64-python-httpx-0.23.0/lib/python3.9/site-packages/httpx/_client.py:1614: in send
      response = await self._send_handling_auth(
  /gnu/store/bj5lb299rfb4cbbq5kczq9imdk9a7y64-python-httpx-0.23.0/lib/python3.9/site-packages/httpx/_client.py:1642: in _send_handling_auth
      response = await self._send_handling_redirects(
  _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

  self = <httpx.AsyncClient object at 0x7fffef085460>
  request = <Request('GET', 'http://localhost/extra%7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E20database/searchable_view%7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E2Ejson')>
  follow_redirects = True
  history = [<Response [302 Found]>, <Response [302 Found]>, <Response [302 Found]>, <Response [302 Found]>, <Response [302 Found]>, <Response [302 Found]>, ...]

      async def _send_handling_redirects(
          self,
          request: Request,
          follow_redirects: bool,
          history: typing.List[Response],
      ) -> Response:
          while True:
              if len(history) > self.max_redirects:
  >               raise TooManyRedirects(
                      "Exceeded maximum allowed redirects.", request=request
                  )
  E               httpx.TooManyRedirects: Exceeded maximum allowed redirects.

  /gnu/store/bj5lb299rfb4cbbq5kczq9imdk9a7y64-python-httpx-0.23.0/lib/python3.9/site-packages/httpx/_client.py:1672: TooManyRedirects
  ________________ test_weird_database_names[database (1).sqlite] ________________
  [gw7] linux -- Python 3.9.9 /gnu/store/slsh0qjv5j68xda2bb6h8gsxwyi1j25a-python-wrapper-3.9.9/bin/python

  tmpdir = local('/tmp/guix-build-datasette-0.64.2.drv-0/pytest-of-nixbld/pytest-0/popen-gw7/test_weird_database_names_data0')
  filename = 'database (1).sqlite'

      @pytest.mark.parametrize(
          "filename", ["test-database (1).sqlite", "database (1).sqlite"]
      )
      def test_weird_database_names(tmpdir, filename):
          # https://github.com/simonw/datasette/issues/1181
          runner = CliRunner()
          db_path = str(tmpdir / filename)
          sqlite3.connect(db_path).execute("vacuum")
          result1 = runner.invoke(cli, [db_path, "--get", "/"])
          assert result1.exit_code == 0, result1.output
          filename_no_stem = filename.rsplit(".", 1)[0]
          expected_link = '<a href="/{}">{}</a>'.format(
              tilde_encode(filename_no_stem), filename_no_stem
          )
          assert expected_link in result1.output
          # Now try hitting that database page
          result2 = runner.invoke(
              cli, [db_path, "--get", "/{}".format(tilde_encode(filename_no_stem))]
          )
  >       assert result2.exit_code == 0, result2.output
  E       AssertionError: 
  E         
  E       assert 1 == 0
  E        +  where 1 = <Result SystemExit(1)>.exit_code

  /tmp/guix-build-datasette-0.64.2.drv-0/source/tests/test_cli.py:321: AssertionError
  _____________ test_weird_database_names[test-database (1).sqlite] ______________
  [gw6] linux -- Python 3.9.9 /gnu/store/slsh0qjv5j68xda2bb6h8gsxwyi1j25a-python-wrapper-3.9.9/bin/python

  tmpdir = local('/tmp/guix-build-datasette-0.64.2.drv-0/pytest-of-nixbld/pytest-0/popen-gw6/test_weird_database_names_test0')
  filename = 'test-database (1).sqlite'

      @pytest.mark.parametrize(
          "filename", ["test-database (1).sqlite", "database (1).sqlite"]
      )
      def test_weird_database_names(tmpdir, filename):
          # https://github.com/simonw/datasette/issues/1181
          runner = CliRunner()
          db_path = str(tmpdir / filename)
          sqlite3.connect(db_path).execute("vacuum")
          result1 = runner.invoke(cli, [db_path, "--get", "/"])
          assert result1.exit_code == 0, result1.output
          filename_no_stem = filename.rsplit(".", 1)[0]
          expected_link = '<a href="/{}">{}</a>'.format(
              tilde_encode(filename_no_stem), filename_no_stem
          )
          assert expected_link in result1.output
          # Now try hitting that database page
          result2 = runner.invoke(
              cli, [db_path, "--get", "/{}".format(tilde_encode(filename_no_stem))]
          )
  >       assert result2.exit_code == 0, result2.output
  E       AssertionError: 
  E         
  E       assert 1 == 0
  E        +  where 1 = <Result SystemExit(1)>.exit_code

  /tmp/guix-build-datasette-0.64.2.drv-0/source/tests/test_cli.py:321: AssertionError
  _ test_row_html_compound_primary_key[/fixtures/compound_primary_key/a~2Fb,~2Ec~2Dd-expected1] _
  [gw11] linux -- Python 3.9.9 /gnu/store/slsh0qjv5j68xda2bb6h8gsxwyi1j25a-python-wrapper-3.9.9/bin/python

  app_client = <datasette.utils.testing.TestClient object at 0x7fffec2d37f0>
  path = '/fixtures/compound_primary_key/a~2Fb,~2Ec~2Dd'
  expected = [['<td class="col-pk1 type-str">a/b</td>', '<td class="col-pk2 type-str">.c-d</td>', '<td class="col-content type-str">c</td>']]

      @pytest.mark.parametrize(
          "path,expected",
          (
              (
                  "/fixtures/compound_primary_key/a,b",
                  [
                      [
                          '<td class="col-pk1 type-str">a</td>',
                          '<td class="col-pk2 type-str">b</td>',
                          '<td class="col-content type-str">c</td>',
                      ]
                  ],
              ),
              (
                  "/fixtures/compound_primary_key/a~2Fb,~2Ec~2Dd",
                  [
                      [
                          '<td class="col-pk1 type-str">a/b</td>',
                          '<td class="col-pk2 type-str">.c-d</td>',
                          '<td class="col-content type-str">c</td>',
                      ]
                  ],
              ),
          ),
      )
      def test_row_html_compound_primary_key(app_client, path, expected):
          response = app_client.get(path)
  >       assert response.status == 200
  E       assert 302 == 200
  E        +  where 302 = <datasette.utils.testing.TestResponse object at 0x7fffd47c23a0>.status

  /tmp/guix-build-datasette-0.64.2.drv-0/source/tests/test_html.py:370: AssertionError
  _ test_css_classes_on_body[/fixtures/table~2Fwith~2Fslashes~2Ecsv-expected_classes5] _
  [gw3] linux -- Python 3.9.9 /gnu/store/slsh0qjv5j68xda2bb6h8gsxwyi1j25a-python-wrapper-3.9.9/bin/python

  app_client = <datasette.utils.testing.TestClient object at 0x7fffd4743fa0>
  path = '/fixtures/table~2Fwith~2Fslashes~2Ecsv'
  expected_classes = ['table', 'db-fixtures', 'table-tablewithslashescsv-fa7563']

      @pytest.mark.parametrize(
          "path,expected_classes",
          [
              ("/", ["index"]),
              ("/fixtures", ["db", "db-fixtures"]),
              ("/fixtures?sql=select+1", ["query", "db-fixtures"]),
              (
                  "/fixtures/simple_primary_key",
                  ["table", "db-fixtures", "table-simple_primary_key"],
              ),
              (
                  "/fixtures/neighborhood_search",
                  ["query", "db-fixtures", "query-neighborhood_search"],
              ),
              (
                  "/fixtures/table~2Fwith~2Fslashes~2Ecsv",
                  ["table", "db-fixtures", "table-tablewithslashescsv-fa7563"],
              ),
              (
                  "/fixtures/simple_primary_key/1",
                  ["row", "db-fixtures", "table-simple_primary_key"],
              ),
          ],
      )
      def test_css_classes_on_body(app_client, path, expected_classes):
          response = app_client.get(path)
  >       assert response.status == 200
  E       assert 302 == 200
  E        +  where 302 = <datasette.utils.testing.TestResponse object at 0x7fffd4628dc0>.status

  /tmp/guix-build-datasette-0.64.2.drv-0/source/tests/test_html.py:238: AssertionError
  _ test_templates_considered[/fixtures/table~2Fwith~2Fslashes~2Ecsv-table-fixtures-tablewithslashescsv-fa7563.html, *table.html] _
  [gw3] linux -- Python 3.9.9 /gnu/store/slsh0qjv5j68xda2bb6h8gsxwyi1j25a-python-wrapper-3.9.9/bin/python

  app_client = <datasette.utils.testing.TestClient object at 0x7fffd4743fa0>
  path = '/fixtures/table~2Fwith~2Fslashes~2Ecsv'
  expected_considered = 'table-fixtures-tablewithslashescsv-fa7563.html, *table.html'

      @pytest.mark.parametrize(
          "path,expected_considered",
          [
              ("/", "*index.html"),
              ("/fixtures", "database-fixtures.html, *database.html"),
              (
                  "/fixtures/simple_primary_key",
                  "table-fixtures-simple_primary_key.html, *table.html",
              ),
              (
                  "/fixtures/table~2Fwith~2Fslashes~2Ecsv",
                  "table-fixtures-tablewithslashescsv-fa7563.html, *table.html",
              ),
              (
                  "/fixtures/simple_primary_key/1",
                  "row-fixtures-simple_primary_key.html, *row.html",
              ),
          ],
      )
      def test_templates_considered(app_client, path, expected_considered):
          response = app_client.get(path)
  >       assert response.status == 200
  E       assert 302 == 200
  E        +  where 302 = <datasette.utils.testing.TestResponse object at 0x7fffd44f2d60>.status

  /tmp/guix-build-datasette-0.64.2.drv-0/source/tests/test_html.py:264: AssertionError
  _ test_alternate_url_json[/fixtures/table~2Fwith~2Fslashes~2Ecsv-http://localhost/fixtures/table~2Fwith~2Fslashes~2Ecsv.json] _
  [gw21] linux -- Python 3.9.9 /gnu/store/slsh0qjv5j68xda2bb6h8gsxwyi1j25a-python-wrapper-3.9.9/bin/python

  app_client = <datasette.utils.testing.TestClient object at 0x7fffecd9fac0>
  path = '/fixtures/table~2Fwith~2Fslashes~2Ecsv'
  expected = 'http://localhost/fixtures/table~2Fwith~2Fslashes~2Ecsv.json'

      @pytest.mark.parametrize(
          "path,expected",
          (
              # Instance index page
              ("/", "http://localhost/.json"),
              # Table page
              ("/fixtures/facetable", "http://localhost/fixtures/facetable.json"),
              (
                  "/fixtures/table~2Fwith~2Fslashes~2Ecsv",
                  "http://localhost/fixtures/table~2Fwith~2Fslashes~2Ecsv.json",
              ),
              # Row page
              (
                  "/fixtures/no_primary_key/1",
                  "http://localhost/fixtures/no_primary_key/1.json",
              ),
              # Database index page
              (
                  "/fixtures",
                  "http://localhost/fixtures.json",
              ),
              # Custom query page
              (
                  "/fixtures?sql=select+*+from+facetable",
                  "http://localhost/fixtures.json?sql=select+*+from+facetable",
              ),
              # Canned query page
              (
                  "/fixtures/neighborhood_search?text=town",
                  "http://localhost/fixtures/neighborhood_search.json?text=town",
              ),
              # /-/ pages
              (
                  "/-/plugins",
                  "http://localhost/-/plugins.json",
              ),
          ),
      )
      def test_alternate_url_json(app_client, path, expected):
          response = app_client.get(path)
  >       assert response.status == 200
  E       assert 302 == 200
  E        +  where 302 = <datasette.utils.testing.TestResponse object at 0x7fffd4650b80>.status

  /tmp/guix-build-datasette-0.64.2.drv-0/source/tests/test_html.py:948: AssertionError
  _ 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] _
  [gw18] linux -- Python 3.9.9 /gnu/store/slsh0qjv5j68xda2bb6h8gsxwyi1j25a-python-wrapper-3.9.9/bin/python

  app_client = <datasette.utils.testing.TestClient object at 0x7fffec5952e0>
  path = '/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'
  expected = '/fixtures?sql=select+id%2C+name+from+facet_cities+order+by+id+limit+1%3B'

      @pytest.mark.parametrize(
          "path,expected",
          [
              (
                  "/fixtures/neighborhood_search",
                  "/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&amp;text=",
              ),
              (
                  "/fixtures/neighborhood_search?text=ber",
                  "/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&amp;text=ber",
              ),
              ("/fixtures/pragma_cache_size", None),
              (
                  # /fixtures/𝐜𝐢𝐭𝐢𝐞𝐬
                  "/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",
              ),
              ("/fixtures/magic_parameters", None),
          ],
      )
      def test_edit_sql_link_on_canned_queries(app_client, path, expected):
          response = app_client.get(path)
  >       assert response.status == 200
  E       assert 302 == 200
  E        +  where 302 = <datasette.utils.testing.TestResponse object at 0x7fffec4a6f70>.status

  /tmp/guix-build-datasette-0.64.2.drv-0/source/tests/test_html.py:841: AssertionError
  _______________________ test_table_with_slashes_in_name ________________________
  [gw9] linux -- Python 3.9.9 /gnu/store/slsh0qjv5j68xda2bb6h8gsxwyi1j25a-python-wrapper-3.9.9/bin/python

  app_client = <datasette.utils.testing.TestClient object at 0x7fffec0860a0>

      def test_table_with_slashes_in_name(app_client):
          response = app_client.get(
              "/fixtures/table~2Fwith~2Fslashes~2Ecsv.json?_shape=objects"
          )
  >       assert response.status == 200
  E       assert 302 == 200
  E        +  where 302 = <datasette.utils.testing.TestResponse object at 0x7fffec086fa0>.status

  /tmp/guix-build-datasette-0.64.2.drv-0/source/tests/test_table_api.py:141: AssertionError
  __________________ test_custom_query_with_unicode_characters ___________________
  [gw8] linux -- Python 3.9.9 /gnu/store/slsh0qjv5j68xda2bb6h8gsxwyi1j25a-python-wrapper-3.9.9/bin/python

  app_client = <datasette.utils.testing.TestClient object at 0x7fffec1cda90>

      def test_custom_query_with_unicode_characters(app_client):
          # /fixtures/𝐜𝐢𝐭𝐢𝐞𝐬.json
          response = app_client.get(
              "/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"
          )
  >       assert [{"id": 1, "name": "San Francisco"}] == response.json

  /tmp/guix-build-datasette-0.64.2.drv-0/source/tests/test_table_api.py:1042: 
  _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
  /tmp/guix-build-datasette-0.64.2.drv-0/source/datasette/utils/testing.py:40: in json
      return json.loads(self.text)
  /gnu/store/65i3nhcwmz0p8rqbg48gaavyky4g4hwk-python-3.9.9/lib/python3.9/json/__init__.py:346: in loads
      return _default_decoder.decode(s)
  /gnu/store/65i3nhcwmz0p8rqbg48gaavyky4g4hwk-python-3.9.9/lib/python3.9/json/decoder.py:337: in decode
      obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

  self = <json.decoder.JSONDecoder object at 0x7ffff7479760>, s = '', idx = 0

      def raw_decode(self, s, idx=0):
          """Decode a JSON document from ``s`` (a ``str`` beginning with
          a JSON document) and return a 2-tuple of the Python
          representation and the index in ``s`` where the document ended.
      
          This can be used to decode a JSON document from a string that may
          have extraneous data at the end.
      
          """
          try:
              obj, end = self.scan_once(s, idx)
          except StopIteration as err:
  >           raise JSONDecodeError("Expecting value", s, err.value) from None
  E           json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)

  /gnu/store/65i3nhcwmz0p8rqbg48gaavyky4g4hwk-python-3.9.9/lib/python3.9/json/decoder.py:355: JSONDecodeError
  _ test_searchable[/fixtures/searchable.json?_search=te*+AND+do*&_searchmode=raw-expected_rows3] _
  [gw13] linux -- Python 3.9.9 /gnu/store/slsh0qjv5j68xda2bb6h8gsxwyi1j25a-python-wrapper-3.9.9/bin/python

  app_client = <datasette.utils.testing.TestClient object at 0x7fffd470bf10>
  path = '/fixtures/searchable.json?_search=te*+AND+do*&_searchmode=raw'
  expected_rows = [[1, 'barry cat', 'terry dog', 'panther'], [2, 'terry dog', 'sara weasel', 'puma']]

      @pytest.mark.parametrize(
          "path,expected_rows",
          [
              (
                  "/fixtures/searchable.json?_search=dog",
                  [
                      [1, "barry cat", "terry dog", "panther"],
                      [2, "terry dog", "sara weasel", "puma"],
                  ],
              ),
              (
                  # Special keyword shouldn't break FTS query
                  "/fixtures/searchable.json?_search=AND",
                  [],
              ),
              (
                  # Without _searchmode=raw this should return no results
                  "/fixtures/searchable.json?_search=te*+AND+do*",
                  [],
              ),
              (
                  # _searchmode=raw
                  "/fixtures/searchable.json?_search=te*+AND+do*&_searchmode=raw",
                  [
                      [1, "barry cat", "terry dog", "panther"],
                      [2, "terry dog", "sara weasel", "puma"],
                  ],
              ),
              (
                  # _searchmode=raw combined with _search_COLUMN
                  "/fixtures/searchable.json?_search_text2=te*&_searchmode=raw",
                  [
                      [1, "barry cat", "terry dog", "panther"],
                  ],
              ),
              (
                  "/fixtures/searchable.json?_search=weasel",
                  [[2, "terry dog", "sara weasel", "puma"]],
              ),
              (
                  "/fixtures/searchable.json?_search_text2=dog",
                  [[1, "barry cat", "terry dog", "panther"]],
              ),
              (
                  "/fixtures/searchable.json?_search_name%20with%20.%20and%20spaces=panther",
                  [[1, "barry cat", "terry dog", "panther"]],
              ),
          ],
      )
      def test_searchable(app_client, path, expected_rows):
          response = app_client.get(path)
  >       assert expected_rows == response.json["rows"]
  E       AssertionError: assert [[1, 'barry cat', 'terry dog', 'panther'],\n [2, 'terry dog', 'sara weasel', 'puma']] == []
  E         Left contains 2 more items, first extra item: [1, 'barry cat', 'terry dog', 'panther']
  E         Full diff:
  E           [
  E         -  ,
  E         +  [1,
  E         +   'barry cat',
  E         +   'terry dog',
  E         +   'panther'],
  E         +  [2,
  E         +   'terry dog',
  E         +   'sara weasel',
  E         +   'puma'],
  E           ]

  /tmp/guix-build-datasette-0.64.2.drv-0/source/tests/test_table_api.py:402: AssertionError
  _____ test_searchmode[table_metadata1-_search=te*+AND+do*-expected_rows1] ______
  [gw20] linux -- Python 3.9.9 /gnu/store/slsh0qjv5j68xda2bb6h8gsxwyi1j25a-python-wrapper-3.9.9/bin/python

  table_metadata = {'searchmode': 'raw'}, querystring = '_search=te*+AND+do*'
  expected_rows = [[1, 'barry cat', 'terry dog', 'panther'], [2, 'terry dog', 'sara weasel', 'puma']]

      @pytest.mark.parametrize(
          "table_metadata,querystring,expected_rows",
          [
              (
                  {},
                  "_search=te*+AND+do*",
                  [],
              ),
              (
                  {"searchmode": "raw"},
                  "_search=te*+AND+do*",
                  _SEARCHMODE_RAW_RESULTS,
              ),
              (
                  {},
                  "_search=te*+AND+do*&_searchmode=raw",
                  _SEARCHMODE_RAW_RESULTS,
              ),
              # Can be over-ridden with _searchmode=escaped
              (
                  {"searchmode": "raw"},
                  "_search=te*+AND+do*&_searchmode=escaped",
                  [],
              ),
          ],
      )
      def test_searchmode(table_metadata, querystring, expected_rows):
          with make_app_client(
              metadata={"databases": {"fixtures": {"tables": {"searchable": table_metadata}}}}
          ) as client:
              response = client.get("/fixtures/searchable.json?" + querystring)
  >           assert expected_rows == response.json["rows"]
  E           AssertionError: assert [[1, 'barry cat', 'terry dog', 'panther'],\n [2, 'terry dog', 'sara weasel', 'puma']] == []
  E             Left contains 2 more items, first extra item: [1, 'barry cat', 'terry dog', 'panther']
  E             Full diff:
  E               [
  E             -  ,
  E             +  [1,
  E             +   'barry cat',
  E             +   'terry dog',
  E             +   'panther'],
  E             +  [2,
  E             +   'terry dog',
  E             +   'sara weasel',
  E             +   'puma'],
  E               ]

  /tmp/guix-build-datasette-0.64.2.drv-0/source/tests/test_table_api.py:442: AssertionError
  _ test_searchmode[table_metadata2-_search=te*+AND+do*&_searchmode=raw-expected_rows2] _
  [gw20] linux -- Python 3.9.9 /gnu/store/slsh0qjv5j68xda2bb6h8gsxwyi1j25a-python-wrapper-3.9.9/bin/python

  table_metadata = {}, querystring = '_search=te*+AND+do*&_searchmode=raw'
  expected_rows = [[1, 'barry cat', 'terry dog', 'panther'], [2, 'terry dog', 'sara weasel', 'puma']]

      @pytest.mark.parametrize(
          "table_metadata,querystring,expected_rows",
          [
              (
                  {},
                  "_search=te*+AND+do*",
                  [],
              ),
              (
                  {"searchmode": "raw"},
                  "_search=te*+AND+do*",
                  _SEARCHMODE_RAW_RESULTS,
              ),
              (
                  {},
                  "_search=te*+AND+do*&_searchmode=raw",
                  _SEARCHMODE_RAW_RESULTS,
              ),
              # Can be over-ridden with _searchmode=escaped
              (
                  {"searchmode": "raw"},
                  "_search=te*+AND+do*&_searchmode=escaped",
                  [],
              ),
          ],
      )
      def test_searchmode(table_metadata, querystring, expected_rows):
          with make_app_client(
              metadata={"databases": {"fixtures": {"tables": {"searchable": table_metadata}}}}
          ) as client:
              response = client.get("/fixtures/searchable.json?" + querystring)
  >           assert expected_rows == response.json["rows"]
  E           AssertionError: assert [[1, 'barry cat', 'terry dog', 'panther'],\n [2, 'terry dog', 'sara weasel', 'puma']] == []
  E             Left contains 2 more items, first extra item: [1, 'barry cat', 'terry dog', 'panther']
  E             Full diff:
  E               [
  E             -  ,
  E             +  [1,
  E             +   'barry cat',
  E             +   'terry dog',
  E             +   'panther'],
  E             +  [2,
  E             +   'terry dog',
  E             +   'sara weasel',
  E             +   'puma'],
  E               ]

  /tmp/guix-build-datasette-0.64.2.drv-0/source/tests/test_table_api.py:442: AssertionError
  =========================== short test summary info ============================
  FAILED tests/test_api.py::test_row_strange_table_name - assert 400 == 200
  FAILED tests/test_api.py::test_database_page_for_database_with_dot_in_name - ...
  FAILED tests/test_api.py::test_tilde_encoded_database_names[fo%o] - assert 30...
  FAILED tests/test_api.py::test_tilde_encoded_database_names[f~/c.d] - assert ...
  FAILED tests/test_api.py::test_database_with_space_in_name[/searchable.json]
  FAILED tests/test_api.py::test_database_with_space_in_name[.json] - httpx.Too...
  FAILED tests/test_api.py::test_database_with_space_in_name[/searchable_view]
  FAILED tests/test_api.py::test_database_with_space_in_name[/] - httpx.TooMany...
  FAILED tests/test_api.py::test_database_with_space_in_name[/searchable] - htt...
  FAILED tests/test_api.py::test_database_with_space_in_name[/searchable_view.json]
  FAILED tests/test_cli.py::test_weird_database_names[database (1).sqlite] - As...
  FAILED tests/test_cli.py::test_weird_database_names[test-database (1).sqlite]
  FAILED tests/test_html.py::test_row_html_compound_primary_key[/fixtures/compound_primary_key/a~2Fb,~2Ec~2Dd-expected1]
  FAILED tests/test_html.py::test_css_classes_on_body[/fixtures/table~2Fwith~2Fslashes~2Ecsv-expected_classes5]
  FAILED tests/test_html.py::test_templates_considered[/fixtures/table~2Fwith~2Fslashes~2Ecsv-table-fixtures-tablewithslashescsv-fa7563.html, *table.html]
  FAILED tests/test_html.py::test_alternate_url_json[/fixtures/table~2Fwith~2Fslashes~2Ecsv-http://localhost/fixtures/table~2Fwith~2Fslashes~2Ecsv.json]
  FAILED 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]
  FAILED tests/test_table_api.py::test_table_with_slashes_in_name - assert 302 ...
  FAILED tests/test_table_api.py::test_custom_query_with_unicode_characters - j...
  FAILED tests/test_table_api.py::test_searchable[/fixtures/searchable.json?_search=te*+AND+do*&_searchmode=raw-expected_rows3]
  FAILED tests/test_table_api.py::test_searchmode[table_metadata1-_search=te*+AND+do*-expected_rows1]
  FAILED tests/test_table_api.py::test_searchmode[table_metadata2-_search=te*+AND+do*&_searchmode=raw-expected_rows2]
  =========== 22 failed, 1049 passed, 3 skipped in 1522.28s (0:25:22) ============
  error: in phase 'check': uncaught exception:
  %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> 
  phase `check' failed after 1523.3 seconds
  ```
  The tests run in a private namespace without internet connectivity, and the Python dependencies are at:
  ```
  python-aiofiles@0.6.0 python-asgi-csrf@0.9 python-asgiref@3.4.1
  + python-beautifulsoup4@4.11.1 python-black@22.3.0 python-click-default-group@1.2.2 python-click@8.1.3
  + python-cogapp@3.3.0 python-httpx@0.23.0 python-hupper@1.10.3 python-itsdangerous@2.0.1
  + 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
  + python-pytest-asyncio@0.17.2 python-pytest-runner@5.2 python-pytest-timeout@2.0.2
  + python-pytest-xdist@2.5.0 python-pytest@7.1.3 python-pyyaml@6.0 python-setuptools@64.0.3
  + python-trustme@0.9.0 python-uvicorn@0.17.6
  ```
  With Python 3.9.9.

  Thank you!

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}


node_id: I_kwDOBm6k_c5iJyum
title: Custom SQL queries should use new JSON ?_extra= format
state: open
created_at: 2023-03-30T00:42:53Z
updated_at: 2023-04-05T23:29:27Z
author_association: OWNER
type: issue
body:
  Related:
  - #262

  I've made the change to the table view, now I need the new format to work for arbitrary SQL queries too.

  Note that this incorporates both arbitrary SQL queries and canned queries.

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}


node_id: I_kwDOBm6k_c5iVdKt
title: Row page JSON should use new ?_extra= format
state: open
created_at: 2023-03-31T17:56:53Z
updated_at: 2023-03-31T17:59:49Z
author_association: OWNER
body:
  https://latest.datasette.io/fixtures/facetable/2.json

  Related:
  - #2049
  - #1709

type: issue
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}


node_id: I_kwDOBm6k_c5iVdn1
title: `?_extra=row_urls` for table pages
state: open
created_at: 2023-03-31T17:58:36Z
updated_at: 2023-03-31T17:58:36Z
author_association: OWNER
type: issue
body:
  Provides URLs to the JSON version of those rows. Maybe it persists the `?_shape=` option too? Not sure about that.

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}


node_id: I_kwDOJHON9s5iZ_q8
title: Error running pytest
state: open
created_at: 2023-04-02T15:02:36Z
updated_at: 2023-04-02T15:07:10Z
author_association: NONE
type: issue
body:
  `______________________________________________________ ERROR collecting tests/test_apple_notes_to_sqlite.py _______________________________________________________
  ImportError while importing test module '/Users/lol/development/apple-notes-to-sqlite/tests/test_apple_notes_to_sqlite.py'.
  Hint: make sure your test modules/packages have valid Python names.
  Traceback:
  /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
      return _bootstrap._gcd_import(name[level:], package, level)
  tests/test_apple_notes_to_sqlite.py:2: in <module>
      from apple_notes_to_sqlite.cli import cli, COUNT_SCRIPT, FOLDERS_SCRIPT
  E   ModuleNotFoundError: No module named 'apple_notes_to_sqlite'`

  Solution:
  This 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

  `python -m pytest`

  The 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)

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}


node_id: PR_kwDOJHON9s5NbyYN
title: use universal command
state: open
created_at: 2023-04-02T15:10:54Z
updated_at: 2023-04-02T15:37:34Z
author_association: FIRST_TIME_CONTRIBUTOR
pull_request: dogsheep/apple-notes-to-sqlite/pulls/13
type: pull
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}


node_id: PR_kwDOBm6k_c5NcFCf
title: feat: Javascript Plugin API (Custom panels, column menu items with JS actions)
state: closed
created_at: 2023-04-02T20:23:44Z
updated_at: 2023-10-14T17:49:03Z
closed_at: 2023-10-13T00:00:27Z
author_association: CONTRIBUTOR
pull_request: simonw/datasette/pulls/2052
type: pull
body:
  ## Motivation

  - 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
  - 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)
  - Discussion w/ @simonw about a general-purpose Datasette JS API

  ## Changes

  Summary: Provide 2 new surface areas for Datasette JS plugin developers. See alpha [documentation](https://github.com/simonw/datasette/pull/2052#issuecomment-1510423051)

  1. Custom column header items: <https://a.cl.ly/Kou97wJr>
  2. Basic "panels" controlled by buttons: <https://a.cl.ly/rRugWobd>

  ### User Facing Changes

  - 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.
  - Allow plugins to register UI elements in a panel controller. The parent component handles switching the visibility of active plugins.
    - Because native button elements are used, the panel is keyboard-accessible - use tab / shift-tab to cycle through tab options, and `enter` to select.
    - There's room to improve the styling, but the focus of this PR is on the API rather than the UX.

  ### (plugin) Developer Facing Changes

  - Dispatch a `datasette_init` [CustomEvent](https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent) when the `datasetteManager` is finished loading.
  - Provide `manager.registerPlugin` API for adding new functionality that coordinates with Datasette lifecycle events.
  - Provide a `manager.selectors` map of DOM elements that users may want to hook into.
    - Updated `table.js` to use refer to these to motivating keeping things in sync
  - Allow plugins to register themselves with 2 hooks:
    - `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)
    - `makeAboveTablePanelConfigs`: Add items to the panel. Each panel has a unique ID (namespaced within that plugin), a render function, and a string label.

  See [this file](https://github.com/simonw/datasette/blob/2d92b9328022d86505261bcdac419b6ed9cb2236/datasette/static/table-example-plugins.js) for example plugin usage.

  ###  Core Developer Facing Changes

  - Modified `table.js` to make use of the `datasetteManager` API.
  - Added example plugins to the `demos/plugins` folder, and stored the test js in the `statics/` folder

  ## Testing

  For Datasette plugin developers, please see the [alpha-level documentation](https://github.com/simonw/datasette/pull/2052#issuecomment-1510423051) .

  To run the examples:

  ```bash
  datasette serve fixtures.db  --plugins-dir=demos/plugins/
  ```

  Open local server: `http://127.0.0.1:8001/fixtures/facetable`

  Open to all feedback on this PR, from API design to variable naming, to what additional hooks might be useful for the future.

  My focus was more on the general shape of the API for developers, rather than on the UX of the test plugins.

  ## Design notes

  - The manager tab panel could be a separate plugin if the implementation is too custom.
  - The `makeColumnHeaderItems` benefits from hooking into the logic of `table.js`
  - 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.
  - Non-goals:
    - 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.
    - 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.

  ## Research Notes

  - 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.

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}


node_id: I_kwDOCGYnMM5ismuI
title: rows: --transpose or psql extended view-like functionality
state: closed
created_at: 2023-04-05T15:37:33Z
updated_at: 2023-06-15T08:39:49Z
closed_at: 2023-06-14T22:05:28Z
author_association: CONTRIBUTOR
type: issue
state_reason: completed
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`)

  In other words instead of this:

  ```
  sqlite-utils rows  --limit 5 --fmt github track_metadata.db songs
  ```

  | track_id           | title             | song_id            | release                              | artist_id          | artist_mbid                          | artist_name      |   duration |   artist_familiarity |   artist_hotttnesss |   year |   track_7digitalid |   shs_perf |   shs_work |
  |--------------------|-------------------|--------------------|--------------------------------------|--------------------|--------------------------------------|------------------|------------|----------------------|---------------------|--------|--------------------|------------|------------|
  | 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 |
  | TRMMMKD128F425225D | Tanssi vaan       | SOVFVAK12A8C1350D9 | Karkuteillä                          | ARMVN3U1187FB3A1EB | 8d7ef530-a6fd-4f8f-b2e2-74aec765e0f9 | Karkkiautomaatti |    156.551 |             0.439604 |            0.356992 |   1995 |            1514808 |         -1 |          0 |
  | 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 |
  | TRMMMCH128F425532C | Si Vos Querés     | SOBNYVR12A8C13558C | De Culo                              | ARNWYLR1187B9B2F9C | 12be7648-7094-495f-90e6-df4189d68615 | Yerba Brava      |    145.058 |             0.448501 |            0.372349 |   2003 |            2168257 |         -1 |          0 |
  | TRMMMWA128F426B589 | Tangle Of Aspens  | SOHSBXH12A8C13B0DF | Rene Ablaze Presents Winter Sessions | AREQDTE1269FB37231 |                                      | Der Mystic       |    514.298 |             0        |            0        |      0 |            2264873 |         -1 |          0 |


  The output would look something like this:

  ```
  $ for col in (sqlite-columns track_metadata.db songs)
      sqlite-utils --fmt github track_metadata.db "select $col from songs order by rowid desc limit 5"
  end
  ```

  | track_id           |
  |--------------------|
  | TRYYYVU12903CD01E3 |
  | TRYYYDJ128F9310A21 |
  | TRYYYMG128F4260ECA |
  | TRYYYJO128F426DA37 |
  | TRYYYUS12903CD2DF0 |
  | title                               |
  |-------------------------------------|
  | Fernweh feat. Sektion Kuchikäschtli |
  | Faraday                             |
  | Novemba                             |
  | Jago Chhadeo                        |
  | O Samba Da Vida                     |
  | song_id            |
  |--------------------|
  | SOWXJXQ12AB0189F43 |
  | SOLXGOR12A81C21EB7 |
  | SOHODZI12A8C137BB3 |
  | SOXQYIQ12A8C137FBB |
  | SOTXAME12AB018F136 |
  | release                         |
  |---------------------------------|
  | So Oder So                      |
  | The Trance Collection Vol. 2    |
  | Dub_Connected: electronic music |
  | Naale Baba Lassi Pee Gya        |
  | Pacha V.I.P.                    |
  | artist_id          |
  |--------------------|
  | AR7PLM21187B990D08 |
  | ARCMCOK1187B9B1073 |
  | ARZ3R6M1187B9AF750 |
  | ART5FZD1187B9A7FCF |
  | AR7Z4J81187FB3FC59 |
  | artist_mbid                          |
  |--------------------------------------|
  | 3af2b07e-c91c-4160-9bda-f0b9e3144ed3 |
  | 4ac5f3de-c5ad-475e-ad50-41f1ef9dba20 |
  | 8b97e9c8-61f5-4615-9a96-276f24204e34 |
  | 2357c400-9109-42b6-b3fe-9e2d9f8e3872 |
  | 9d50cb20-7e42-45cc-b0dd-154c3e92a577 |
  | artist_name    |
  |----------------|
  | Texta          |
  | Elude          |
  | Gabriel Le Mar |
  | Kuldeep Manak  |
  | Kiko Navarro   |
  |   duration |
  |------------|
  |    295.079 |
  |    484.519 |
  |    553.038 |
  |    244.166 |
  |    217.443 |
  |   artist_familiarity |
  |----------------------|
  |             0.552977 |
  |             0.403668 |
  |             0.556918 |
  |             0.4015   |
  |             0.528617 |
  |   artist_hotttnesss |
  |---------------------|
  |            0.454869 |
  |            0.256935 |
  |            0.336914 |
  |            0.374866 |
  |            0.411595 |
  |   year |
  |--------|
  |   2004 |
  |      0 |
  |      0 |
  |      0 |
  |      0 |
  |   track_7digitalid |
  |--------------------|
  |            8486723 |
  |            5472456 |
  |            2219291 |
  |            1632096 |
  |            7522478 |
  |   shs_perf |
  |------------|
  |         -1 |
  |         -1 |
  |         -1 |
  |         -1 |
  |         -1 |
  |   shs_work |
  |------------|
  |          0 |
  |          0 |
  |          0 |
  |          0 |
  |          0 |

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}


node_id: PR_kwDOBm6k_c5NuBNG
title: WIP new JSON for queries
state: closed
created_at: 2023-04-05T23:26:15Z
updated_at: 2023-07-26T18:28:59Z
closed_at: 2023-07-26T18:26:45Z
author_association: OWNER
pull_request: simonw/datasette/pulls/2053
type: pull
body:
  Refs:
  - #2049

  TODO:

  - [x] Read queries JSON
  - Implement error display with `"ok": false` and an errors key
  - Read queries HTML
  - Read queries other formats (plugins)
  - Canned read queries (dispatched to from table)
  - Write queries (a canned query thing)
  - Implement different shapes, refactoring to share code with table
  - Implement a sensible subset of extras, also refactoring to share code with table
  - Get all tests passing

  <!-- readthedocs-preview datasette start -->
  ----
  :books: Documentation preview :books:: https://datasette--2053.org.readthedocs.build/en/2053/

  <!-- readthedocs-preview datasette end -->

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}


node_id: I_kwDOBm6k_c5i0POi
title: Make detailed notes on how table, query and row views work right now
state: open
created_at: 2023-04-06T18:21:09Z
updated_at: 2023-04-07T20:14:38Z
author_association: OWNER
body:
  Research to help influence the following:
  - #2049
  - #2053
  - #2050
  - #262

type: issue
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}


node_id: PR_kwDOCGYnMM5N35VZ
title: Add paths for homebrew on Apple silicon
state: closed
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
type: pull
body:
  Does what it says and nothing else. This is the same set of paths as Datasette uses.

  <!-- readthedocs-preview sqlite-utils start -->
  ----
  :books: Documentation preview :books:: https://sqlite-utils--536.org.readthedocs.build/en/536/

  <!-- readthedocs-preview sqlite-utils end -->

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}


node_id: I_kwDODD6af85jCkOg
title: ambiguous column name: createdAt - on checkin_details view
state: closed
created_at: 2023-04-11T01:07:47Z
updated_at: 2023-04-11T03:16:37Z
closed_at: 2023-04-11T03:16:37Z
author_association: MEMBER
type: issue
state_reason: completed
body:
  It looks like Swarm changed their schema and now both `venues` and `checkins` have `createdAt` fields.

  Which breaks this view: https://github.com/dogsheep/swarm-to-sqlite/blob/719b6e96a016d0ca8b316d3bed9c2a7a0cb499ee/swarm_to_sqlite/utils.py#L171-L188

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}


node_id: PR_kwDOBm6k_c5N_bMw
title: GitHub Action to lint Python code with ruff
state: open
created_at: 2023-04-11T06:41:27Z
updated_at: 2023-04-15T14:24:46Z
author_association: FIRST_TIME_CONTRIBUTOR
pull_request: simonw/datasette/pulls/2056
type: pull
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.

  The ruff Action uses minimal steps to run in ~5 seconds, rapidly providing intuitive GitHub Annotations to contributors.

  ![image](https://user-images.githubusercontent.com/3709715/223758136-afc386d2-70aa-4eff-953a-2c2d82ceea23.png)

  <!-- readthedocs-preview datasette start -->
  ----
  :books: Documentation preview :books:: https://datasette--2056.org.readthedocs.build/en/2056/

  <!-- readthedocs-preview datasette end -->

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}


node_id: I_kwDOBm6k_c5jHqHD
title: DeprecationWarning: pkg_resources is deprecated as an API
state: closed
created_at: 2023-04-11T17:41:20Z
updated_at: 2023-09-21T22:09:10Z
closed_at: 2023-09-21T22:09:10Z
author_association: OWNER
type: issue
state_reason: completed
body:
  Got this running tests against Python 3.11.

  ```
  ../../../.local/share/virtualenvs/datasette-big-local-6Yn-280V/lib/python3.11/site-packages/datasette/app.py:14: in <module>
      import pkg_resources
  ../../../.local/share/virtualenvs/datasette-big-local-6Yn-280V/lib/python3.11/site-packages/pkg_resources/__init__.py:121: in <module>
      warnings.warn("pkg_resources is deprecated as an API", DeprecationWarning)
  E   DeprecationWarning: pkg_resources is deprecated as an API
  ```

  I 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:

  https://github.com/simonw/datasette/blob/5890a20c374fb0812d88c9b0ef26a838bfa06c76/datasette/plugins.py#L43-L50

  https://github.com/simonw/datasette/blob/5890a20c374fb0812d88c9b0ef26a838bfa06c76/datasette/app.py#L1037

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}


node_id: I_kwDOBm6k_c5jJXeN
title: 500 "attempt to write a readonly database" error caused by "PRAGMA schema_version"
state: open
created_at: 2023-04-11T23:57:50Z
updated_at: 2023-04-13T16:35:21Z
author_association: OWNER
type: issue
body:
  I've not been able to replicate this myself yet, but I've seen log files from a user affected by it.

  ```
  File "/usr/local/lib/python3.11/site-packages/datasette/views/base.py", line 89, in dispatch_request
  await self.ds.refresh_schemas()
  File "/usr/local/lib/python3.11/site-packages/datasette/app.py", line 371, in refresh_schemas
  await self._refresh_schemas()
  File "/usr/local/lib/python3.11/site-packages/datasette/app.py", line 386, in _refresh_schemas
  schema_version = (await db.execute("PRAGMA schema_version")).first()[0]
  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/datasette/database.py", line 267, in execute
  results = await self.execute_fn(sql_operation_in_thread)
  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/datasette/database.py", line 213, in execute_fn
  return await asyncio.get_event_loop().run_in_executor(
  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/concurrent/futures/thread.py", line 58, in run
  result = self.fn(*self.args, **self.kwargs)
  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/datasette/database.py", line 211, in in_thread
  return fn(conn)
  ^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/datasette/database.py", line 237, in sql_operation_in_thread
  cursor.execute(sql, params if params is not None else {})
  sqlite3.OperationalError: attempt to write a readonly database
  ```
  That's running the official Datasette Docker image on https://fly.io/ - it's causing 500 errors on every page of their site.

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}


node_id: I_kwDOBm6k_c5jPrPO
title: "Deceptive site ahead" alert on Heroku deployment
state: open
created_at: 2023-04-12T18:34:51Z
updated_at: 2023-04-13T01:13:01Z
author_association: NONE
type: issue
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.

  Is there way around this? Maybe a way to add ownership verification [through Google's search console](https://search.google.com/search-console/welcome)? 

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}


node_id: PR_kwDOCGYnMM5OKveS
title: Support self-referencing FKs in `Table.create`
state: closed
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
type: pull
body:
  <!-- readthedocs-preview sqlite-utils start -->
  ----
  :books: Documentation preview :books:: https://sqlite-utils--537.org.readthedocs.build/en/537/

  <!-- readthedocs-preview sqlite-utils end -->

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}


node_id: I_kwDOBm6k_c5jRat5
title: Clean up a bunch of warnings from ruff
state: open
created_at: 2023-04-13T01:23:02Z
updated_at: 2023-04-13T01:23:02Z
author_association: OWNER
type: issue
body:
  See:
  - #2056

  `ruff` spots a bunch of warnings about things like unused variables - would be good to clean up as many of these as possible.

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}


node_id: PR_kwDOBm6k_c5OpEz_
title: Add "Packaging a plugin using Poetry" section in docs
state: open
created_at: 2023-04-19T07:23:28Z
updated_at: 2023-04-19T07:27:18Z
author_association: FIRST_TIME_CONTRIBUTOR
pull_request: simonw/datasette/pulls/2061
type: pull
body:
  This PR adds a new section about packaging a plugin using `poetry` within the "Writing plugins" page of the documentation.

  <!-- readthedocs-preview datasette start -->
  ----
  :books: Documentation preview :books:: https://datasette--2061.org.readthedocs.build/en/2061/

  <!-- readthedocs-preview datasette end -->

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}


node_id: PR_kwDOBm6k_c5PAcGt
title: Bump sphinx from 6.1.3 to 6.2.0
state: closed
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
type: pull
body:
  Bumps [sphinx](https://github.com/sphinx-doc/sphinx) from 6.1.3 to 6.2.0.
  <details>
  <summary>Release notes</summary>
  <p><em>Sourced from <a href="https://github.com/sphinx-doc/sphinx/releases">sphinx's releases</a>.</em></p>
  <blockquote>
  <h2>v6.2.0</h2>
  <p>Changelog: <a href="https://www.sphinx-doc.org/en/master/changes.html">https://www.sphinx-doc.org/en/master/changes.html</a></p>
  </blockquote>
  </details>
  <details>
  <summary>Changelog</summary>
  <p><em>Sourced from <a href="https://github.com/sphinx-doc/sphinx/blob/master/CHANGES">sphinx's changelog</a>.</em></p>
  <blockquote>
  <h1>Release 6.2.0 (released Apr 23, 2023)</h1>
  <h2>Dependencies</h2>
  <ul>
  <li>Require Docutils 0.18.1 or greater.</li>
  </ul>
  <h2>Incompatible changes</h2>
  <ul>
  <li>LaTeX: removal of some internal TeX <code>\dimen</code> registers (not previously
  publicly documented) as per 5.1.0 code comments in <code>sphinx.sty</code>:
  <code>\sphinxverbatimsep</code>, <code>\sphinxverbatimborder</code>, <code>\sphinxshadowsep</code>,
  <code>\sphinxshadowsize</code>, and <code>\sphinxshadowrule</code>. (refs: <a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11105">#11105</a>)</li>
  <li>Remove <code>.egg</code> support from pycode <code>ModuleAnalyser</code>; Python eggs are a
  now-obsolete binary distribution format</li>
  <li><a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11089">#11089</a>: Remove deprecated code in <code>sphinx.builders.linkcheck</code>.
  Patch by Daniel Eades</li>
  <li>Remove internal-only <code>sphinx.locale.setlocale</code></li>
  </ul>
  <h2>Deprecated</h2>
  <ul>
  <li><a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11247">#11247</a>: Deprecate the legacy <code>intersphinx_mapping</code> format</li>
  <li><code>sphinx.util.osutil.cd</code> is deprecated in favour of <code>contextlib.chdir</code>.</li>
  </ul>
  <h2>Features added</h2>
  <ul>
  <li><a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11277">#11277</a>: :rst:dir:<code>autoproperty</code> allows the return type to be specified as
  a type comment (e.g., <code># type: () -&gt; int</code>). Patch by Bénédikt Tran</li>
  <li><a href="https://redirect.github.com/sphinx-doc/sphinx/issues/10811">#10811</a>: Autosummary: extend <code>__all__</code> to imported members for template rendering
  when option <code>autosummary_ignore_module_all</code> is set to <code>False</code>. Patch by
  Clement Pinard</li>
  <li><a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11147">#11147</a>: Add a <code>content_offset</code> parameter to <code>nested_parse_with_titles()</code>,
  allowing for correct line numbers during nested parsing.
  Patch by Jeremy Maitin-Shepard</li>
  <li>Update to Unicode CLDR 42</li>
  <li>Add a <code>--jobs</code> synonym for <code>-j</code>. Patch by Hugo van Kemenade</li>
  <li>LaTeX: a command <code>\sphinxbox</code> for styling text elements with a (possibly
  rounded) box, optional background color and shadow, has been added.
  See :ref:<code>sphinxbox</code>. (refs: <a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11224">#11224</a>)</li>
  <li>LaTeX: add <code>\sphinxstylenotetitle</code>, ..., <code>\sphinxstylewarningtitle</code>, ...,
  for an extra layer of mark-up freeing up <code>\sphinxstrong</code> for other uses.
  See :ref:<code>latex-macros</code>. (refs: <a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11267">#11267</a>)</li>
  <li>LaTeX: :dudir:<code>note</code>, :dudir:<code>hint</code>, :dudir:<code>important</code> and :dudir:<code>tip</code> can
  now each be styled as the other admonitions, i.e. possibly with a background
  color, individual border widths and paddings, possibly rounded corners, and
  optional shadow.  See :ref:<code>additionalcss</code>. (refs: <a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11234">#11234</a>)</li>
  </ul>
  <!-- raw HTML omitted -->
  </blockquote>
  <p>... (truncated)</p>
  </details>
  <details>
  <summary>Commits</summary>
  <ul>
  <li><a href="https://github.com/sphinx-doc/sphinx/commit/e7d4c3669cec32721ee7fc25d9cb8dc3497095ed"><code>e7d4c36</code></a> Bump to 6.2.0 final</li>
  <li><a href="https://github.com/sphinx-doc/sphinx/commit/4e27a5fba146bf85b6e2e0ba8b9f5ac30b1c1e29"><code>4e27a5f</code></a> Remove unneeded JavaScript from <code>sphinx13</code> theme</li>
  <li><a href="https://github.com/sphinx-doc/sphinx/commit/bffb54734f64e88c95b1d5558ec3fb7cb44ceda7"><code>bffb547</code></a> Note correct deprecation version for <code>sphinx.util.osutil.cd</code></li>
  <li><a href="https://github.com/sphinx-doc/sphinx/commit/59de8d52029deca803d38b5d084a3a32c7b7f994"><code>59de8d5</code></a> Revert &quot;Support and prefer <code>.jinja</code> to <code>_t</code> for static templates (<a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11165">#11165</a>)...</li>
  <li><a href="https://github.com/sphinx-doc/sphinx/commit/aee3c0ab75974790adf359a9c5089d1d781a6b21"><code>aee3c0a</code></a> Partially revert &quot;Disable localisation when SOURCE_DATE_EPOCH is set (<a href="https://redirect.github.com/sphinx-doc/sphinx/issues/10949">#10949</a>)...</li>
  <li><a href="https://github.com/sphinx-doc/sphinx/commit/186d596f3323f3141c34618e2e788e5cdff8fec3"><code>186d596</code></a> Use <code>overwrite_file</code> context manager in <code>test_ext_autodoc_configs</code> (<a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11320">#11320</a>)</li>
  <li><a href="https://github.com/sphinx-doc/sphinx/commit/77483f28244dac1e7459d09397180812cfb36946"><code>77483f2</code></a> Add missing test decorator for <code>test_util_inspect</code> (<a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11321">#11321</a>)</li>
  <li><a href="https://github.com/sphinx-doc/sphinx/commit/d8f15c7361c4766667db65252b685f19d4a08b56"><code>d8f15c7</code></a> Increase timeout threshold for <code>linkcheck</code> tests (<a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11326">#11326</a>)</li>
  <li><a href="https://github.com/sphinx-doc/sphinx/commit/b430e052858c490a4e90f3143f159ee6240eb948"><code>b430e05</code></a> Create a 'search field' component for themes (<a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11045">#11045</a>)</li>
  <li><a href="https://github.com/sphinx-doc/sphinx/commit/e2f66cea4997b6d8c588d3509adb68d4e9108ee6"><code>e2f66ce</code></a> Update CHANGES for PR <a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11333">#11333</a></li>
  <li>Additional commits viewable in <a href="https://github.com/sphinx-doc/sphinx/compare/v6.1.3...v6.2.0">compare view</a></li>
  </ul>
  </details>
  <br />


  [![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)

  Dependabot 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`.

  [//]: # (dependabot-automerge-start)
  [//]: # (dependabot-automerge-end)

  ---

  <details>
  <summary>Dependabot commands and options</summary>
  <br />

  You can trigger Dependabot actions by commenting on this PR:
  - `@dependabot rebase` will rebase this PR
  - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
  - `@dependabot merge` will merge this PR after your CI passes on it
  - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it
  - `@dependabot cancel merge` will cancel a previously requested merge and block automerging
  - `@dependabot reopen` will reopen this PR if it is closed
  - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
  - `@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)
  - `@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)
  - `@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)


  </details>

  <!-- readthedocs-preview datasette start -->
  ----
  :books: Documentation preview :books:: https://datasette--2063.org.readthedocs.build/en/2063/

  <!-- readthedocs-preview datasette end -->

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}


node_id: PR_kwDOBm6k_c5PG0wF
title: Bump sphinx from 6.1.3 to 6.2.1
state: closed
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
type: pull
body:
  Bumps [sphinx](https://github.com/sphinx-doc/sphinx) from 6.1.3 to 6.2.1.
  <details>
  <summary>Release notes</summary>
  <p><em>Sourced from <a href="https://github.com/sphinx-doc/sphinx/releases">sphinx's releases</a>.</em></p>
  <blockquote>
  <h2>v6.2.1</h2>
  <p>Changelog: <a href="https://www.sphinx-doc.org/en/master/changes.html">https://www.sphinx-doc.org/en/master/changes.html</a></p>
  <h2>v6.2.0</h2>
  <p>Changelog: <a href="https://www.sphinx-doc.org/en/master/changes.html">https://www.sphinx-doc.org/en/master/changes.html</a></p>
  </blockquote>
  </details>
  <details>
  <summary>Changelog</summary>
  <p><em>Sourced from <a href="https://github.com/sphinx-doc/sphinx/blob/master/CHANGES">sphinx's changelog</a>.</em></p>
  <blockquote>
  <h1>Release 6.2.1 (released Apr 25, 2023)</h1>
  <h2>Bugs fixed</h2>
  <ul>
  <li><a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11355">#11355</a>: Revert the default type of :confval:<code>nitpick_ignore</code> and
  :confval:<code>nitpick_ignore_regex</code> to <code>list</code>.</li>
  </ul>
  <h1>Release 6.2.0 (released Apr 23, 2023)</h1>
  <h2>Dependencies</h2>
  <ul>
  <li>Require Docutils 0.18.1 or greater.</li>
  </ul>
  <h2>Incompatible changes</h2>
  <ul>
  <li>LaTeX: removal of some internal TeX <code>\dimen</code> registers (not previously
  publicly documented) as per 5.1.0 code comments in <code>sphinx.sty</code>:
  <code>\sphinxverbatimsep</code>, <code>\sphinxverbatimborder</code>, <code>\sphinxshadowsep</code>,
  <code>\sphinxshadowsize</code>, and <code>\sphinxshadowrule</code>. (refs: <a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11105">#11105</a>)</li>
  <li>Remove <code>.egg</code> support from pycode <code>ModuleAnalyser</code>; Python eggs are a
  now-obsolete binary distribution format</li>
  <li><a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11089">#11089</a>: Remove deprecated code in <code>sphinx.builders.linkcheck</code>.
  Patch by Daniel Eades</li>
  <li>Remove internal-only <code>sphinx.locale.setlocale</code></li>
  </ul>
  <h2>Deprecated</h2>
  <ul>
  <li><a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11247">#11247</a>: Deprecate the legacy <code>intersphinx_mapping</code> format</li>
  <li><code>sphinx.util.osutil.cd</code> is deprecated in favour of <code>contextlib.chdir</code>.</li>
  </ul>
  <h2>Features added</h2>
  <ul>
  <li><a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11277">#11277</a>: :rst:dir:<code>autoproperty</code> allows the return type to be specified as
  a type comment (e.g., <code># type: () -&gt; int</code>). Patch by Bénédikt Tran</li>
  <li><a href="https://redirect.github.com/sphinx-doc/sphinx/issues/10811">#10811</a>: Autosummary: extend <code>__all__</code> to imported members for template rendering
  when option <code>autosummary_ignore_module_all</code> is set to <code>False</code>. Patch by
  Clement Pinard</li>
  <li><a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11147">#11147</a>: Add a <code>content_offset</code> parameter to <code>nested_parse_with_titles()</code>,
  allowing for correct line numbers during nested parsing.
  Patch by Jeremy Maitin-Shepard</li>
  <li>Update to Unicode CLDR 42</li>
  <li>Add a <code>--jobs</code> synonym for <code>-j</code>. Patch by Hugo van Kemenade</li>
  <li>LaTeX: a command <code>\sphinxbox</code> for styling text elements with a (possibly</li>
  </ul>
  <!-- raw HTML omitted -->
  </blockquote>
  <p>... (truncated)</p>
  </details>
  <details>
  <summary>Commits</summary>
  <ul>
  <li><a href="https://github.com/sphinx-doc/sphinx/commit/ec993dda3690f260345133c47a4a0f6ef0b18493"><code>ec993dd</code></a> Bump to 6.2.1 final</li>
  <li><a href="https://github.com/sphinx-doc/sphinx/commit/d2aa91f63ce2fa749e4d8835ea7b771ead29e54a"><code>d2aa91f</code></a> Revert the default type of <code>nitpick_ignore[_regex]</code> to <code>list</code></li>
  <li><a href="https://github.com/sphinx-doc/sphinx/commit/60d8fa10b881308c97012d478fb13770a41b469f"><code>60d8fa1</code></a> Bump version</li>
  <li><a href="https://github.com/sphinx-doc/sphinx/commit/70102ac2ee4d89e1293d8efa7763dcdd104ad548"><code>70102ac</code></a> Bump to 6.2.0 final</li>
  <li><a href="https://github.com/sphinx-doc/sphinx/commit/4e27a5fba146bf85b6e2e0ba8b9f5ac30b1c1e29"><code>4e27a5f</code></a> Remove unneeded JavaScript from <code>sphinx13</code> theme</li>
  <li><a href="https://github.com/sphinx-doc/sphinx/commit/bffb54734f64e88c95b1d5558ec3fb7cb44ceda7"><code>bffb547</code></a> Note correct deprecation version for <code>sphinx.util.osutil.cd</code></li>
  <li><a href="https://github.com/sphinx-doc/sphinx/commit/59de8d52029deca803d38b5d084a3a32c7b7f994"><code>59de8d5</code></a> Revert &quot;Support and prefer <code>.jinja</code> to <code>_t</code> for static templates (<a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11165">#11165</a>)...</li>
  <li><a href="https://github.com/sphinx-doc/sphinx/commit/aee3c0ab75974790adf359a9c5089d1d781a6b21"><code>aee3c0a</code></a> Partially revert &quot;Disable localisation when SOURCE_DATE_EPOCH is set (<a href="https://redirect.github.com/sphinx-doc/sphinx/issues/10949">#10949</a>)...</li>
  <li><a href="https://github.com/sphinx-doc/sphinx/commit/186d596f3323f3141c34618e2e788e5cdff8fec3"><code>186d596</code></a> Use <code>overwrite_file</code> context manager in <code>test_ext_autodoc_configs</code> (<a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11320">#11320</a>)</li>
  <li><a href="https://github.com/sphinx-doc/sphinx/commit/77483f28244dac1e7459d09397180812cfb36946"><code>77483f2</code></a> Add missing test decorator for <code>test_util_inspect</code> (<a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11321">#11321</a>)</li>
  <li>Additional commits viewable in <a href="https://github.com/sphinx-doc/sphinx/compare/v6.1.3...v6.2.1">compare view</a></li>
  </ul>
  </details>
  <br />


  [![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)

  Dependabot 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`.

  [//]: # (dependabot-automerge-start)
  [//]: # (dependabot-automerge-end)

  ---

  <details>
  <summary>Dependabot commands and options</summary>
  <br />

  You can trigger Dependabot actions by commenting on this PR:
  - `@dependabot rebase` will rebase this PR
  - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
  - `@dependabot merge` will merge this PR after your CI passes on it
  - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it
  - `@dependabot cancel merge` will cancel a previously requested merge and block automerging
  - `@dependabot reopen` will reopen this PR if it is closed
  - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
  - `@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)
  - `@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)
  - `@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)


  </details>

  <!-- readthedocs-preview datasette start -->
  ----
  :books: Documentation preview :books:: https://datasette--2064.org.readthedocs.build/en/2064/

  <!-- readthedocs-preview datasette end -->

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}


node_id: I_kwDOBm6k_c5kftT0
title: Datasette cannot be installed with Rye
state: closed
created_at: 2023-04-27T03:35:42Z
updated_at: 2023-04-27T05:09:36Z
closed_at: 2023-04-27T05:09:36Z
author_association: OWNER
type: issue
state_reason: completed
body:
  https://github.com/mitsuhiko/rye

  I tried this:

      rye install datasette

  But now:

  ```
  % ~/.rye/shims/datasette
  Traceback (most recent call last):
    File "/Users/simon/.rye/shims/datasette", line 5, in <module>
      from datasette.cli import cli
    File "/Users/simon/.rye/tools/datasette/lib/python3.11/site-packages/datasette/cli.py", line 17, in <module>
      from .app import (
    File "/Users/simon/.rye/tools/datasette/lib/python3.11/site-packages/datasette/app.py", line 14, in <module>
      import pkg_resources
  ModuleNotFoundError: No module named 'pkg_resources'
  ```
  I think that's because `setuptools` is not included in Rye.

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}


node_id: I_kwDOBm6k_c5kfvad
title: Failing test: httpx.InvalidURL: URL too long
state: closed
created_at: 2023-04-27T03:48:47Z
updated_at: 2023-04-27T04:27:50Z
closed_at: 2023-04-27T04:27:50Z
author_association: OWNER
type: issue
state_reason: completed
body:
  https://github.com/simonw/datasette/actions/runs/4815723640/jobs/8574667731
  ```
      def urlparse(url: str = "", **kwargs: typing.Optional[str]) -> ParseResult:
          # Initial basic checks on allowable URLs.
          # ---------------------------------------
      
          # Hard limit the maximum allowable URL length.
          if len(url) > MAX_URL_LENGTH:
  >           raise InvalidURL("URL too long")
  E           httpx.InvalidURL: URL too long

  /opt/hostedtoolcache/Python/3.7.16/x64/lib/python3.7/site-packages/httpx/_urlparse.py:155: InvalidURL
  =========================== short test summary info ============================
  FAILED tests/test_csv.py::test_max_csv_mb - httpx.InvalidURL: URL too long
  ```

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}


node_id: I_kwDOBm6k_c5kxwh6
title: Litestream-restored db: errors on 3.11 and 3.10.8; but works on py3.10.7 and 3.10.6
state: open
created_at: 2023-05-01T12:42:28Z
updated_at: 2023-05-03T00:16:03Z
author_association: NONE
type: issue
body:
  Hi! Wondering if this issue is limited to my local system or if it affects others as well. 

  It 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.

  To 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.

  ```sh
  # create new shell with 3.11.3
  litestream restore -o data/db.sqlite s3://mytestbucketxx/db
  sqlite3 data/db.sqlite  
  # SQLite version 3.41.2 2023-03-22 11:56:21
  # Enter ".help" for usage hints.
  # sqlite> .tables
  # _litestream_lock  _litestream_seq   movie           
  # sqlite> 
  ```

  However this get me an `OperationalError` when reading via datasette:

  <details>
  <summary>Error on 3.11.3 and 3.10.8</summary>

  ```sh
  datasette data/db.sqlite
  ```

  ```console
  /tester/.venv/lib/python3.11/site-packages/pkg_resources/__init__.py:121: DeprecationWarning: pkg_resources is deprecated as an API
    warnings.warn("pkg_resources is deprecated as an API", DeprecationWarning)
  Traceback (most recent call last):
    File "/tester/.venv/bin/datasette", line 8, in <module>
      sys.exit(cli())
               ^^^^^
    File "/tester/.venv/lib/python3.11/site-packages/click/core.py", line 1130, in __call__
      return self.main(*args, **kwargs)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^
    File "/tester/.venv/lib/python3.11/site-packages/click/core.py", line 1055, in main
      rv = self.invoke(ctx)
           ^^^^^^^^^^^^^^^^
    File "/tester/.venv/lib/python3.11/site-packages/click/core.py", line 1657, in invoke
      return _process_result(sub_ctx.command.invoke(sub_ctx))
                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    File "/tester/.venv/lib/python3.11/site-packages/click/core.py", line 1404, in invoke
      return ctx.invoke(self.callback, **ctx.params)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    File "/tester/.venv/lib/python3.11/site-packages/click/core.py", line 760, in invoke
      return __callback(*args, **kwargs)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^
    File "/tester/.venv/lib/python3.11/site-packages/datasette/cli.py", line 143, in wrapped
      return fn(*args, **kwargs)
             ^^^^^^^^^^^^^^^^^^^
    File "/tester/.venv/lib/python3.11/site-packages/datasette/cli.py", line 615, in serve
      asyncio.get_event_loop().run_until_complete(check_databases(ds))
    File "/Users/mv/.pyenv/versions/3.11.3/lib/python3.11/asyncio/base_events.py", line 653, in run_until_complete
      return future.result()
             ^^^^^^^^^^^^^^^
    File "/tester/.venv/lib/python3.11/site-packages/datasette/cli.py", line 660, in check_databases
      await database.execute_fn(check_connection)
    File "/tester/.venv/lib/python3.11/site-packages/datasette/database.py", line 213, in execute_fn
      return await asyncio.get_event_loop().run_in_executor(
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    File "/Users/mv/.pyenv/versions/3.11.3/lib/python3.11/concurrent/futures/thread.py", line 58, in run
      result = self.fn(*self.args, **self.kwargs)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    File "/tester/.venv/lib/python3.11/site-packages/datasette/database.py", line 211, in in_thread
      return fn(conn)
             ^^^^^^^^
    File "/tester/.venv/lib/python3.11/site-packages/datasette/utils/__init__.py", line 951, in check_connection
      for r in conn.execute(
               ^^^^^^^^^^^^^
  sqlite3.OperationalError: unable to open database file
  ```

  </details>


  <details>
  <summary>Works on 3.10.7, 3.10.6</summary>

  ```sh
  # create new shell with 3.10.7 / 3.10.6
  litestream restore -o data/db.sqlite s3://mytestbucketxx/db
  datasette data/db.sqlite
  # ...
  # INFO:     Uvicorn running on http://127.0.0.1:8001 (Press CTRL+C to quit)
  ```

  </details>

  In both scenarios, the only dependencies were the pinned python version and the latest Datasette version 0.64.

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}


node_id: PR_kwDOBm6k_c5PgNaA
title: Bump sphinx from 6.1.3 to 7.0.0
state: closed
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
type: pull
body:
  Bumps [sphinx](https://github.com/sphinx-doc/sphinx) from 6.1.3 to 7.0.0.
  <details>
  <summary>Release notes</summary>
  <p><em>Sourced from <a href="https://github.com/sphinx-doc/sphinx/releases">sphinx's releases</a>.</em></p>
  <blockquote>
  <h2>v7.0.0</h2>
  <p>Changelog: <a href="https://www.sphinx-doc.org/en/master/changes.html">https://www.sphinx-doc.org/en/master/changes.html</a></p>
  <h2>v7.0.0rc1</h2>
  <p>Changelog: <a href="https://www.sphinx-doc.org/en/master/changes.html">https://www.sphinx-doc.org/en/master/changes.html</a></p>
  <h2>v6.2.1</h2>
  <p>Changelog: <a href="https://www.sphinx-doc.org/en/master/changes.html">https://www.sphinx-doc.org/en/master/changes.html</a></p>
  <h2>v6.2.0</h2>
  <p>Changelog: <a href="https://www.sphinx-doc.org/en/master/changes.html">https://www.sphinx-doc.org/en/master/changes.html</a></p>
  </blockquote>
  </details>
  <details>
  <summary>Changelog</summary>
  <p><em>Sourced from <a href="https://github.com/sphinx-doc/sphinx/blob/master/CHANGES">sphinx's changelog</a>.</em></p>
  <blockquote>
  <h1>Release 7.0.0 (released Apr 29, 2023)</h1>
  <h2>Incompatible changes</h2>
  <ul>
  <li><a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11359">#11359</a>: Remove long-deprecated aliases for <code>MecabSplitter</code> and
  <code>DefaultSplitter</code> in <code>sphinx.search.ja</code>.</li>
  <li><a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11360">#11360</a>: Remove deprecated <code>make_old_id</code> functions in domain object
  description classes.</li>
  <li><a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11363">#11363</a>: Remove the Setuptools integration (<code>build_sphinx</code> hook in
  <code>setup.py</code>).</li>
  <li><a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11364">#11364</a>: Remove deprecated <code>sphinx.ext.napoleon.iterators</code> module.</li>
  <li><a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11365">#11365</a>: Remove support for the <code>jsdump</code> format in <code>sphinx.search</code>.</li>
  <li><a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11366">#11366</a>: Make <code>locale</code> a required argument to
  <code>sphinx.util.i18n.format_date()</code>.</li>
  <li><a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11370">#11370</a>: Remove deprecated <code>sphinx.util.stemmer</code> module.</li>
  <li><a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11371">#11371</a>: Remove deprecated <code>sphinx.pycode.ast.parse()</code> function.</li>
  <li><a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11372">#11372</a>: Remove deprecated <code>sphinx.io.read_doc()</code> function.</li>
  <li><a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11373">#11373</a>: Removed deprecated <code>sphinx.util.get_matching_files()</code> function.</li>
  <li><a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11378">#11378</a>: Remove deprecated <code>sphinx.util.docutils.is_html5_writer_available()</code>
  function.</li>
  <li><a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11379">#11379</a>: Make the <code>env</code> argument to <code>Builder</code> subclasses required.</li>
  <li><a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11380">#11380</a>: autosummary: Always emit grouped import exceptions.</li>
  <li><a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11381">#11381</a>: Remove deprecated <code>style</code> key for HTML templates.</li>
  <li><a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11382">#11382</a>: Remove deprecated <code>sphinx.writers.latex.LaTeXTranslator.docclasses</code>
  attribute.</li>
  <li><a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11383">#11383</a>: Remove deprecated <code>sphinx.builders.html.html5_ready</code> and
  <code>sphinx.builders.html.HTMLTranslator</code> attributes.</li>
  <li><a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11385">#11385</a>: Remove support for HTML 4 output.</li>
  </ul>
  <h1>Release 6.2.1 (released Apr 25, 2023)</h1>
  <h2>Bugs fixed</h2>
  <ul>
  <li><a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11355">#11355</a>: Revert the default type of :confval:<code>nitpick_ignore</code> and
  :confval:<code>nitpick_ignore_regex</code> to <code>list</code>.</li>
  </ul>
  <h1>Release 6.2.0 (released Apr 23, 2023)</h1>
  <h2>Dependencies</h2>
  <ul>
  <li>Require Docutils 0.18.1 or greater.</li>
  </ul>
  <h2>Incompatible changes</h2>
  <!-- raw HTML omitted -->
  </blockquote>
  <p>... (truncated)</p>
  </details>
  <details>
  <summary>Commits</summary>
  <ul>
  <li><a href="https://github.com/sphinx-doc/sphinx/commit/d568b2f4f7cca743fcbf70814d15602d8129b790"><code>d568b2f</code></a> Bump to 7.0.0 final</li>
  <li><a href="https://github.com/sphinx-doc/sphinx/commit/ff79edf353f5cc6e02036f58e0295dc704c5e681"><code>ff79edf</code></a> Remove <code>jsdump</code> references post removal</li>
  <li><a href="https://github.com/sphinx-doc/sphinx/commit/1a5133ac391931d8e0e2a271fe8ea9c505176908"><code>1a5133a</code></a> Bump to 7.0.0rc1 final</li>
  <li><a href="https://github.com/sphinx-doc/sphinx/commit/5795fc7f9f7a5fe968cd11b961fc33fbd952a152"><code>5795fc7</code></a> Update <code>sphinx.deprecation</code> for Sphinx 7.0 (<a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11386">#11386</a>)</li>
  <li><a href="https://github.com/sphinx-doc/sphinx/commit/6202087f912a2ae32808865072f884ea44cd31cb"><code>6202087</code></a> Add a note to CHANGES for PR 11385</li>
  <li><a href="https://github.com/sphinx-doc/sphinx/commit/ad473730a3763f241e9aaea1a87d1893f01b86fd"><code>ad47373</code></a> Remove HTML 4 support (<a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11385">#11385</a>)</li>
  <li><a href="https://github.com/sphinx-doc/sphinx/commit/3e3251d3ba4f1e5fa6d34d995505f4d3ace5acad"><code>3e3251d</code></a> Remove <code>HTMLTranslator</code> and <code>html5_ready</code> from <code>sphinx.builders.html</code> (...</li>
  <li><a href="https://github.com/sphinx-doc/sphinx/commit/77fd819a09881102bdd48593cc69ec164b2495c8"><code>77fd819</code></a> Remove deprecated <code>LaTeXTranslator.docclasses</code> attribute (<a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11382">#11382</a>)</li>
  <li><a href="https://github.com/sphinx-doc/sphinx/commit/4be56f3b7ddf44265d2e7a8f26a33ba46be52ab9"><code>4be56f3</code></a> Remove deprecated <code>style</code> key for HTML templates (<a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11381">#11381</a>)</li>
  <li><a href="https://github.com/sphinx-doc/sphinx/commit/49027a9ae61d0d00016182025f68239a50ba4c09"><code>49027a9</code></a> Autosummary: Always emit grouped <code>ImportError</code> exceptions (<a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11380">#11380</a>)</li>
  <li>Additional commits viewable in <a href="https://github.com/sphinx-doc/sphinx/compare/v6.1.3...v7.0.0">compare view</a></li>
  </ul>
  </details>
  <br />


  [![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)

  Dependabot 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`.

  [//]: # (dependabot-automerge-start)
  [//]: # (dependabot-automerge-end)

  ---

  <details>
  <summary>Dependabot commands and options</summary>
  <br />

  You can trigger Dependabot actions by commenting on this PR:
  - `@dependabot rebase` will rebase this PR
  - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
  - `@dependabot merge` will merge this PR after your CI passes on it
  - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it
  - `@dependabot cancel merge` will cancel a previously requested merge and block automerging
  - `@dependabot reopen` will reopen this PR if it is closed
  - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
  - `@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)
  - `@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)
  - `@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)


  </details>

  <!-- readthedocs-preview datasette start -->
  ----
  :books: Documentation preview :books:: https://datasette--2068.org.readthedocs.build/en/2068/

  <!-- readthedocs-preview datasette end -->

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}


node_id: I_kwDOCGYnMM5lDi6L
title: `table.upsert_all` fails to write rows when `not_null` is present
state: closed
created_at: 2023-05-04T07:30:38Z
updated_at: 2023-05-08T20:06:35Z
closed_at: 2023-05-08T19:27:02Z
author_association: NONE
type: issue
state_reason: completed
body:
  I found an odd bug today, where calls to `table.upsert_all` don't write rows if you include the `not_null` kwarg.

  ## Repro Example

  ```py
  from sqlite_utils import Database

  db = Database("upsert-test.db")

  db["comments"].upsert_all(
      [{"id": 1, "name": "david"}],
      pk="id",
      not_null=["name"],
  )

  assert list(db["comments"].rows) # err!
  ```

  The schema is correctly created:

  ```sql
  CREATE TABLE [comments] (
     [id] INTEGER PRIMARY KEY,
     [name] TEXT NOT NULL
  )
  ```

  But no rows are created. Removing either the `not_null` kwargs works as expected, as does an `insert_all` call.

  ## Version Info

  - Python: `3.11.0`
  - sqlite-utils: `3.30`
  - sqlite: `3.39.5 2022-10-14`

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}


node_id: I_kwDOBm6k_c5lQqAe
title: [BUG] Cannot insert new data to deployed instance
state: open
created_at: 2023-05-07T02:59:42Z
updated_at: 2023-05-07T03:17:35Z
author_association: NONE
type: issue
body:
  ## Summary

  Recently, I deployed an instance of datasette to Vercel with the following plugins:

  - datasette-auth-tokens
  - datasette-insert

  With 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:

  ```console
  File "/var/task/datasette/database.py", line 179, in _execute_writes
  conn = self.connect(write=True)
  File "/var/task/datasette/database.py", line 93, in connect
  assert not (write and not self.is_mutable)
  AssertionError
  ``` 

  <img width="1380" alt="image" src="https://user-images.githubusercontent.com/31861128/236655274-3fd5e16f-4e06-4ba8-87ff-41130b8ebe90.png">

  I think it is a potential bug.

  ## Reproduce

  <details><summary>metadata.json</summary>
  </br>

  ```json
  {
    "plugins": {
      "datasette-insert": {
        "allow": {
          "id": "*"
        }
      },
      "datasette-auth-tokens": {
        "tokens": [
          {
            "token": {
              "$env": "INSERT_TOKEN"
            },
            "actor": {
              "id": "repeater"
            }
          }
        ],
        "param": "_auth_token"
      }
    }
  }
  ```

  </details>

  <details><summary>commands</summary>
  </br>

  ```bash
  # deploy
  datasette publish vercel remote.db \
    --project=repeater-bot-sqlite \
    --metadata metadata.json \
    --install datasette-auth-tokens \
    --install datasette-insert \
    --vercel-json=vercel.json

  # test insert
  cat fixtures/dogs.json | curl --request POST -d @- -H "Authorization: Bearer <token>" \
    'https://repeater-bot-sqlite.vercel.app/-/insert/remote/dogs?pk=id'
  ```

  </details>

  <details><summary>logs</summary>
  </br>

  ```console
  Traceback (most recent call last):
  File "/var/task/datasette/app.py", line 1354, in route_path
  response = await view(request, send)
  File "/var/task/datasette/app.py", line 1500, in async_view_fn
  response = await async_call_with_supported_arguments(
  File "/var/task/datasette/utils/__init__.py", line 1005, in async_call_with_supported_arguments
  return await fn(*call_with)
  File "/var/task/datasette_insert/__init__.py", line 14, in insert_or_upsert
  response = await insert_or_upsert_implementation(request, datasette)
  File "/var/task/datasette_insert/__init__.py", line 91, in insert_or_upsert_implementation
  table_count = await db.execute_write_fn(write_in_thread, block=True)
  File "/var/task/datasette/database.py", line 167, in execute_write_fn
  raise result
  File "/var/task/datasette/database.py", line 179, in _execute_writes
  conn = self.connect(write=True)
  File "/var/task/datasette/database.py", line 93, in connect
  assert not (write and not self.is_mutable)
  AssertionError
  ```

  </details>

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}


node_id: I_kwDOCGYnMM5lR1an
title: `--raw-lines` option, like `--raw` for multiple lines
state: closed
created_at: 2023-05-07T18:07:46Z
updated_at: 2023-05-07T18:43:24Z
closed_at: 2023-05-07T18:26:18Z
author_association: OWNER
type: issue
state_reason: completed
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.

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}


node_id: I_kwDOCGYnMM5lR3_H
title: sphinx.builders.linkcheck build error
state: closed
created_at: 2023-05-07T18:37:09Z
updated_at: 2023-05-08T04:56:13Z
closed_at: 2023-05-07T18:42:36Z
author_association: OWNER
type: issue
state_reason: completed
body:
  https://readthedocs.org/projects/sqlite-utils/builds/20512693/
  ```
   Running Sphinx v6.2.1

  Traceback (most recent call last):
    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
      mod = import_module(extname)
    File "/home/docs/checkouts/readthedocs.org/user_builds/sqlite-utils/envs/latest/lib/python3.8/importlib/__init__.py", line 127, in import_module
      return _bootstrap._gcd_import(name[level:], package, level)
    File "<frozen importlib._bootstrap>", line 1014, in _gcd_import
    File "<frozen importlib._bootstrap>", line 991, in _find_and_load
    File "<frozen importlib._bootstrap>", line 975, in _find_and_load_unlocked
    File "<frozen importlib._bootstrap>", line 671, in _load_unlocked
    File "<frozen importlib._bootstrap_external>", line 783, in exec_module
    File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
    File "/home/docs/checkouts/readthedocs.org/user_builds/sqlite-utils/envs/latest/lib/python3.8/site-packages/sphinx/builders/linkcheck.py", line 20, in <module>
      from requests import Response
    File "/home/docs/checkouts/readthedocs.org/user_builds/sqlite-utils/envs/latest/lib/python3.8/site-packages/requests/__init__.py", line 43, in <module>
      import urllib3
    File "/home/docs/checkouts/readthedocs.org/user_builds/sqlite-utils/envs/latest/lib/python3.8/site-packages/urllib3/__init__.py", line 38, in <module>
      raise ImportError(
  ImportError: 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

  The above exception was the direct cause of the following exception:

  Traceback (most recent call last):
    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
      app = Sphinx(args.sourcedir, args.confdir, args.outputdir,
    File "/home/docs/checkouts/readthedocs.org/user_builds/sqlite-utils/envs/latest/lib/python3.8/site-packages/sphinx/application.py", line 225, in __init__
      self.setup_extension(extension)
    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
      self.registry.load_extension(self, extname)
    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
      raise ExtensionError(__('Could not import extension %s') % extname,
  sphinx.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)

  Extension error:
  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)
  ```

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}


node_id: I_kwDOCGYnMM5lYMNJ
title: Get tests to pass with `pytest -Werror`
state: open
created_at: 2023-05-08T19:57:23Z
updated_at: 2023-05-08T19:59:35Z
author_association: OWNER
body:
  Inspired by:
  - #534

type: issue
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}


node_id: I_kwDOCGYnMM5lYjo1
title: Remove `skip_false=True` and `--no-skip-false` in `sqlite-utils` 4.0
state: open
created_at: 2023-05-08T21:04:28Z
updated_at: 2023-05-08T21:07:41Z
author_association: OWNER
type: issue
body:
  Following:
  - #527

  The 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.

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}


node_id: I_kwDOCGYnMM5lY30d
title: Tests broken on Windows due to new convert() lambda names
state: closed
created_at: 2023-05-08T22:11:29Z
updated_at: 2023-05-08T22:19:04Z
closed_at: 2023-05-08T22:19:04Z
author_association: OWNER
type: issue
state_reason: completed
body:
  https://github.com/simonw/sqlite-utils/actions/runs/4920084038/jobs/8788501314
  ```python
  sql = 'update [example] set [dt] = lambda_-9223371942137158589([dt]);'
  ```
  From:
  - #526

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}


node_id: I_kwDOBm6k_c5ld90v
title: Mechanism for deploying a preview of a branch using Vercel
state: closed
created_at: 2023-05-09T16:21:45Z
updated_at: 2023-05-09T16:25:00Z
closed_at: 2023-05-09T16:24:31Z
author_association: OWNER
type: issue
state_reason: completed
body:
  I prototyped that here: https://github.com/simonw/one-off-actions/blob/main/.github/workflows/deploy-datasette-branch-preview.yml

  It deployed the `json-extras-query` branch here: https://datasette-preview-json-extras-query.vercel.app/

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}


node_id: I_kwDOBm6k_c5lznkM
title: Faceting doesn't work against integer columns in views
state: open
created_at: 2023-05-12T18:20:10Z
updated_at: 2023-05-12T18:24:07Z
author_association: OWNER
type: issue
body:
  Spotted this issue here: https://til.simonwillison.net/datasette/baseline

  I had to do this workaround:
  ```sql
  create view baseline as select
    _key,
    spec,
    '' || json_extract(status, '$.is_baseline') as is_baseline,
    json_extract(status, '$.since') as baseline_since,
    json_extract(status, '$.support.chrome') as baseline_chrome,
    json_extract(status, '$.support.edge') as baseline_edge,
    json_extract(status, '$.support.firefox') as baseline_firefox,
    json_extract(status, '$.support.safari') as baseline_safari,
    compat_features,
    caniuse,
    usage_stats,
    status
  from
    [index]
  ```
  I 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.

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}


node_id: PR_kwDOBm6k_c5QdMea
title: sort files by mtime
state: open
created_at: 2023-05-14T15:25:15Z
updated_at: 2023-05-14T15:25:29Z
author_association: FIRST_TIME_CONTRIBUTOR
pull_request: simonw/datasette/pulls/2074
type: pull
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 ;)

  <!-- readthedocs-preview datasette start -->
  ----
  :books: Documentation preview :books:: https://datasette--2074.org.readthedocs.build/en/2074/

  <!-- readthedocs-preview datasette end -->

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}


node_id: PR_kwDOBm6k_c5QhIL2
title: Bump sphinx from 6.1.3 to 7.0.1
state: closed
created_at: 2023-05-15T13:59:31Z
updated_at: 2023-07-25T13:28:39Z
closed_at: 2023-07-25T13:28:36Z
author_association: CONTRIBUTOR
pull_request: simonw/datasette/pulls/2075
type: pull
body:
  Bumps [sphinx](https://github.com/sphinx-doc/sphinx) from 6.1.3 to 7.0.1.
  <details>
  <summary>Release notes</summary>
  <p><em>Sourced from <a href="https://github.com/sphinx-doc/sphinx/releases">sphinx's releases</a>.</em></p>
  <blockquote>
  <h2>v7.0.1</h2>
  <p>Changelog: <a href="https://www.sphinx-doc.org/en/master/changes.html">https://www.sphinx-doc.org/en/master/changes.html</a></p>
  <h2>v7.0.0</h2>
  <p>Changelog: <a href="https://www.sphinx-doc.org/en/master/changes.html">https://www.sphinx-doc.org/en/master/changes.html</a></p>
  <h2>v7.0.0rc1</h2>
  <p>Changelog: <a href="https://www.sphinx-doc.org/en/master/changes.html">https://www.sphinx-doc.org/en/master/changes.html</a></p>
  <h2>v6.2.1</h2>
  <p>Changelog: <a href="https://www.sphinx-doc.org/en/master/changes.html">https://www.sphinx-doc.org/en/master/changes.html</a></p>
  <h2>v6.2.0</h2>
  <p>Changelog: <a href="https://www.sphinx-doc.org/en/master/changes.html">https://www.sphinx-doc.org/en/master/changes.html</a></p>
  </blockquote>
  </details>
  <details>
  <summary>Changelog</summary>
  <p><em>Sourced from <a href="https://github.com/sphinx-doc/sphinx/blob/master/CHANGES">sphinx's changelog</a>.</em></p>
  <blockquote>
  <h1>Release 7.0.1 (released May 12, 2023)</h1>
  <h2>Dependencies</h2>
  <ul>
  <li><a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11411">#11411</a>: Support <code>Docutils 0.20</code>_. Patch by Adam Turner.</li>
  </ul>
  <p>.. _Docutils 0.20: <a href="https://docutils.sourceforge.io/RELEASE-NOTES.html#release-0-20-2023-05-04">https://docutils.sourceforge.io/RELEASE-NOTES.html#release-0-20-2023-05-04</a></p>
  <h2>Bugs fixed</h2>
  <ul>
  <li><a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11418">#11418</a>: Clean up remaining references to <code>sphinx.setup_command</code>
  following the removal of support for setuptools.
  Patch by Willem Mulder.</li>
  </ul>
  <h1>Release 7.0.0 (released Apr 29, 2023)</h1>
  <h2>Incompatible changes</h2>
  <ul>
  <li><a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11359">#11359</a>: Remove long-deprecated aliases for <code>MecabSplitter</code> and
  <code>DefaultSplitter</code> in <code>sphinx.search.ja</code>.</li>
  <li><a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11360">#11360</a>: Remove deprecated <code>make_old_id</code> functions in domain object
  description classes.</li>
  <li><a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11363">#11363</a>: Remove the Setuptools integration (<code>build_sphinx</code> hook in
  <code>setup.py</code>).</li>
  <li><a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11364">#11364</a>: Remove deprecated <code>sphinx.ext.napoleon.iterators</code> module.</li>
  <li><a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11365">#11365</a>: Remove support for the <code>jsdump</code> format in <code>sphinx.search</code>.</li>
  <li><a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11366">#11366</a>: Make <code>locale</code> a required argument to
  <code>sphinx.util.i18n.format_date()</code>.</li>
  <li><a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11370">#11370</a>: Remove deprecated <code>sphinx.util.stemmer</code> module.</li>
  <li><a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11371">#11371</a>: Remove deprecated <code>sphinx.pycode.ast.parse()</code> function.</li>
  <li><a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11372">#11372</a>: Remove deprecated <code>sphinx.io.read_doc()</code> function.</li>
  <li><a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11373">#11373</a>: Removed deprecated <code>sphinx.util.get_matching_files()</code> function.</li>
  <li><a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11378">#11378</a>: Remove deprecated <code>sphinx.util.docutils.is_html5_writer_available()</code>
  function.</li>
  <li><a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11379">#11379</a>: Make the <code>env</code> argument to <code>Builder</code> subclasses required.</li>
  <li><a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11380">#11380</a>: autosummary: Always emit grouped import exceptions.</li>
  <li><a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11381">#11381</a>: Remove deprecated <code>style</code> key for HTML templates.</li>
  <li><a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11382">#11382</a>: Remove deprecated <code>sphinx.writers.latex.LaTeXTranslator.docclasses</code>
  attribute.</li>
  <li><a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11383">#11383</a>: Remove deprecated <code>sphinx.builders.html.html5_ready</code> and
  <code>sphinx.builders.html.HTMLTranslator</code> attributes.</li>
  <li><a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11385">#11385</a>: Remove support for HTML 4 output.</li>
  </ul>
  <h1>Release 6.2.1 (released Apr 25, 2023)</h1>
  <!-- raw HTML omitted -->
  </blockquote>
  <p>... (truncated)</p>
  </details>
  <details>
  <summary>Commits</summary>
  <ul>
  <li><a href="https://github.com/sphinx-doc/sphinx/commit/d48cc783b6e48b99cbbcf5462f44c59a4ed78e6a"><code>d48cc78</code></a> Bump to 7.0.1 final</li>
  <li><a href="https://github.com/sphinx-doc/sphinx/commit/de6b18ac7de317030be4344ea7a9d553c423ffcf"><code>de6b18a</code></a> Remove remaining references to the setuptools integration (<a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11418">#11418</a>)</li>
  <li><a href="https://github.com/sphinx-doc/sphinx/commit/db546189ce1d2a345f4399367ced6ecdd538be5d"><code>db54618</code></a> Support Docutils 0.20 (<a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11411">#11411</a>)</li>
  <li><a href="https://github.com/sphinx-doc/sphinx/commit/8942a1dddf2355928f088d6b631db8658034eaae"><code>8942a1d</code></a> Test with Docutils 0.20</li>
  <li><a href="https://github.com/sphinx-doc/sphinx/commit/c9d0933e5d8e34aa9d2c1d88c5a80b46b575730e"><code>c9d0933</code></a> linkcheck: Use context managers for HTTP requests (<a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11318">#11318</a>)</li>
  <li><a href="https://github.com/sphinx-doc/sphinx/commit/2b1c106bbff5265e8a6076318db5d083c329d575"><code>2b1c106</code></a> Update documentation workflow</li>
  <li><a href="https://github.com/sphinx-doc/sphinx/commit/ba7408209e84ee413f240afc20f3c6b484a81f8f"><code>ba74082</code></a> Change concurrency groups for GitHub workflows</li>
  <li><a href="https://github.com/sphinx-doc/sphinx/commit/b546879539200ec4128bcc6d0ed911ebf28bb3cb"><code>b546879</code></a> Bump version</li>
  <li><a href="https://github.com/sphinx-doc/sphinx/commit/d568b2f4f7cca743fcbf70814d15602d8129b790"><code>d568b2f</code></a> Bump to 7.0.0 final</li>
  <li><a href="https://github.com/sphinx-doc/sphinx/commit/ff79edf353f5cc6e02036f58e0295dc704c5e681"><code>ff79edf</code></a> Remove <code>jsdump</code> references post removal</li>
  <li>Additional commits viewable in <a href="https://github.com/sphinx-doc/sphinx/compare/v6.1.3...v7.0.1">compare view</a></li>
  </ul>
  </details>
  <br />


  [![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)

  You can trigger a rebase of this PR by commenting `@dependabot rebase`.

  [//]: # (dependabot-automerge-start)
  [//]: # (dependabot-automerge-end)

  ---

  <details>
  <summary>Dependabot commands and options</summary>
  <br />

  You can trigger Dependabot actions by commenting on this PR:
  - `@dependabot rebase` will rebase this PR
  - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
  - `@dependabot merge` will merge this PR after your CI passes on it
  - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it
  - `@dependabot cancel merge` will cancel a previously requested merge and block automerging
  - `@dependabot reopen` will reopen this PR if it is closed
  - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
  - `@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)
  - `@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)
  - `@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)


  </details>

  <!-- readthedocs-preview datasette start -->
  ----
  :books: Documentation preview :books:: https://datasette--2075.org.readthedocs.build/en/2075/

  <!-- readthedocs-preview datasette end -->
  > **Note**
  > Automatic rebases have been disabled on this pull request as it has been open for over 30 days.

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}


node_id: PR_kwDOBm6k_c5QzEAM
title: Datsette gpt plugin
state: open
created_at: 2023-05-18T11:22:30Z
updated_at: 2023-05-18T11:22:45Z
author_association: FIRST_TIME_CONTRIBUTOR
pull_request: simonw/datasette/pulls/2076
type: pull
body:
  <!-- readthedocs-preview datasette start -->
  ----
  :books: Documentation preview :books:: https://datasette--2076.org.readthedocs.build/en/2076/

  <!-- readthedocs-preview datasette end -->

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}


node_id: I_kwDOCGYnMM5mbneG
title: New options for analyze-tables --common-limit --no-most and --no-least
state: closed
created_at: 2023-05-21T14:03:19Z
updated_at: 2023-05-21T17:03:06Z
closed_at: 2023-05-21T16:19:31Z
author_association: OWNER
type: issue
state_reason: completed
body:
  The "least common" section is frequently uninteresting, especially for huge tables with a large number of repeated-once values.

      sqlite-utils analyze-tables content.db repos --common-limit 20 --no-least

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}


node_id: I_kwDOCGYnMM5mboB6
title: Try out Trogon for a tui interface
state: closed
created_at: 2023-05-21T14:08:25Z
updated_at: 2023-05-21T19:33:13Z
closed_at: 2023-05-21T18:41:58Z
author_association: OWNER
body: https://github.com/Textualize/trogon
type: issue
state_reason: completed
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}


node_id: PR_kwDOCGYnMM5Q9VH0
title: Analyze tables options: --common-limit, --no-most, --no-least
state: closed
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
type: pull
body:
  Refs #544

  - [x] Documentation for CLI options
  - [x] Documentation for new Python API parameters:  `most_common: bool` and `least_common: bool`
  - [x] Tests for CLI
  - [x] Tests for Python API

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}


node_id: I_kwDOCGYnMM5mb1Sp
title: No need to show common values if everything is null
state: closed
created_at: 2023-05-21T17:05:07Z
updated_at: 2023-05-21T17:19:21Z
closed_at: 2023-05-21T17:19:21Z
author_association: OWNER
type: issue
state_reason: completed
body:
  Noticed this:

  ```
  % sqlite-utils analyze-tables content.db repos -c delete_branch_on_merge --common-limit 20 --no-least
  repos.delete_branch_on_merge: (1/1)

    Total rows: 158
    Null rows: 158
    Blank rows: 0

    Distinct values: 0

    Most common:
      158: None
  ```

  The `158: None` there is duplicate information considering we already know there are 158/158 null rows.

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}


node_id: I_kwDOCGYnMM5mb2Z5
title: analyze-tables should validate provide --column names
state: closed
created_at: 2023-05-21T17:20:24Z
updated_at: 2023-05-21T17:35:52Z
closed_at: 2023-05-21T17:35:52Z
author_association: OWNER
type: issue
state_reason: completed
body:
  Noticed this while testing:
  - #547 

  If you pass a non-existent column to `-c/--column` you don't get an error message.

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}


node_id: PR_kwDOCGYnMM5Q9cAv
title: TUI powered by Trogon
state: closed
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
type: pull
body:
  Refs:
  - #545

  <!-- readthedocs-preview sqlite-utils start -->
  ----
  :books: Documentation preview :books:: https://sqlite-utils--549.org.readthedocs.build/en/549/

  <!-- readthedocs-preview sqlite-utils end -->

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}


node_id: I_kwDOCGYnMM5mb7B0
title: AttributeError: 'EntryPoints' object has no attribute 'get' for flake8 on Python 3.7
state: closed
created_at: 2023-05-21T18:24:39Z
updated_at: 2023-05-21T18:42:25Z
closed_at: 2023-05-21T18:41:58Z
author_association: OWNER
type: issue
state_reason: completed
body:
  https://github.com/simonw/sqlite-utils/actions/runs/5039064797/jobs/9036965488

  ```
  Traceback (most recent call last):
    File "/opt/hostedtoolcache/Python/3.7.16/x64/bin/flake8", line 8, in <module>
      sys.exit(main())
    File "/opt/hostedtoolcache/Python/3.7.16/x64/lib/python3.7/site-packages/flake8/main/cli.py", line 22, in main
      app.run(argv)
    File "/opt/hostedtoolcache/Python/3.7.16/x64/lib/python3.7/site-packages/flake8/main/application.py", line 363, in run
      self._run(argv)
    File "/opt/hostedtoolcache/Python/3.7.16/x64/lib/python3.7/site-packages/flake8/main/application.py", line 350, in _run
      self.initialize(argv)
    File "/opt/hostedtoolcache/Python/3.7.16/x64/lib/python3.7/site-packages/flake8/main/application.py", line 330, in initialize
      self.find_plugins(config_finder)
    File "/opt/hostedtoolcache/Python/3.7.16/x64/lib/python3.7/site-packages/flake8/main/application.py", line 153, in find_plugins
      self.check_plugins = plugin_manager.Checkers(local_plugins.extension)
    File "/opt/hostedtoolcache/Python/3.7.16/x64/lib/python3.7/site-packages/flake8/plugins/manager.py", line 357, in __init__
      self.namespace, local_plugins=local_plugins
    File "/opt/hostedtoolcache/Python/3.7.16/x64/lib/python3.7/site-packages/flake8/plugins/manager.py", line 238, in __init__
      self._load_entrypoint_plugins()
    File "/opt/hostedtoolcache/Python/3.7.16/x64/lib/python3.7/site-packages/flake8/plugins/manager.py", line 254, in _load_entrypoint_plugins
      eps = importlib_metadata.entry_points().get(self.namespace, ())
  AttributeError: 'EntryPoints' object has no attribute 'get'
  Error: Process completed with exit code 1.
  ```

reactions:
  {"url": "https://api.github.com/repos/simonw/sqlite-utils/issues/550/reactions", "total_count": 1, "+1": 1, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0}


node_id: I_kwDOCGYnMM5mb-Aj
title: Make as many examples in the CLI docs as possible copy-and-pastable
state: closed
created_at: 2023-05-21T19:04:10Z
updated_at: 2023-05-21T21:04:04Z
closed_at: 2023-05-21T20:57:24Z
author_association: OWNER
type: issue
state_reason: completed
body:
  e.g. in this section:

  https://sqlite-utils.datasette.io/en/stable/cli.html#running-queries-directly-against-csv-or-json

  <img width="771" alt="image" src="https://github.com/simonw/sqlite-utils/assets/9599/3935111d-441e-4edb-9100-ce210117dbe5">

  The little copy button will also copy the `$ ` which breaks the examples when copied.

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}


node_id: I_kwDOCGYnMM5mb_JZ
title: Document how to setup shell auto-completion
state: closed
created_at: 2023-05-21T19:20:41Z
updated_at: 2023-05-21T21:05:16Z
closed_at: 2023-05-21T21:03:40Z
author_association: OWNER
type: issue
state_reason: completed
body:
  https://click.palletsprojects.com/en/8.1.x/shell-completion/

  This works for `zsh`:

      eval "$(_SQLITE_UTILS_COMPLETE=zsh_source sqlite-utils)"

  This will probably work for `bash`:

      eval "$(_SQLITE_UTILS_COMPLETE=bash_source sqlite-utils)"

  Need 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.

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}


node_id: PR_kwDOCGYnMM5Q9lY4
title: Reformatted CLI examples in docs
state: closed
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
type: pull
body:
  Refs:
  - #551

  <!-- readthedocs-preview sqlite-utils start -->
  ----
  :books: Documentation preview :books:: https://sqlite-utils--553.org.readthedocs.build/en/553/

  <!-- readthedocs-preview sqlite-utils end -->

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}


node_id: PR_kwDOBm6k_c5RBXH_
title: Bump furo from 2023.3.27 to 2023.5.20
state: closed
created_at: 2023-05-22T13:58:16Z
updated_at: 2023-07-27T13:40:55Z
closed_at: 2023-07-27T13:40:53Z
author_association: CONTRIBUTOR
pull_request: simonw/datasette/pulls/2077
type: pull
body:
  Bumps [furo](https://github.com/pradyunsg/furo) from 2023.3.27 to 2023.5.20.
  <details>
  <summary>Changelog</summary>
  <p><em>Sourced from <a href="https://github.com/pradyunsg/furo/blob/main/docs/changelog.md">furo's changelog</a>.</em></p>
  <blockquote>
  <h1>Changelog</h1>
  <!-- raw HTML omitted -->
  <h2>2023.05.20 -- Unassuming Ultramarine</h2>
  <ul>
  <li>✨ Add support for Sphinx 7.</li>
  <li>Drop support for Sphinx 5.</li>
  <li>Improve the screen-reader label for sidebar collapse.</li>
  <li>Make it easier to create derived themes from Furo.</li>
  <li>Bump all JS dependencies (NodeJS and npm packages).</li>
  </ul>
  <h2>2023.03.27 -- Tasty Tangerine</h2>
  <ul>
  <li>Regenerate with newer version of sphinx-theme-builder, to fix RECORD hashes.</li>
  <li>Add missing class to Font Awesome examples</li>
  </ul>
  <h2>2023.03.23 -- Sassy Saffron</h2>
  <ul>
  <li>Update Python version classifiers.</li>
  <li>Increase the icon size in mobile header.</li>
  <li>Increase admonition title bg opacity.</li>
  <li>Change the default API background to transparent.</li>
  <li>Transition the API background change.</li>
  <li>Remove the &quot;indent&quot; of API entries which have a background.</li>
  <li>Break long inline code literals.</li>
  </ul>
  <h2>2022.12.07 -- Reverent Raspberry</h2>
  <ul>
  <li>✨ Add support for Sphinx 6.</li>
  <li>✨ Improve footnote presentation with docutils 0.18+.</li>
  <li>Drop support for Sphinx 4.</li>
  <li>Improve documentation about what the edit button does.</li>
  <li>Improve handling of empty-flexboxes for better print experience on Chrome.</li>
  <li>Improve styling for inline signatures.</li>
  <li>Replace the <code>meta</code> generator tag with a comment.</li>
  <li>Tweak labels with icons to prevent users selecting icons as text on touch.</li>
  </ul>
  <h2>2022.09.29 -- Quaint Quartz</h2>
  <ul>
  <li>Add ability to set arbitrary URLs for edit button.</li>
  </ul>
  <!-- raw HTML omitted -->
  </blockquote>
  <p>... (truncated)</p>
  </details>
  <details>
  <summary>Commits</summary>
  <ul>
  <li><a href="https://github.com/pradyunsg/furo/commit/d2c9ca852542820632361f05521b5c94824d1fdc"><code>d2c9ca8</code></a> Prepare release: 2023.05.20</li>
  <li><a href="https://github.com/pradyunsg/furo/commit/662d21b66c0422693e3bcdac87e1c605ed95b32f"><code>662d21b</code></a> Update changelog</li>
  <li><a href="https://github.com/pradyunsg/furo/commit/591780b0f01378aef769da40e5d7a917304bd1a5"><code>591780b</code></a> Bump compatible Sphinx version</li>
  <li><a href="https://github.com/pradyunsg/furo/commit/c2e7837352d290f75579b1859233e9c77afc8911"><code>c2e7837</code></a> Bump NodeJS and package versions</li>
  <li><a href="https://github.com/pradyunsg/furo/commit/dd85574e803bb5e9416be66696acc1a6f91f3470"><code>dd85574</code></a> Use the reference HtmlFormatter class defined on PygmentsBridge. (<a href="https://redirect.github.com/pradyunsg/furo/issues/657">#657</a>)</li>
  <li><a href="https://github.com/pradyunsg/furo/commit/6bff41949f18dc204cfaeae82c42a7197ff3a200"><code>6bff419</code></a> Fix broken link (<a href="https://redirect.github.com/pradyunsg/furo/issues/654">#654</a>)</li>
  <li><a href="https://github.com/pradyunsg/furo/commit/e7f732ea5133d29fc6ca62af0455b16ffaab00dc"><code>e7f732e</code></a> Improve the screen-reader label for sidebar collapse</li>
  <li><a href="https://github.com/pradyunsg/furo/commit/48c0bf2aa983fb1ccd79b4167fe85387249afedf"><code>48c0bf2</code></a> Drop the check for the theme name</li>
  <li><a href="https://github.com/pradyunsg/furo/commit/1b17d8102079c3ec2a49f57ebc1931f6869cd61d"><code>1b17d81</code></a> [pre-commit.ci] pre-commit autoupdate (<a href="https://redirect.github.com/pradyunsg/furo/issues/646">#646</a>)</li>
  <li><a href="https://github.com/pradyunsg/furo/commit/4904fd5ce0c74386eaee3bd07940aa46254a11ce"><code>4904fd5</code></a> Remove Python 3.8 constraint from Black pre-commit config (<a href="https://redirect.github.com/pradyunsg/furo/issues/647">#647</a>)</li>
  <li>Additional commits viewable in <a href="https://github.com/pradyunsg/furo/compare/2023.03.27...2023.05.20">compare view</a></li>
  </ul>
  </details>
  <br />


  [![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)

  You can trigger a rebase of this PR by commenting `@dependabot rebase`.

  [//]: # (dependabot-automerge-start)
  [//]: # (dependabot-automerge-end)

  ---

  <details>
  <summary>Dependabot commands and options</summary>
  <br />

  You can trigger Dependabot actions by commenting on this PR:
  - `@dependabot rebase` will rebase this PR
  - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
  - `@dependabot merge` will merge this PR after your CI passes on it
  - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it
  - `@dependabot cancel merge` will cancel a previously requested merge and block automerging
  - `@dependabot reopen` will reopen this PR if it is closed
  - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
  - `@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)
  - `@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)
  - `@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)


  </details>

  <!-- readthedocs-preview datasette start -->
  ----
  :books: Documentation preview :books:: https://datasette--2077.org.readthedocs.build/en/2077/

  <!-- readthedocs-preview datasette end -->
  > **Note**
  > Automatic rebases have been disabled on this pull request as it has been open for over 30 days.

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}


node_id: I_kwDOCGYnMM5mhpji
title: `IndexError` when doing `.insert(..., pk='id')` after `insert_all`
state: open
created_at: 2023-05-22T17:13:02Z
updated_at: 2023-05-22T17:18:33Z
author_association: NONE
type: issue
body:
  I believe this is related to https://github.com/simonw/sqlite-utils/issues/98.

  When `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:

  ```py
  from sqlite_utils import Database


  def test_pk_for_insert(fresh_db):
      user = {"id": "abc", "name": "david"}

      fresh_db["users"].insert(user, pk="id")

      fresh_db["comments"].insert_all(
          [
              {"id": "def", "text": "ok"},
              {"id": "ghi", "text": "great"},
          ],
      )

      fresh_db["users"].insert(
          user,
          ignore=True,
          # BUG: when specifying pk on the second insert call 
          # db.py goes into a block it doesn't expect and we get the error
          pk="id",
      )


  if __name__ == "__main__":
      db = Database("bug.db")
      if db["users"].exists():
          raise ValueError(
              "bug only shows on a new database - remove bug.db before running the script"
          )
      test_pk_for_insert(db)
  ```

  The error is:

  ```py
    File "/Users/david/projects/reddit-to-sqlite/.venv/lib/python3.11/site-packages/sqlite_utils/db.py", line 2960, in insert_chunk
      row = list(self.rows_where("rowid = ?", [self.last_rowid]))[0]
            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^
  IndexError: list index out of range
  ```

  The issue is in this block: 

  https://github.com/simonw/sqlite-utils/blob/2747257a3334d55e890b40ec58fada57ae8cfbfd/sqlite_utils/db.py#L2954-L2958

  relevant locals are:

  - `pk`: `'id'`
  - `result.lastrowid`: `2`

  What'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. 

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}


node_id: I_kwDOBm6k_c5m5Eiv
title: Resolve the difference between `wrap_view()` and `BaseView`
state: closed
created_at: 2023-05-25T17:44:32Z
updated_at: 2023-05-26T00:18:46Z
closed_at: 2023-05-26T00:18:46Z
author_association: OWNER
type: issue
state_reason: completed
body:
  There are two patterns for implementing views in Datasette at the moment. I want to combine those.

  Part of:
  - #2053

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}


node_id: I_kwDOBm6k_c5m6McW
title: Datasette should serve Access-Control-Max-Age
state: closed
created_at: 2023-05-25T21:50:50Z
updated_at: 2023-05-25T22:56:28Z
closed_at: 2023-05-25T22:08:35Z
author_association: OWNER
type: issue
state_reason: completed
body:
  Currently the CORS headers served are:

  https://github.com/simonw/datasette/blob/9584879534ff0556e04e4c420262972884cac87b/datasette/utils/__init__.py#L1139-L1143

  Serving `Access-Control-Max-Age: 600` would allow browsers to cache that for 10 minutes, avoiding additional CORS pre-flight OPTIONS requests during that time.

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}


node_id: PR_kwDOBm6k_c5RYvTU
title: New View base class
state: closed
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
type: pull
body:
  Refs:

  - #2078

  TODO:

  - [x] Teach router layer how to handle this
  - [x] Use it for something

  <!-- readthedocs-preview datasette start -->
  ----
  :books: Documentation preview :books:: https://datasette--2080.org.readthedocs.build/en/2080/

  <!-- readthedocs-preview datasette end -->

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}


node_id: I_kwDOBm6k_c5m9zx3
title: Update Endpoints defined in metadata throws 403 Forbidden after a while
state: open
created_at: 2023-05-26T11:52:30Z
updated_at: 2023-05-26T11:52:30Z
author_association: NONE
type: issue
body:
  Hello. I expose an endpoint to update `tasks`:
  ```
  {
      "title": "My Datasette Instance",
      "databases": {
          "tasks": {
              "queries": {
                  "update_task": {
                      "sql": "UPDATE tasks SET status = :status, result = :result, systemMessage = :systemMessage WHERE queueID = :queueID",
                      "write": true,
                      "on_success_message": "Task updated",
                      "on_success_redirect": "/tasks/tasks.json",
                      "on_error_message": "Task update failed",
                      "on_error_redirect": "/tasks.json",
                      "params": ["queueID", "taskData", "status", "result", "systemMessage"]
                  }
              }
          }
      }
  }
  ```

  This works really well! But after a while, the Datasette Instanz answers with **403 Forbidden**.
  I have to delete the database and recreate it in order to work again.

  Any help here? (´。＿。｀)

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}


node_id: I_kwDOCGYnMM5nToRk
title: Filter table by a large bunch of ids
state: open
created_at: 2023-05-31T00:29:51Z
updated_at: 2023-06-14T22:01:57Z
author_association: NONE
type: issue
body:
  Hi! this might be a question related to both SQLite & sqlite-utils, and you might be more experienced with them.

  I 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.

  The naive approach would be something like `select * from table where rowid in (?, ?, ?...)` but that wouldn't scale if ids are >1k.

  Another 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.

  I failed to attach an in-memory db both using sqlite-utils, and plain sql's execute(), so my closest approach is something like,

  ```python
  def filter_existing_video_ids(video_ids):
      db = get_db()  # contains a "videos" table
      db.execute("CREATE TEMPORARY TABLE IF NOT EXISTS tmp (video_id TEXT NOT NULL PRIMARY KEY)")
      db["tmp"].insert_all([{"video_id": video_id} for video_id in video_ids])
      for row in db["tmp"].rows_where("video_id not in (select video_id from videos)"):
          yield row["video_id"]
      db["tmp"].drop()
  ```

  That 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.

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}


node_id: PR_kwDOBm6k_c5R0fcK
title: Catch query interrupted on facet suggest row count
state: open
created_at: 2023-05-31T18:42:46Z
updated_at: 2023-05-31T18:45:26Z
author_association: FIRST_TIME_CONTRIBUTOR
pull_request: simonw/datasette/pulls/2082
type: pull
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. 

  I'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.

  <!-- readthedocs-preview datasette start -->
  ----
  :books: Documentation preview :books:: https://datasette--2082.org.readthedocs.build/en/2082/

  <!-- readthedocs-preview datasette end -->

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}


node_id: I_kwDOCGYnMM5ntrC-
title: Support storing incrementally piped values
state: open
created_at: 2023-06-04T00:45:23Z
updated_at: 2023-06-04T01:21:15Z
author_association: CONTRIBUTOR
type: issue
body:
  I'm trying to use sqlite-utils to data generated incrementally. There are a few
  aspects of this that I don't currently know how to handle. I would like an option
  to apply writes incrementally, line-by-line as they are received. I would like an
  option to echo incremental progress. And, it would be nice to have 

  In particular, I'm using CoreLocationCLI -w -j to generate, newline-delimited JSON.

  One variant of the command 

  `stdbuf -oL CoreLocationCLI -w -j | pee 'sqlite-utils insert loc.db loc -' nl`

  `pee`, from `moreutils`, is like `tee` but spawns and pipes to the processes
  created by invoking each of its arguments, so, for gratuitous demonstration,
  `pee 'sponge out.log' cat` would behave like `tee`.

  It looks like I can get what I want with:
  `stdbuf -oL CoreLocationCLI -w -j | while read line; do <<<"$line" sqlite-utils insert loc.db loc -; echo "$line"; done | nl`

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}


node_id: I_kwDOCGYnMM5nuJY3
title: Aliased ROWID option for tables created from alter=True commands
state: closed
created_at: 2023-06-04T05:29:28Z
updated_at: 2023-06-14T06:09:21Z
closed_at: 2023-06-05T19:26:26Z
author_association: CONTRIBUTOR
type: issue
state_reason: completed
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.

  ROWID 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.

  It 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

  I 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

  https://github.com/chapmanjacobd/library/actions/runs/5173602136/jobs/9319024777

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}


node_id: I_kwDOC8SPRc5oYWic
title: Getting sqlite_master may not be modified when creating dogsheep index
state: open
created_at: 2023-06-11T03:21:53Z
updated_at: 2023-06-11T03:21:53Z
author_association: NONE
type: issue
body:
  When creating a `dogsheep` index from `config.yml` file on pocket.db (created using pocket-to-sqlite), I am getting this error

  ```
  Traceback (most recent call last):
    File "/Users/khushmeeet/.pyenv/versions/3.11.2/bin/dogsheep-beta", line 8, in <module>
      sys.exit(cli())
               ^^^^^
    File "/Users/khushmeeet/.pyenv/versions/3.11.2/lib/python3.11/site-packages/click/core.py", line 1130, in __call__
      return self.main(*args, **kwargs)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^
    File "/Users/khushmeeet/.pyenv/versions/3.11.2/lib/python3.11/site-packages/click/core.py", line 1055, in main
      rv = self.invoke(ctx)
           ^^^^^^^^^^^^^^^^
    File "/Users/khushmeeet/.pyenv/versions/3.11.2/lib/python3.11/site-packages/click/core.py", line 1657, in invoke
      return _process_result(sub_ctx.command.invoke(sub_ctx))
                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    File "/Users/khushmeeet/.pyenv/versions/3.11.2/lib/python3.11/site-packages/click/core.py", line 1404, in invoke
      return ctx.invoke(self.callback, **ctx.params)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    File "/Users/khushmeeet/.pyenv/versions/3.11.2/lib/python3.11/site-packages/click/core.py", line 760, in invoke
      return __callback(*args, **kwargs)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^
    File "/Users/khushmeeet/.pyenv/versions/3.11.2/lib/python3.11/site-packages/dogsheep_beta/cli.py", line 36, in index
      run_indexer(
    File "/Users/khushmeeet/.pyenv/versions/3.11.2/lib/python3.11/site-packages/dogsheep_beta/utils.py", line 32, in run_indexer
      ensure_table_and_indexes(db, tokenize)
    File "/Users/khushmeeet/.pyenv/versions/3.11.2/lib/python3.11/site-packages/dogsheep_beta/utils.py", line 91, in ensure_table_and_indexes
      table.add_foreign_key(*fk)
    File "/Users/khushmeeet/.pyenv/versions/3.11.2/lib/python3.11/site-packages/sqlite_utils/db.py", line 2155, in add_foreign_key
      self.db.add_foreign_keys([(self.name, column, other_table, other_column)])
    File "/Users/khushmeeet/.pyenv/versions/3.11.2/lib/python3.11/site-packages/sqlite_utils/db.py", line 1116, in add_foreign_keys
      cursor.execute(
  sqlite3.OperationalError: table sqlite_master may not be modified
  ```

  Command I ran to get this error
  ```
  dogsheep-beta index pocket.db config.yml
  ```

  Dogsheep version
  ```
  dogsheep-beta, version 0.10.2
  ```

  Python version 
  ```
  Python 3.11.2
  ```

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}


node_id: I_kwDOCGYnMM5ojpQg
title: Ability to define unique columns when creating a table
state: open
created_at: 2023-06-13T06:56:19Z
updated_at: 2023-08-18T01:06:03Z
author_association: NONE
type: issue
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.

  ```python
  from sqlite_utils import Database

  columns = {"mRID": str, "name": str}
  db = Database("example.db")
  db["ExampleTable"].create(columns, pk="mRID", not_null=["mRID"], if_not_exists=True)
  db["ExampleTable"].create_index(["mRID"], unique=True, if_not_exists=True)
  ```

  So something like this would add the UNIQUE flag to the table definition. 

  ```python
  db["ExampleTable"].create(columns, pk="mRID", not_null=["mRID"], unique=["mRID"], if_not_exists=True)
  ```

  ```sql
  CREATE TABLE ExampleTable (
      mRID TEXT PRIMARY KEY
                NOT NULL
                UNIQUE,
      name TEXT
  );
  ```

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}


node_id: PR_kwDOBm6k_c5S_5Jl
title: Bump blacken-docs from 1.13.0 to 1.14.0
state: closed
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
type: pull
body:
  Bumps [blacken-docs](https://github.com/asottile/blacken-docs) from 1.13.0 to 1.14.0.
  <details>
  <summary>Changelog</summary>
  <p><em>Sourced from <a href="https://github.com/adamchainz/blacken-docs/blob/main/CHANGELOG.rst">blacken-docs's changelog</a>.</em></p>
  <blockquote>
  <h2>1.14.0 (2023-06-13)</h2>
  <ul>
  <li>Support Python 3.12.</li>
  </ul>
  </blockquote>
  </details>
  <details>
  <summary>Commits</summary>
  <ul>
  <li><a href="https://github.com/adamchainz/blacken-docs/commit/4b94add9bc83d772ae5e31a679a18609c1750513"><code>4b94add</code></a> Version 1.14.0</li>
  <li><a href="https://github.com/adamchainz/blacken-docs/commit/292cb18828c73dfa5273c88ce261b453fb9fdf43"><code>292cb18</code></a> Support Python 3.12 (<a href="https://redirect.github.com/asottile/blacken-docs/issues/251">#251</a>)</li>
  <li><a href="https://github.com/adamchainz/blacken-docs/commit/72ecf2c719027fd464f5561d4ab119f736e8a4ad"><code>72ecf2c</code></a> [pre-commit.ci] pre-commit autoupdate (<a href="https://redirect.github.com/asottile/blacken-docs/issues/249">#249</a>)</li>
  <li><a href="https://github.com/adamchainz/blacken-docs/commit/ea8f1ca88f2f0a58371bb07dab9c647d56d5b3ed"><code>ea8f1ca</code></a> Upgrade requirements (<a href="https://redirect.github.com/asottile/blacken-docs/issues/248">#248</a>)</li>
  <li><a href="https://github.com/adamchainz/blacken-docs/commit/9979d7a78be5b7749ebb000f10f4515e5dc9a574"><code>9979d7a</code></a> Upgrade requirements (<a href="https://redirect.github.com/asottile/blacken-docs/issues/247">#247</a>)</li>
  <li><a href="https://github.com/adamchainz/blacken-docs/commit/7b71075ceb458be255e24da587c0275818b51faa"><code>7b71075</code></a> [pre-commit.ci] pre-commit autoupdate (<a href="https://redirect.github.com/asottile/blacken-docs/issues/245">#245</a>)</li>
  <li><a href="https://github.com/adamchainz/blacken-docs/commit/6280868a8b944193e72436bb467749a21b790d7c"><code>6280868</code></a> [pre-commit.ci] pre-commit autoupdate (<a href="https://redirect.github.com/asottile/blacken-docs/issues/244">#244</a>)</li>
  <li><a href="https://github.com/adamchainz/blacken-docs/commit/83efc37a18b2aea999985439841d644833cb9b90"><code>83efc37</code></a> Upgrade requirements (<a href="https://redirect.github.com/asottile/blacken-docs/issues/243">#243</a>)</li>
  <li><a href="https://github.com/adamchainz/blacken-docs/commit/7aedc23ae3fa040c30e122d8beb66928a05d5320"><code>7aedc23</code></a> [pre-commit.ci] pre-commit autoupdate (<a href="https://redirect.github.com/asottile/blacken-docs/issues/242">#242</a>)</li>
  <li><a href="https://github.com/adamchainz/blacken-docs/commit/d78d593d9a523c8d82d234b94d8ced690ee55fe6"><code>d78d593</code></a> [pre-commit.ci] pre-commit autoupdate (<a href="https://redirect.github.com/asottile/blacken-docs/issues/241">#241</a>)</li>
  <li>Additional commits viewable in <a href="https://github.com/asottile/blacken-docs/compare/1.13.0...1.14.0">compare view</a></li>
  </ul>
  </details>
  <br />


  [![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)

  Dependabot 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`.

  [//]: # (dependabot-automerge-start)
  [//]: # (dependabot-automerge-end)

  ---

  <details>
  <summary>Dependabot commands and options</summary>
  <br />

  You can trigger Dependabot actions by commenting on this PR:
  - `@dependabot rebase` will rebase this PR
  - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
  - `@dependabot merge` will merge this PR after your CI passes on it
  - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it
  - `@dependabot cancel merge` will cancel a previously requested merge and block automerging
  - `@dependabot reopen` will reopen this PR if it is closed
  - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
  - `@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)
  - `@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)
  - `@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)


  </details>

  <!-- readthedocs-preview datasette start -->
  ----
  :books: Documentation preview :books:: https://datasette--2083.org.readthedocs.build/en/2083/

  <!-- readthedocs-preview datasette end -->

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}


node_id: I_kwDOBm6k_c5pABfS
title: Support facets for columns that contain timestamps
state: open
created_at: 2023-06-17T03:33:54Z
updated_at: 2023-06-17T03:33:54Z
author_association: NONE
type: issue
body:
  Django has this very nice filter for datetime fields -

  <img width="176" alt="image" src="https://github.com/simonw/datasette/assets/19492893/3c66d7c4-1579-4d30-8f08-89d111f4566e">

  It 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...

  <img width="283" alt="image" src="https://github.com/simonw/datasette/assets/19492893/069083e4-13f5-4b28-9473-a7b9d48839ea">

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}


node_id: I_kwDOBm6k_c5pCL05
title: Interactive row selection in Datasette
state: open
created_at: 2023-06-18T08:29:45Z
updated_at: 2023-06-18T08:31:23Z
author_association: NONE
type: issue
body:
  Simon did a excellent [prototype](https://til.simonwillison.net/datasette/row-selection-prototype) of an interactive row selection in Datasette.

  I hope this [functionality](https://camo.githubusercontent.com/3d4a0f31fb6a27fd279f809af5b53dc3b76faa63c7721e228951c5252b645a77/68747470733a2f2f7374617469632e73696d6f6e77696c6c69736f6e2e6e65742f7374617469632f323032332f6461746173657474652d7069636b65722e676966) can be turned into a Datasette plugin.

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}


node_id: I_kwDOBm6k_c5pMJc9
title: Show information on startup in directory configuration mode
state: open
created_at: 2023-06-20T07:13:33Z
updated_at: 2023-06-20T07:13:33Z
author_association: OWNER
type: issue
body:
  https://discord.com/channels/823971286308356157/823971286941302908/1120516587036889098

  > 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.

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}


node_id: I_kwDOBm6k_c5pQQwZ
title: `--settings settings.json` option
state: open
created_at: 2023-06-20T17:48:45Z
updated_at: 2023-07-14T17:02:03Z
author_association: OWNER
type: issue
body:
  https://discord.com/channels/823971286308356157/823971286941302908/1120705940728066080

  > 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)

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}


node_id: I_kwDOCGYnMM5ptLOo
title: sqlean support
state: closed
created_at: 2023-06-25T19:27:26Z
updated_at: 2023-06-25T23:25:53Z
closed_at: 2023-06-25T23:25:53Z
author_association: OWNER
type: issue
state_reason: completed
body:
  If sqlean is available, use that.

  Refs:
  - https://github.com/nalgeon/sqlean.py/issues/1#issuecomment-1605707788

  This will provide a good workaround for:
  - #235 

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}


node_id: PR_kwDOCGYnMM5T2mMb
title: Use sqlean if available in environment
state: closed
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
type: pull
body:
  Refs:
  - #559 

  <!-- readthedocs-preview sqlite-utils start -->
  ----
  :books: Documentation preview :books:: https://sqlite-utils--560.org.readthedocs.build/en/560/

  <!-- readthedocs-preview sqlite-utils end -->

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}


node_id: I_kwDOCGYnMM5p8z2b
title: `--stop-after` option for `insert` and `upsert` commands
state: closed
created_at: 2023-06-27T18:44:15Z
updated_at: 2023-06-27T18:50:09Z
closed_at: 2023-06-27T18:50:08Z
author_association: OWNER
type: issue
state_reason: completed
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

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}


node_id: I_kwDOBm6k_c5qJ37q
title: codespell test failure
state: closed
created_at: 2023-06-29T14:40:10Z
updated_at: 2023-06-29T14:48:11Z
closed_at: 2023-06-29T14:48:10Z
author_association: OWNER
type: issue
state_reason: completed
body:
  https://github.com/simonw/datasette/actions/runs/5413443676/jobs/9838999356
  ```
    codespell docs/*.rst --ignore-words docs/codespell-ignore-words.txt
    codespell datasette -S datasette/static --ignore-words docs/codespell-ignore-words.txt
    shell: /usr/bin/bash -e {0}
    env:
      pythonLocation: /opt/hostedtoolcache/Python/3.9.17/x64
      LD_LIBRARY_PATH: /opt/hostedtoolcache/Python/3.9.17/x64/lib
  docs/metadata.rst:192: displaing ==> displaying
  ```
  This failure is legit, it found a spelling mistake: https://github.com/simonw/datasette/blob/ede62036180993dbd9d4e5d280fc21c183cda1c3/docs/metadata.rst#L192

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}


node_id: I_kwDOBm6k_c5qJ_2s
title: Adopt ruff for linting
state: open
created_at: 2023-06-29T14:56:43Z
updated_at: 2023-06-29T15:05:04Z
author_association: OWNER
body: https://beta.ruff.rs/docs/
type: issue
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}


node_id: I_kwDOBm6k_c5qKD6h
title: Drop support for Python 3.7
state: closed
created_at: 2023-06-29T15:06:38Z
updated_at: 2023-08-23T18:18:18Z
closed_at: 2023-08-23T18:18:18Z
author_association: OWNER
body: It's EOL now, as of 2023-06-27 (two days ago): https://devguide.python.org/versions/
type: issue
state_reason: completed
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}


node_id: I_kwDOBm6k_c5qKKHD
title: test_homepage intermittent failure
state: closed
created_at: 2023-06-29T15:20:37Z
updated_at: 2023-06-29T15:26:28Z
closed_at: 2023-06-29T15:24:13Z
author_association: OWNER
type: issue
state_reason: completed
body:
  e.g. in https://github.com/simonw/datasette/actions/runs/5413590227/jobs/9839373852

  ```
  =================================== FAILURES ===================================
  ________________________________ test_homepage _________________________________
  [gw0] linux -- Python 3.7.17 /opt/hostedtoolcache/Python/3.7.17/x64/bin/python

  ds_client = <datasette.app.DatasetteClient object at 0x7f85d271ef50>

      @pytest.mark.asyncio
      async def test_homepage(ds_client):
          response = await ds_client.get("/.json")
          assert response.status_code == 200
          assert "application/json; charset=utf-8" == response.headers["content-type"]
          data = response.json()
          assert data.keys() == {"fixtures": 0}.keys()
          d = data["fixtures"]
          assert d["name"] == "fixtures"
          assert d["tables_count"] == 24
          assert len(d["tables_and_views_truncated"]) == 5
          assert d["tables_and_views_more"] is True
          # 4 hidden FTS tables + no_primary_key (hidden in metadata)
          assert d["hidden_tables_count"] == 6
          # 201 in no_primary_key, plus 6 in other hidden tables:
  >       assert d["hidden_table_rows_sum"] == 207, data
  E       AssertionError: {'fixtures': {'color': '9403e5', 'hash': None, 'hidden_table_rows_sum': 0, 'hidden_tables_count': 6, ...}}
  E       assert 0 == 207
  ```
  My 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.

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}


node_id: I_kwDOBm6k_c5qL_7n
title: Proposal: Combine settings, metadata, static, etc. into a single `datasette.yaml` File
state: open
created_at: 2023-06-29T21:18:23Z
updated_at: 2023-09-11T20:19:32Z
author_association: CONTRIBUTOR
type: issue
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?

  Normally 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.

  - Flat CLI flags like `--port`, `--host`, `--cors`, etc.
  - `--setting`, like `default_page_size`, `sql_time_limit_ms` etc
  - Inside `metadata.json`, including plugin configuration

  Typically my Datasette deploys are extremely long shell commands, with multiple `--setting` and other CLI flags.

  ## Proposal: Consolidate all "config" into `datasette.toml`

  I 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.

  A sample of what it could look like:

  ```toml
  # "top level" configuration that are currently CLI flags on `datasette serve`
  [config]
  port = 8020
  host = "0.0.0.0"
  cors = true

  # replaces multiple `--setting` flags
  [settings]
  base_url = "/app/datasette/"
  default_allow_sql = true
  sql_time_limit_ms = 3500

  # replaces `metadata.json`.
  # 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)
  [metadata]
  include="./datasette-metadata.json"

  # plugin-specific 
  [plugins]
  [plugins.datasette-auth-github]
  client_id = {env = "DATASETTE_AUTH_GITHUB_CLIENT_ID"}
  client_secret = {env = "GITHUB_CLIENT_SECRET"}

  [plugins.datasette-cluster-map]

  latitude_column = "lat"
  longitude_column = "lon"
  ```

  ## Pros
  - Instead of multiple files and CLI flags, everything could be in one tidy file
  - 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
  - New users will know "just edit my `datasette.toml` instead of needing to learn metadata + settings + CLI flags
  - 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.)

  ## Cons
  - 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.
  - If toml is chosen, would need to add a toml parser for Python version <3.11
  - Multiple sources of config require priority. For example: Would `--setting default_allow_sql off` override the value inside `[settings]`? What about `--port`? 

  ## Other Notes

  ### Toml

  I 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


  ### Plugin config will be difficult

  Plugin config is currently in `metadata.json` in two places:

  1. Top level, under `"plugins.[plugin-name]"`. This fits well into `datasette.toml` as `[plugins.plugin-name]`
  2. 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]`?

  ### Extensions, static, one-off plugins?

  We 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. 


  ### Explicitly list with plugins to use?

  I 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

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}


node_id: I_kwDOBm6k_c5qSxIu
title: JS Plugin Hooks for the Code Editor
state: open
created_at: 2023-07-01T00:51:57Z
updated_at: 2023-07-01T00:51:57Z
author_association: CONTRIBUTOR
type: issue
body:
  When #2052 merges, I'd like to add support to add extensions/functions to the Datasette code editor. 

  I'd eventually like to build a JS plugin for [`sqlite-docs`](https://github.com/asg017/sqlite-docs), to add things like:

  - Inline documentation for tables/columns on hover
  - Inline docs for custom functions that are loaded in
  - More detailed autocomplete for tables/columns/functions

  I did some hacking to see what this would look like, see here:

  <img width="1223" alt="image" src="https://github.com/simonw/datasette/assets/15178711/64f95cbc-1492-4365-896f-b88c6d08a649">
  <img width="1223" alt="image" src="https://github.com/simonw/datasette/assets/15178711/73e602ba-5f45-417a-997e-5aea1738527a">

  There can be a new hook that allows JS plugins to add new "extension" in the CodeMirror editorview here:

  https://github.com/simonw/datasette/blob/8cd60fd1d899952f1153460469b3175465f33f80/datasette/static/cm-editor-6.0.1.js#L25

  Will 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. 

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}


node_id: I_kwDOCGYnMM5qYc15
title: Explore the intersection between sqlite-utils and dataclasses
state: open
created_at: 2023-07-02T19:23:08Z
updated_at: 2023-07-02T19:26:39Z
author_association: OWNER
type: issue
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).

  _Originally posted by @simonw in https://github.com/simonw/llm/issues/65#issuecomment-1616742529_
              

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}


node_id: I_kwDOCGYnMM5qanAZ
title: `--empty-null` option when importing CSV
state: closed
created_at: 2023-07-03T05:23:36Z
updated_at: 2023-07-03T05:44:43Z
closed_at: 2023-07-03T05:42:30Z
author_association: OWNER
type: issue
state_reason: completed
body:
  CSV files with empty cells in (which come through as the empty string) are common and a bit gross.

  Having an option that means "and if it's an empty string store `null` instead) would be cool.

  I brainstormed name options here https://chat.openai.com/share/c947b738-ee7d-419c-af90-bc84e90987da

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}


node_id: I_kwDOCGYnMM5qd-tB
title: Document that running `db.transform()` tidies up the schema indentation
state: closed
created_at: 2023-07-03T13:59:28Z
updated_at: 2023-07-22T22:15:34Z
closed_at: 2023-07-22T22:15:34Z
author_association: OWNER
type: issue
state_reason: completed
body:
  > ... and it turns out running `.transform()` with no arguments still fixes the format of the schema!

  ```pycon
  >>> db["log"].add_column("foo", str)
  <Table log (id, name2, age, weight, foo)>
  >>> db["log"].add_column("bar", str)
  <Table log (id, name2, age, weight, foo, bar)>
  >>> db["log"].add_column("baz", str)
  <Table log (id, name2, age, weight, foo, bar, baz)>
  >>> print(db["log"].schema)
  CREATE TABLE "log" (
     [id] INTEGER PRIMARY KEY,
     [name2] TEXT,
     [age] INTEGER,
     [weight] FLOAT
  , [foo] TEXT, [bar] TEXT, [baz] TEXT)
  >>> db["log"].transform()
  <Table log (id, name2, age, weight, foo, bar, baz)>
  >>> print(db["log"].schema)
  CREATE TABLE "log" (
     [id] INTEGER PRIMARY KEY,
     [name2] TEXT,
     [age] INTEGER,
     [weight] FLOAT,
     [foo] TEXT,
     [bar] TEXT,
     [baz] TEXT
  )
  ```

  _Originally posted by @simonw in https://github.com/simonw/llm/issues/65#issuecomment-1618347727_
              

reactions:
  {"url": "https://api.github.com/repos/simonw/sqlite-utils/issues/564/reactions", "total_count": 1, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 1}


node_id: I_kwDOCGYnMM5qeCRG
title: Table renaming: db.rename_table() and sqlite-utils rename-table
state: closed
created_at: 2023-07-03T14:07:42Z
updated_at: 2023-07-22T22:12:40Z
closed_at: 2023-07-22T22:12:40Z
author_association: OWNER
type: issue
state_reason: completed
body:
  > I find myself wanting two new features in `sqlite-utils`:
  > - The ability to have the new transformed table set to a specific name, while keeping the old table around
  > - The ability to rename a table (`sqlite-utils` doesn't have a table rename function at all right now)

  _Originally posted by @simonw in https://github.com/simonw/llm/issues/65#issuecomment-1618375042_
              

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}


node_id: I_kwDOBm6k_c5q78LP
title: Introduce "dark mode" CSS
state: open
created_at: 2023-07-07T19:15:58Z
updated_at: 2023-07-07T19:15:58Z
author_association: NONE
type: issue
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

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}


node_id: PR_kwDOBm6k_c5U-akg
title: Clarify docs for descriptions in metadata
state: open
created_at: 2023-07-08T01:57:58Z
updated_at: 2023-07-08T01:58:13Z
author_association: FIRST_TIME_CONTRIBUTOR
pull_request: simonw/datasette/pulls/2096
type: pull
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.

  <!-- readthedocs-preview datasette start -->
  ----
  :books: Documentation preview :books:: https://datasette--2096.org.readthedocs.build/en/2096/

  <!-- readthedocs-preview datasette end -->

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}


node_id: I_kwDOBm6k_c5q_k-3
title: Drop Python 3.7
state: closed
created_at: 2023-07-08T18:39:44Z
updated_at: 2023-08-23T18:18:00Z
closed_at: 2023-08-23T18:18:00Z
author_association: OWNER
type: issue
state_reason: completed
body:
  >  I'm going to drop Python 3.7.

  _Originally posted by @simonw in https://github.com/simonw/datasette/issues/1153#issuecomment-1627455892_

  It's not supported any more: https://devguide.python.org/versions/

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}


node_id: I_kwDODLZ_YM5rAGMl
title: Switch to pyproject.toml
state: closed
created_at: 2023-07-09T01:06:56Z
updated_at: 2023-07-09T01:19:43Z
closed_at: 2023-07-09T01:19:42Z
author_association: MEMBER
body: First of my CLI tools to use https://til.simonwillison.net/python/pyproject
type: issue
state_reason: completed
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}


node_id: I_kwDOCGYnMM5rAOGZ
title: `--no-headers` doesn't work on most formats
state: open
created_at: 2023-07-09T03:43:36Z
updated_at: 2023-07-09T04:13:35Z
author_association: NONE
type: issue
body:
  Version 3.33

  ```
  sqlite-utils query library.db 'select asin from audible' --fmt plain --no-headers | head -3
  asin
  0062804006
  0062891421
  ```

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}


node_id: PR_kwDOBm6k_c5VFw3j
title: Bump blacken-docs from 1.14.0 to 1.15.0
state: closed
created_at: 2023-07-10T13:49:12Z
updated_at: 2023-08-07T16:20:22Z
closed_at: 2023-08-07T16:20:20Z
author_association: CONTRIBUTOR
pull_request: simonw/datasette/pulls/2098
type: pull
body:
  Bumps [blacken-docs](https://github.com/asottile/blacken-docs) from 1.14.0 to 1.15.0.
  <details>
  <summary>Changelog</summary>
  <p><em>Sourced from <a href="https://github.com/adamchainz/blacken-docs/blob/main/CHANGELOG.rst">blacken-docs's changelog</a>.</em></p>
  <blockquote>
  <h2>1.15.0 (2023-07-09)</h2>
  <ul>
  <li>Drop Python 3.7 support.</li>
  </ul>
  </blockquote>
  </details>
  <details>
  <summary>Commits</summary>
  <ul>
  <li><a href="https://github.com/adamchainz/blacken-docs/commit/2e74dc4c30c336176e76e0426c66f09a4e79df9c"><code>2e74dc4</code></a> Version 1.15.0</li>
  <li><a href="https://github.com/adamchainz/blacken-docs/commit/8ddb2f1269b7652a9b668faa92c9d63d764696c0"><code>8ddb2f1</code></a> [pre-commit.ci] pre-commit autoupdate (<a href="https://redirect.github.com/asottile/blacken-docs/issues/257">#257</a>)</li>
  <li><a href="https://github.com/adamchainz/blacken-docs/commit/64fbca6cad36db1822528ece7f97a8152d29e05f"><code>64fbca6</code></a> Drop Python 3.7 support (<a href="https://redirect.github.com/asottile/blacken-docs/issues/256">#256</a>)</li>
  <li><a href="https://github.com/adamchainz/blacken-docs/commit/f6a0817dbb7957f96ea6cc251edf3a50bf1c3c08"><code>f6a0817</code></a> [pre-commit.ci] pre-commit autoupdate (<a href="https://redirect.github.com/asottile/blacken-docs/issues/255">#255</a>)</li>
  <li><a href="https://github.com/adamchainz/blacken-docs/commit/cbdcb50b125b4f2fdb470122b2ba5e3c15de241a"><code>cbdcb50</code></a> [pre-commit.ci] pre-commit autoupdate (<a href="https://redirect.github.com/asottile/blacken-docs/issues/254">#254</a>)</li>
  <li><a href="https://github.com/adamchainz/blacken-docs/commit/37fc70ee00c7063777ed7343c1bd26fceb5422a6"><code>37fc70e</code></a> Upgrade requirements (<a href="https://redirect.github.com/asottile/blacken-docs/issues/253">#253</a>)</li>
  <li><a href="https://github.com/adamchainz/blacken-docs/commit/7bbe434415ce9f590cb057010590a648e7bea072"><code>7bbe434</code></a> [pre-commit.ci] pre-commit autoupdate (<a href="https://redirect.github.com/asottile/blacken-docs/issues/250">#250</a>)</li>
  <li>See full diff in <a href="https://github.com/asottile/blacken-docs/compare/1.14.0...1.15.0">compare view</a></li>
  </ul>
  </details>
  <br />


  [![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)

  Dependabot 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`.

  [//]: # (dependabot-automerge-start)
  [//]: # (dependabot-automerge-end)

  ---

  <details>
  <summary>Dependabot commands and options</summary>
  <br />

  You can trigger Dependabot actions by commenting on this PR:
  - `@dependabot rebase` will rebase this PR
  - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
  - `@dependabot merge` will merge this PR after your CI passes on it
  - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it
  - `@dependabot cancel merge` will cancel a previously requested merge and block automerging
  - `@dependabot reopen` will reopen this PR if it is closed
  - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
  - `@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)
  - `@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)
  - `@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)


  </details>

  <!-- readthedocs-preview datasette start -->
  ----
  :books: Documentation preview :books:: https://datasette--2098.org.readthedocs.build/en/2098/

  <!-- readthedocs-preview datasette end -->

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}


node_id: PR_kwDOBm6k_c5VM2MK
title: Bump black from 23.3.0 to 23.7.0
state: closed
created_at: 2023-07-11T13:05:53Z
updated_at: 2023-07-21T21:19:25Z
closed_at: 2023-07-21T21:19:24Z
author_association: CONTRIBUTOR
pull_request: simonw/datasette/pulls/2099
type: pull
body:
  Bumps [black](https://github.com/psf/black) from 23.3.0 to 23.7.0.
  <details>
  <summary>Release notes</summary>
  <p><em>Sourced from <a href="https://github.com/psf/black/releases">black's releases</a>.</em></p>
  <blockquote>
  <h2>23.7.0</h2>
  <h3>Highlights</h3>
  <ul>
  <li>Runtime support for Python 3.7 has been removed. Formatting 3.7 code will still be
  supported until further notice (<a href="https://redirect.github.com/psf/black/issues/3765">#3765</a>)</li>
  </ul>
  <h3>Stable style</h3>
  <ul>
  <li>Fix a bug where an illegal trailing comma was added to return type annotations using
  PEP 604 unions (<a href="https://redirect.github.com/psf/black/issues/3735">#3735</a>)</li>
  <li>Fix several bugs and crashes where comments in stub files were removed or mishandled
  under some circumstances (<a href="https://redirect.github.com/psf/black/issues/3745">#3745</a>)</li>
  <li>Fix a crash with multi-line magic comments like <code>type: ignore</code> within parentheses
  (<a href="https://redirect.github.com/psf/black/issues/3740">#3740</a>)</li>
  <li>Fix error in AST validation when <em>Black</em> removes trailing whitespace in a type comment
  (<a href="https://redirect.github.com/psf/black/issues/3773">#3773</a>)</li>
  </ul>
  <h3>Preview style</h3>
  <ul>
  <li>Implicitly concatenated strings used as function args are no longer wrapped inside
  parentheses (<a href="https://redirect.github.com/psf/black/issues/3640">#3640</a>)</li>
  <li>Remove blank lines between a class definition and its docstring (<a href="https://redirect.github.com/psf/black/issues/3692">#3692</a>)</li>
  </ul>
  <h3>Configuration</h3>
  <ul>
  <li>The <code>--workers</code> argument to <em>Black</em> can now be specified via the <code>BLACK_NUM_WORKERS</code>
  environment variable (<a href="https://redirect.github.com/psf/black/issues/3743">#3743</a>)</li>
  <li><code>.pytest_cache</code>, <code>.ruff_cache</code> and <code>.vscode</code> are now excluded by default (<a href="https://redirect.github.com/psf/black/issues/3691">#3691</a>)</li>
  <li>Fix <em>Black</em> not honouring <code>pyproject.toml</code> settings when running <code>--stdin-filename</code>
  and the <code>pyproject.toml</code> found isn't in the current working directory (<a href="https://redirect.github.com/psf/black/issues/3719">#3719</a>)</li>
  <li><em>Black</em> will now error if <code>exclude</code> and <code>extend-exclude</code> have invalid data types in
  <code>pyproject.toml</code>, instead of silently doing the wrong thing (<a href="https://redirect.github.com/psf/black/issues/3764">#3764</a>)</li>
  </ul>
  <h3>Packaging</h3>
  <ul>
  <li>Upgrade mypyc from 0.991 to 1.3 (<a href="https://redirect.github.com/psf/black/issues/3697">#3697</a>)</li>
  <li>Remove patching of Click that mitigated errors on Python 3.6 with <code>LANG=C</code> (<a href="https://redirect.github.com/psf/black/issues/3768">#3768</a>)</li>
  </ul>
  <h3>Parser</h3>
  <ul>
  <li>Add support for the new PEP 695 syntax in Python 3.12 (<a href="https://redirect.github.com/psf/black/issues/3703">#3703</a>)</li>
  </ul>
  <h3>Performance</h3>
  <ul>
  <li>Speed up <em>Black</em> significantly when the cache is full (<a href="https://redirect.github.com/psf/black/issues/3751">#3751</a>)</li>
  <li>Avoid importing <code>IPython</code> in a case where we wouldn't need it (<a href="https://redirect.github.com/psf/black/issues/3748">#3748</a>)</li>
  </ul>
  <h3>Output</h3>
  <!-- raw HTML omitted -->
  </blockquote>
  <p>... (truncated)</p>
  </details>
  <details>
  <summary>Changelog</summary>
  <p><em>Sourced from <a href="https://github.com/psf/black/blob/main/CHANGES.md">black's changelog</a>.</em></p>
  <blockquote>
  <h2>23.7.0</h2>
  <h3>Highlights</h3>
  <ul>
  <li>Runtime support for Python 3.7 has been removed. Formatting 3.7 code will still be
  supported until further notice (<a href="https://redirect.github.com/psf/black/issues/3765">#3765</a>)</li>
  </ul>
  <h3>Stable style</h3>
  <ul>
  <li>Fix a bug where an illegal trailing comma was added to return type annotations using
  PEP 604 unions (<a href="https://redirect.github.com/psf/black/issues/3735">#3735</a>)</li>
  <li>Fix several bugs and crashes where comments in stub files were removed or mishandled
  under some circumstances (<a href="https://redirect.github.com/psf/black/issues/3745">#3745</a>)</li>
  <li>Fix a crash with multi-line magic comments like <code>type: ignore</code> within parentheses
  (<a href="https://redirect.github.com/psf/black/issues/3740">#3740</a>)</li>
  <li>Fix error in AST validation when <em>Black</em> removes trailing whitespace in a type comment
  (<a href="https://redirect.github.com/psf/black/issues/3773">#3773</a>)</li>
  </ul>
  <h3>Preview style</h3>
  <ul>
  <li>Implicitly concatenated strings used as function args are no longer wrapped inside
  parentheses (<a href="https://redirect.github.com/psf/black/issues/3640">#3640</a>)</li>
  <li>Remove blank lines between a class definition and its docstring (<a href="https://redirect.github.com/psf/black/issues/3692">#3692</a>)</li>
  </ul>
  <h3>Configuration</h3>
  <ul>
  <li>The <code>--workers</code> argument to <em>Black</em> can now be specified via the <code>BLACK_NUM_WORKERS</code>
  environment variable (<a href="https://redirect.github.com/psf/black/issues/3743">#3743</a>)</li>
  <li><code>.pytest_cache</code>, <code>.ruff_cache</code> and <code>.vscode</code> are now excluded by default (<a href="https://redirect.github.com/psf/black/issues/3691">#3691</a>)</li>
  <li>Fix <em>Black</em> not honouring <code>pyproject.toml</code> settings when running <code>--stdin-filename</code>
  and the <code>pyproject.toml</code> found isn't in the current working directory (<a href="https://redirect.github.com/psf/black/issues/3719">#3719</a>)</li>
  <li><em>Black</em> will now error if <code>exclude</code> and <code>extend-exclude</code> have invalid data types in
  <code>pyproject.toml</code>, instead of silently doing the wrong thing (<a href="https://redirect.github.com/psf/black/issues/3764">#3764</a>)</li>
  </ul>
  <h3>Packaging</h3>
  <ul>
  <li>Upgrade mypyc from 0.991 to 1.3 (<a href="https://redirect.github.com/psf/black/issues/3697">#3697</a>)</li>
  <li>Remove patching of Click that mitigated errors on Python 3.6 with <code>LANG=C</code> (<a href="https://redirect.github.com/psf/black/issues/3768">#3768</a>)</li>
  </ul>
  <h3>Parser</h3>
  <ul>
  <li>Add support for the new PEP 695 syntax in Python 3.12 (<a href="https://redirect.github.com/psf/black/issues/3703">#3703</a>)</li>
  </ul>
  <h3>Performance</h3>
  <ul>
  <li>Speed up <em>Black</em> significantly when the cache is full (<a href="https://redirect.github.com/psf/black/issues/3751">#3751</a>)</li>
  <li>Avoid importing <code>IPython</code> in a case where we wouldn't need it (<a href="https://redirect.github.com/psf/black/issues/3748">#3748</a>)</li>
  </ul>
  <h3>Output</h3>
  <!-- raw HTML omitted -->
  </blockquote>
  <p>... (truncated)</p>
  </details>
  <details>
  <summary>Commits</summary>
  <ul>
  <li><a href="https://github.com/psf/black/commit/193ee766ca496871f93621d6b58d57a6564ff81b"><code>193ee76</code></a> Prepare release 23.7.0 (<a href="https://redirect.github.com/psf/black/issues/3776">#3776</a>)</li>
  <li><a href="https://github.com/psf/black/commit/38723bb7787d50f8751fad2eaa48b52c9e94c18d"><code>38723bb</code></a> Unpin pytest-xdist (<a href="https://redirect.github.com/psf/black/issues/3772">#3772</a>)</li>
  <li><a href="https://github.com/psf/black/commit/138769aa27d6bd86507a0cd98d9a5bf8f63a8e99"><code>138769a</code></a> Disable coverage on pypy tests (<a href="https://redirect.github.com/psf/black/issues/3777">#3777</a>)</li>
  <li><a href="https://github.com/psf/black/commit/ad3724b7ffc01d8152c97fe7f4dcf35220f21a8e"><code>ad3724b</code></a> Upgrade to latest mypy (<a href="https://redirect.github.com/psf/black/issues/3775">#3775</a>)</li>
  <li><a href="https://github.com/psf/black/commit/b8e2ec728cc09d0f00829a9cffcb54da3efa5760"><code>b8e2ec7</code></a> Fix crash on type comment with trailing space (<a href="https://redirect.github.com/psf/black/issues/3773">#3773</a>)</li>
  <li><a href="https://github.com/psf/black/commit/257d392217974a76231e306133288748c7b70786"><code>257d392</code></a> Fix removed comments in stub files (<a href="https://redirect.github.com/psf/black/issues/3745">#3745</a>)</li>
  <li><a href="https://github.com/psf/black/commit/2593af2c5d211b58e28f7c1472f1f67e6783216a"><code>2593af2</code></a> Improve performance by skipping unnecessary normalisation (<a href="https://redirect.github.com/psf/black/issues/3751">#3751</a>)</li>
  <li><a href="https://github.com/psf/black/commit/f3b50e466969f9142393ec32a4b2a383ffbe5f23"><code>f3b50e4</code></a> Add CITATION.cff file (<a href="https://redirect.github.com/psf/black/issues/3723">#3723</a>)</li>
  <li><a href="https://github.com/psf/black/commit/0b4d7d55f78913be9e0a3738681ef3aafd5d9a5a"><code>0b4d7d5</code></a> Run pyupgrade on blib2to3 and src (<a href="https://redirect.github.com/psf/black/issues/3771">#3771</a>)</li>
  <li><a href="https://github.com/psf/black/commit/114e8357e65384e17baaa3c31aa528371e15679b"><code>114e835</code></a> Remove click patch (<a href="https://redirect.github.com/psf/black/issues/3768">#3768</a>)</li>
  <li>Additional commits viewable in <a href="https://github.com/psf/black/compare/23.3.0...23.7.0">compare view</a></li>
  </ul>
  </details>
  <br />


  [![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)

  Dependabot 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`.

  [//]: # (dependabot-automerge-start)
  [//]: # (dependabot-automerge-end)

  ---

  <details>
  <summary>Dependabot commands and options</summary>
  <br />

  You can trigger Dependabot actions by commenting on this PR:
  - `@dependabot rebase` will rebase this PR
  - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
  - `@dependabot merge` will merge this PR after your CI passes on it
  - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it
  - `@dependabot cancel merge` will cancel a previously requested merge and block automerging
  - `@dependabot reopen` will reopen this PR if it is closed
  - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
  - `@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)
  - `@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)
  - `@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)


  </details>

  <!-- readthedocs-preview datasette start -->
  ----
  :books: Documentation preview :books:: https://datasette--2099.org.readthedocs.build/en/2099/

  <!-- readthedocs-preview datasette end -->

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}


node_id: I_kwDOCGYnMM5rXxo4
title: Plugin system
state: closed
created_at: 2023-07-12T17:02:14Z
updated_at: 2023-07-22T22:59:37Z
closed_at: 2023-07-22T22:59:36Z
author_association: CONTRIBUTOR
type: issue
state_reason: completed
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:

  - Register SQLite extensions for more SQL functions + virtual tables
  - Register new subcommands
  - Different input file formats for `sqlite-utils memory`
  - Different output file formats (in addition to `--csv` `--tsv` `--nl` etc.

  A few real-world use-cases of plugins I'd like to see in sqlite-utils:

  - Register many of my sqlite extensions in sqlite-utils (`sqlite-http`, `sqlite-lines`, `sqlite-regex`, etc.)
  - New subcommands to work with `sqlite-vss` vector tables
  - Input/ouput Parquet/Avro/Arrow IPC files with `sqlite-arrow`

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}


node_id: PR_kwDOBm6k_c5VZhfw
title: Make primary key view accessible to render_cell hook
state: open
created_at: 2023-07-13T09:30:36Z
updated_at: 2023-08-10T13:15:41Z
author_association: FIRST_TIME_CONTRIBUTOR
pull_request: simonw/datasette/pulls/2100
type: pull
body:
  <!-- readthedocs-preview datasette start -->
  ----
  :books: Documentation preview :books:: https://datasette--2100.org.readthedocs.build/en/2100/

  <!-- readthedocs-preview datasette end -->

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}


node_id: I_kwDOBm6k_c5re6EQ
title: alter: true support for JSON write API
state: open
created_at: 2023-07-13T15:24:11Z
updated_at: 2023-07-13T15:24:18Z
author_association: OWNER
type: issue
body:
  Requested here: https://discord.com/channels/823971286308356157/823971286941302908/1129034187073134642

  > The former datasette-insert plugin had an option `?alter=1` to auto-add new columns. Does the JSON write API also have this?

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}


node_id: I_kwDOBm6k_c5rl0lS
title: API tokens with view-table but not view-database/view-instance cannot access the table
state: closed
created_at: 2023-07-14T15:34:27Z
updated_at: 2023-08-29T16:32:36Z
closed_at: 2023-08-29T16:32:35Z
author_association: OWNER
type: issue
state_reason: completed
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.
  >
  > 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
  >
  >> 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.
  >
  > I'm now second-guessing if this was a good decision.

  _Originally posted by @simonw in https://github.com/simonw/datasette-auth-tokens/issues/7#issuecomment-1636031702_
              

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}


node_id: I_kwDOBm6k_c5rxaxb
title: data attribute on Datasette tables exposing the primary key of the row
state: open
created_at: 2023-07-17T16:18:25Z
updated_at: 2023-07-17T16:18:25Z
author_association: OWNER
body: Maybe put it on the `<tr>` but probably better to go on the `td.type-pk`.
type: issue
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}


node_id: I_kwDOBm6k_c5rxy0r
title: Tables starting with an underscore should be treated as hidden
state: open
created_at: 2023-07-17T17:13:53Z
updated_at: 2023-07-18T22:41:37Z
author_association: OWNER
type: issue
body:
  Plugins can then take advantage of this pattern, for example:
  - https://github.com/simonw/datasette-auth-tokens/pull/8

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}


node_id: I_kwDOBm6k_c5r_j6z
title: When reverse proxying datasette with nginx an URL element gets erronously added
state: open
created_at: 2023-07-19T12:16:53Z
updated_at: 2023-07-21T21:17:09Z
author_association: NONE
type: issue
body:
  I use this nginx config:
  ```
      location /datasette-llm {
        return 302 /datasette-llm/;
      }

      location /datasette-llm/ {
        proxy_set_header Upgrade           $http_upgrade;
        proxy_set_header Connection        "Upgrade";
        proxy_http_version 1.1;
        proxy_set_header X-Real-IP         $remote_addr;
        proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto https;
        proxy_set_header X-Forwarded-Host  $http_host;
        proxy_set_header Host              $host;
        proxy_max_temp_file_size           0;
        proxy_pass                         http://127.0.0.1:8001/datasette-llm/;
        proxy_redirect                     http:// https://;
        proxy_buffering off;
        proxy_request_buffering off;
        proxy_set_header Origin            '';
        client_max_body_size 0;
        auth_basic                         "datasette-llm";
        auth_basic_user_file               /etc/nginx/custom-userdb;
      }
  ```
  Then I start datasette with this command:
  ```
  datasette serve --setting base_url /datasette-llm/ $(llm logs path)
  ```
  Everything else works right, except the links in "This data as json, CSV".
  They get an extra URL element "datasette-llm" like this:

  https://192.168.1.3:5432/datasette-llm/datasette-llm/logs.json?sql=select+*+from+_llm_migrations

  https://192.168.1.3:5432/datasette-llm/datasette-llm/logs.csv?sql=select+*+from+_llm_migrations&_size=max

  When I remove that extra "datasette-llm" from the URL, those links work too.

reactions:
  {"url": "https://api.github.com/repos/simonw/datasette/issues/2105/reactions", "total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0}


node_id: I_kwDODEm0Qs5sSqJS
title: Twitter v1 API shutdown
state: open
created_at: 2023-07-22T16:57:41Z
updated_at: 2023-07-22T16:57:41Z
author_association: NONE
type: issue
body:
  I've been using this project reliably over the past two years to periodically download my liked tweets, but unfortunately since 19th July I get:

  ```
  [2023-07-19 21:00:04.937536]   File "/home/pi/code/liked-tweets/lib/python3.7/site-packages/twitter_to_sqlite/utils.py", line 202, in fetch_timeline
  [2023-07-19 21:00:04.937606]     raise Exception(str(tweets["errors"]))
  [2023-07-19 21:00:04.937678] Exception: [{'message': 'You currently have access to a subset of Twitter API v2 endpoints and limited v1.1 endpoints (e.g. media post, oauth) only. If you need access to this endpoint, you may need a different access level. You can learn more here: https://developer.twitter.com/en/portal/product', 'code': 453}]
  ```

  It appears like Twitter has now shut down their v1 endpoints, which is rather gracious of them, considering they [announced they'd be deprecated on 29th April](https://twittercommunity.com/t/reminder-to-migrate-to-the-new-free-basic-or-enterprise-plans-of-the-twitter-api/189737).

  Unfortunately [retrieving likes using the v2 API](https://developer.twitter.com/en/docs/twitter-api/tweets/likes/introduction) is not part of their [free plan](https://developer.twitter.com/en/portal/products). In fact, with the free plan one can only post and delete tweets and retrieve information about oneself.

  So I'm afraid this is the end of this very nice project. It was very useful, thank you!

reactions:
  {"url": "https://api.github.com/repos/dogsheep/twitter-to-sqlite/issues/73/reactions", "total_count": 1, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 1}


node_id: I_kwDOCGYnMM5sSvJw
title: table.create(..., replace=True)
state: closed
created_at: 2023-07-22T18:12:22Z
updated_at: 2023-07-22T19:25:35Z
closed_at: 2023-07-22T19:15:44Z
author_association: OWNER
type: issue
state_reason: completed
body:
  Found myself using this pattern to quickly prototype a schema:

  ```python
  import sqlite_utils
  db = sqlite_utils.Database(memory=True)

  print(db["answers_chunks"].create({
      "id": int,
      "content": str,
      "embedding_type_id": int,
      "embedding": bytes,
      "embedding_content_md5": str,
      "source": str,
  }, pk="id", transform=True).schema)
  ```

  <img width="472" alt="image" src="https://github.com/simonw/datasette-answers/assets/9599/30237f7c-4964-4190-984c-d824c57939a9">

  Using `replace=True` to drop and then recreate the table would be neat here, and would be consistent with other places that use `replace=True`.

reactions:
  {"url": "https://api.github.com/repos/simonw/sqlite-utils/issues/568/reactions", "total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0}


node_id: I_kwDOCGYnMM5sSvey
title: register_command plugin hook
state: closed
created_at: 2023-07-22T18:17:27Z
updated_at: 2023-07-22T19:19:35Z
closed_at: 2023-07-22T19:19:35Z
author_association: OWNER
type: issue
state_reason: completed
body:
  > I'm going to start by adding the `register_command` hook using the exact same pattern as Datasette and LLM.

  _Originally posted by @simonw in https://github.com/simonw/sqlite-utils/issues/567#issuecomment-1646643450_
              

reactions:
  {"url": "https://api.github.com/repos/simonw/sqlite-utils/issues/569/reactions", "total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0}


node_id: I_kwDOCGYnMM5sSwoR
title: `sqlite-utils install -e` option
state: closed
created_at: 2023-07-22T18:32:23Z
updated_at: 2023-07-22T18:55:59Z
closed_at: 2023-07-22T18:32:56Z
author_association: OWNER
body:
  As seen in LLM.

  Needed while working on:
  - #567

type: issue
state_reason: completed
reactions:
  {"url": "https://api.github.com/repos/simonw/sqlite-utils/issues/570/reactions", "total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0}


node_id: I_kwDOBm6k_c5sSwti
title: `datasette install -e` option
state: closed
created_at: 2023-07-22T18:33:42Z
updated_at: 2023-07-26T18:28:33Z
closed_at: 2023-07-22T18:42:54Z
author_association: OWNER
type: issue
state_reason: completed
body:
  As seen in LLM and now in `sqlite-utils` too:
  - https://github.com/simonw/sqlite-utils/issues/570

  Useful for developing plugins, see tutorial at https://llm.datasette.io/en/stable/plugins/tutorial-model-plugin.html

reactions:
  {"url": "https://api.github.com/repos/simonw/datasette/issues/2106/reactions", "total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0}


node_id: I_kwDOCGYnMM5sS1Sz
title: `.transform(keep_table=...)` option
state: closed
created_at: 2023-07-22T19:49:29Z
updated_at: 2023-07-22T22:32:18Z
closed_at: 2023-07-22T22:32:18Z
author_association: OWNER
type: issue
state_reason: completed
body:
  >> Also need a design for an option for the `.transform()` method to indicate that the new table should be created with a new name without dropping the old one.
  >
  > I think `keep_table="name_of_table"` is good for this.

  _Originally posted by @simonw in https://github.com/simonw/sqlite-utils/issues/565#issuecomment-1646657324_
              

reactions:
  {"url": "https://api.github.com/repos/simonw/sqlite-utils/issues/571/reactions", "total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0}


node_id: I_kwDOCGYnMM5sS1tW
title: Don't test Python 3.7 against textual
state: closed
created_at: 2023-07-22T19:57:03Z
updated_at: 2023-07-22T22:16:50Z
closed_at: 2023-07-22T22:16:50Z
author_association: OWNER
type: issue
state_reason: completed
body:
  Spotted this in the GitHub Actions logs:

  ![IMG_5046](https://github.com/simonw/sqlite-utils/assets/9599/81fb1093-cd8a-4019-a612-2e49b500c933)

reactions:
  {"url": "https://api.github.com/repos/simonw/sqlite-utils/issues/572/reactions", "total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0}


node_id: PR_kwDOCGYnMM5WJ6Jm
title: feat: Implement a prepare_connection plugin hook
state: closed
created_at: 2023-07-22T22:48:44Z
updated_at: 2023-07-22T22:59:09Z
closed_at: 2023-07-22T22:59:09Z
author_association: CONTRIBUTOR
pull_request: simonw/sqlite-utils/pulls/573
type: pull
body:
  Just like the [Datasette prepare_connection hook](https://docs.datasette.io/en/stable/plugin_hooks.html#prepare-connection-conn-database-datasette), this PR adds a similar hook for the `sqlite-utils` plugin system. 

  The sole argument is `conn`, since I don't believe a `database` or `datasette` argument would be relevant here. 

  I want to do this so I can release `sqlite-utils` plugins for my [SQLite extensions](https://github.com/asg017/sqlite-ecosystem), similar to the Datasette plugins I've release for them. 

  An example plugin: https://gist.github.com/asg017/d7cdf0d56e2be87efda28cebee27fa3c

  ```bash
  $ sqlite-utils install https://gist.github.com/asg017/d7cdf0d56e2be87efda28cebee27fa3c/archive/5f5ad549a40860787629c69ca120a08c32519e99.zip

  $ sqlite-utils memory 'select hello("alex") as response'
  [{"response": "Hello, alex!"}]
  ```
  Refs:
  - #574 

  <!-- readthedocs-preview sqlite-utils start -->
  ----
  :books: Documentation preview :books:: https://sqlite-utils--573.org.readthedocs.build/en/573/

  <!-- readthedocs-preview sqlite-utils end -->

reactions:
  {"url": "https://api.github.com/repos/simonw/sqlite-utils/issues/573/reactions", "total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0}


node_id: I_kwDOCGYnMM5sS_ip
title: `prepare_connection()` plugin hook
state: closed
created_at: 2023-07-22T22:52:47Z
updated_at: 2023-07-22T23:13:14Z
closed_at: 2023-07-22T22:59:10Z
author_association: OWNER
type: issue
state_reason: completed
body:
  > Splitting off an issue for `prepare_connection()` since Alex got the PR in seconds before I shipped 3.34!

  _Originally posted by @simonw in https://github.com/simonw/sqlite-utils/issues/567#issuecomment-1646686424_
              

reactions:
  {"url": "https://api.github.com/repos/simonw/sqlite-utils/issues/574/reactions", "total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0}


node_id: I_kwDOCGYnMM5sS_4Q
title: Python API ability to opt-out of connection plugins
state: closed
created_at: 2023-07-22T23:01:13Z
updated_at: 2023-07-22T23:17:22Z
closed_at: 2023-07-22T23:08:22Z
author_association: OWNER
type: issue
state_reason: completed
body:
  Plugins affecting the CLI by default makes sense to me.

  I'm less confident about them _always_ affecting users of the Python API.

  I'm going to have them apply by default, but I'm going to add a mechanism to opt-out on an individual database basis. Basically this:

  ```python
  from sqlite_utils import Database
  db = Database(memory=True, execute_plugins=False)
  # Anything using db from here on will not execute plugins
  ```
  cc @asg017 

  Refs:
  - #567 
  - #574 

reactions:
  {"url": "https://api.github.com/repos/simonw/sqlite-utils/issues/575/reactions", "total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0}


node_id: I_kwDOCGYnMM5sTS4O
title: Backfill the release notes prior to 0.4
state: closed
created_at: 2023-07-23T05:41:42Z
updated_at: 2023-07-23T05:49:51Z
closed_at: 2023-07-23T05:48:21Z
author_association: OWNER
type: issue
state_reason: completed
body:
  Currently the changelog starts at 0.4:

  https://sqlite-utils.datasette.io/en/3.34/changelog.html#id115

  I want the other releases - according to https://pypi.org/project/sqlite-utils/#history there are three missing:

  <img width="663" alt="image" src="https://github.com/simonw/sqlite-utils/assets/9599/4ebc036b-7bb1-477c-95c1-a2c7e26bcb62">

reactions:
  {"url": "https://api.github.com/repos/simonw/sqlite-utils/issues/576/reactions", "total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0}


node_id: I_kwDOC8SPRc5sUYQV
title: cannot use jinja filters in display?
state: closed
created_at: 2023-07-23T20:09:54Z
updated_at: 2023-07-23T20:18:27Z
closed_at: 2023-07-23T20:18:26Z
author_association: NONE
type: issue
state_reason: completed
body:
  Hi, I'm trying to have a display function in Dogsheep's `config.yml` that includes something like this:

  ```         
  <h3>
    <a href="{{ urls.row('my_database', 'my_table', key) }}">{{ display.title }}</a>
    <a href="{{ display.url }}🔗" target="_blank">(source)</a>
  </h3>
  <p>{{ display.snippet|safe }}</p>
  ```

  Unfortunately, rendering fails with a message 'urls is undefined'.

  The same happens if I'm trying to build a row URL manually, using filters like `quote_plus` (as my keys are URLs).

  Any hints?

  Thanks!

reactions:
  {"url": "https://api.github.com/repos/dogsheep/dogsheep-beta/issues/37/reactions", "total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0}


node_id: I_kwDOCGYnMM5sUaMx
title: Get `add_foreign_keys()` to work without modifying `sqlite_master`
state: closed
created_at: 2023-07-23T20:40:18Z
updated_at: 2023-08-18T17:43:11Z
closed_at: 2023-08-18T00:48:10Z
author_association: OWNER
type: issue
state_reason: completed
body:
  https://github.com/simonw/sqlite-utils/blob/13ebcc575d2547c45e8d31288b71a3242c16b886/sqlite_utils/db.py#L1165-L1174

  This is the only place in the code that attempts to modify `sqlite_master` directly, which fails on some Python installations.

  Could this use the `.transform()` trick instead?

  Or automatically switch to that trick if it hits an error?

reactions:
  {"url": "https://api.github.com/repos/simonw/sqlite-utils/issues/577/reactions", "total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0}


node_id: I_kwDOCGYnMM5saUUW
title: Plugin hook for adding new output formats
state: open
created_at: 2023-07-24T17:29:18Z
updated_at: 2023-08-07T15:41:49Z
author_association: OWNER
type: issue
body:
  > What would it take to add a format hook? I'm still thinking about my GIS workflow, and being able to do `sqlite-utils query ... --geojson` would be nice. It's the one place my Datasette workflow is messy, having to do `datasette . --get /path/to/query.geojson --setting max_rows_returned 10000 --load-extension spatialite`.
  > I know the current pattern is `--csv`, but maybe `--format geojson` is more future-proof.

  https://discord.com/channels/823971286308356157/997738192360964156/1133076679011602432

reactions:
  {"url": "https://api.github.com/repos/simonw/sqlite-utils/issues/578/reactions", "total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0}


node_id: PR_kwDOBm6k_c5WVYor
title: Bump sphinx from 6.1.3 to 7.1.0
state: closed
created_at: 2023-07-25T13:28:30Z
updated_at: 2023-07-28T13:23:19Z
closed_at: 2023-07-28T13:23:17Z
author_association: CONTRIBUTOR
pull_request: simonw/datasette/pulls/2107
type: pull
body:
  Bumps [sphinx](https://github.com/sphinx-doc/sphinx) from 6.1.3 to 7.1.0.
  <details>
  <summary>Release notes</summary>
  <p><em>Sourced from <a href="https://github.com/sphinx-doc/sphinx/releases">sphinx's releases</a>.</em></p>
  <blockquote>
  <h2>Sphinx 7.1.0</h2>
  <p>Changelog: <a href="https://www.sphinx-doc.org/en/master/changes.html">https://www.sphinx-doc.org/en/master/changes.html</a></p>
  <h2>v7.0.1</h2>
  <p>Changelog: <a href="https://www.sphinx-doc.org/en/master/changes.html">https://www.sphinx-doc.org/en/master/changes.html</a></p>
  <h2>v7.0.0</h2>
  <p>Changelog: <a href="https://www.sphinx-doc.org/en/master/changes.html">https://www.sphinx-doc.org/en/master/changes.html</a></p>
  <h2>v7.0.0rc1</h2>
  <p>Changelog: <a href="https://www.sphinx-doc.org/en/master/changes.html">https://www.sphinx-doc.org/en/master/changes.html</a></p>
  <h2>v6.2.1</h2>
  <p>Changelog: <a href="https://www.sphinx-doc.org/en/master/changes.html">https://www.sphinx-doc.org/en/master/changes.html</a></p>
  <h2>v6.2.0</h2>
  <p>Changelog: <a href="https://www.sphinx-doc.org/en/master/changes.html">https://www.sphinx-doc.org/en/master/changes.html</a></p>
  </blockquote>
  </details>
  <details>
  <summary>Changelog</summary>
  <p><em>Sourced from <a href="https://github.com/sphinx-doc/sphinx/blob/master/CHANGES">sphinx's changelog</a>.</em></p>
  <blockquote>
  <h1>Release 7.1.0 (released Jul 24, 2023)</h1>
  <h2>Incompatible changes</h2>
  <ul>
  <li>
  <p>Releases are no longer signed, given the <code>change in PyPI policy</code>_.</p>
  <p>.. _change in PyPI policy: <a href="https://blog.pypi.org/posts/2023-05-23-removing-pgp/">https://blog.pypi.org/posts/2023-05-23-removing-pgp/</a></p>
  </li>
  </ul>
  <h2>Deprecated</h2>
  <ul>
  <li><a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11412">#11412</a>: Emit warnings on using a deprecated Python-specific index entry type
  (namely, <code>module</code>, <code>keyword</code>, <code>operator</code>, <code>object</code>, <code>exception</code>,
  <code>statement</code>, and <code>builtin</code>) in the :rst:dir:<code>index</code> directive, and
  set the removal version to Sphinx 9. Patch by Adam Turner.</li>
  </ul>
  <h2>Features added</h2>
  <ul>
  <li><a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11415">#11415</a>: Add a checksum to JavaScript and CSS asset URIs included within
  generated HTML, using the CRC32 algorithm.</li>
  <li>:meth:<code>~sphinx.application.Sphinx.require_sphinx</code> now allows the version
  requirement to be specified as <code>(major, minor)</code>.</li>
  <li><a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11011">#11011</a>: Allow configuring a line-length limit for object signatures, via
  :confval:<code>maximum_signature_line_length</code> and the domain-specific variants.
  If the length of the signature (in characters) is greater than the configured
  limit, each parameter in the signature will be split to its own logical line.
  This behaviour may also be controlled by options on object description
  directives, for example :rst:dir:<code>py:function:single-line-parameter-list</code>.
  Patch by Thomas Louf, Adam Turner, and Jean-François B.</li>
  <li><a href="https://redirect.github.com/sphinx-doc/sphinx/issues/10983">#10983</a>: Support for multiline copyright statements in the footer block.
  Patch by Stefanie Molin</li>
  <li><code>sphinx.util.display.status_iterator</code> now clears the current line
  with ANSI control codes, rather than overprinting with space characters.</li>
  <li><a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11431">#11431</a>: linkcheck: Treat SSL failures as broken links.
  Patch by Bénédikt Tran</li>
  <li><a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11157">#11157</a>: Keep the <code>translated</code> attribute on translated nodes.</li>
  <li><a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11451">#11451</a>: Improve the traceback displayed when using :option:<code>sphinx-build -T</code>
  in parallel builds. Patch by Bénédikt Tran</li>
  <li><a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11324">#11324</a>: linkcheck: Use session-basd HTTP requests.</li>
  <li><a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11438">#11438</a>: Add support for the :rst:dir:<code>py:class</code> and :rst:dir:<code>py:function</code>
  directives for PEP 695 (generic classes and functions declarations) and
  PEP 696 (default type parameters).  Multi-line support (<a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11011">#11011</a>) is enabled
  for type parameters list and can be locally controlled on object description
  directives, e.g., :rst:dir:<code>py:function:single-line-type-parameter-list</code>.
  Patch by Bénédikt Tran.</li>
  <li><a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11484">#11484</a>: linkcheck: Allow HTML anchors to be ignored on a per-URL basis
  via :confval:<code>linkcheck_anchors_ignore_for_url</code> while</li>
  </ul>
  <!-- raw HTML omitted -->
  </blockquote>
  <p>... (truncated)</p>
  </details>
  <details>
  <summary>Commits</summary>
  <ul>
  <li><a href="https://github.com/sphinx-doc/sphinx/commit/e560f6334aa87af07304415e6aeaf42d03d1c525"><code>e560f63</code></a> Bump to 7.1.0 final</li>
  <li><a href="https://github.com/sphinx-doc/sphinx/commit/066e0fabc60c55072b3f75876637a44fdcb51332"><code>066e0fa</code></a> Add translation progress information (<a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11509">#11509</a>)</li>
  <li><a href="https://github.com/sphinx-doc/sphinx/commit/0882914d5c5057ad3cec280c0142cfe5f6965844"><code>0882914</code></a> Target PyPI in create-release.yml</li>
  <li><a href="https://github.com/sphinx-doc/sphinx/commit/21fbee5e83a3e9d34e589d06c66d928f3a67923c"><code>21fbee5</code></a> Fix OIDC token payload</li>
  <li><a href="https://github.com/sphinx-doc/sphinx/commit/1a403e4f9ad4d8d7a3e4c7c34f55d9a45ed600bd"><code>1a403e4</code></a> Add informational log messaging</li>
  <li><a href="https://github.com/sphinx-doc/sphinx/commit/258b0ea9fcdd05221ebead5e5c162a7ad37c4412"><code>258b0ea</code></a> Revert &quot;Switch to using <code>github.request</code>&quot;</li>
  <li><a href="https://github.com/sphinx-doc/sphinx/commit/f9c89e5d8431155caa7be57d923f96004a2dd4bd"><code>f9c89e5</code></a> Switch to using <code>github.request</code></li>
  <li><a href="https://github.com/sphinx-doc/sphinx/commit/52c7f66ce172f723e8227896fe02165d288cb28f"><code>52c7f66</code></a> Use the correct token minting URL for TestPyPI</li>
  <li><a href="https://github.com/sphinx-doc/sphinx/commit/6079f28faa2a60d00f62b02786f23cd489019cdb"><code>6079f28</code></a> Install twine in PyPI publish workflow</li>
  <li><a href="https://github.com/sphinx-doc/sphinx/commit/3d43b9efdb49706cad6947f0c4d877d603781fe6"><code>3d43b9e</code></a> Fix github-script syntax in create-release.yml</li>
  <li>Additional commits viewable in <a href="https://github.com/sphinx-doc/sphinx/compare/v6.1.3...v7.1.0">compare view</a></li>
  </ul>
  </details>
  <br />


  [![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.1.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

  Dependabot 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`.

  [//]: # (dependabot-automerge-start)
  [//]: # (dependabot-automerge-end)

  ---

  <details>
  <summary>Dependabot commands and options</summary>
  <br />

  You can trigger Dependabot actions by commenting on this PR:
  - `@dependabot rebase` will rebase this PR
  - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
  - `@dependabot merge` will merge this PR after your CI passes on it
  - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it
  - `@dependabot cancel merge` will cancel a previously requested merge and block automerging
  - `@dependabot reopen` will reopen this PR if it is closed
  - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
  - `@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)
  - `@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)
  - `@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)


  </details>

  <!-- readthedocs-preview datasette start -->
  ----
  :books: Documentation preview :books:: https://datasette--2107.org.readthedocs.build/en/2107/

  <!-- readthedocs-preview datasette end -->

reactions:
  {"url": "https://api.github.com/repos/simonw/datasette/issues/2107/reactions", "total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0}


node_id: I_kwDOCGYnMM5si-ne
title: Special handling for SQLite column of type `JSON`
state: open
created_at: 2023-07-25T20:37:23Z
updated_at: 2023-07-25T20:37:23Z
author_association: CONTRIBUTOR
type: issue
body:
  `sqlite-utils` should detect and have specially handling for column with a `JSON` column. For example:

  ```sql
  CREATE TABLE "dogs" (
    id INTEGER PRIMARY KEY,
    name TEXT,
    friends JSON 
  );
  ```

  ## Automatic Nesting

  According to ["Nested JSON Values"](https://sqlite-utils.datasette.io/en/stable/cli.html#nested-json-values), sqlite-utils will only expand JSON if the `--json-cols` flag is passed. It looks like it'll try to `json.load` all text column to test if its JSON, which can get expensive on non-json columns. 

  Instead, `sqlite-utils` should be default (ie without the `--json-cols` flags) do the `maybe_json()` operation on columns with a declared `JSON` type. So the above table would expand the `"friends"` column as expected, withoutthe `--json-cols` flag:

  ```bash
  sqlite-utils dogs.db "select * from dogs" | python -mjson.tool
  ```

  ```
  [
      {
          "id": 1,
          "name": "Cleo",
          "friends": [
              {
                  "name": "Pancakes"
              },
              {
                  "name": "Bailey"
              }
          ]
      }
  ]
  ```

  ---

  I'm sure there's other ways `sqlite-utils` can specially handle JSON columns, so keeping this open while I think of more

reactions:
  {"url": "https://api.github.com/repos/simonw/sqlite-utils/issues/579/reactions", "total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0}


node_id: I_kwDOBm6k_c5spe27
title: some (many?) SQL syntax errors are not throwing errors with a .csv endpoint
state: open
created_at: 2023-07-26T16:57:45Z
updated_at: 2023-07-26T16:58:07Z
author_association: CONTRIBUTOR
type: issue
body:
  here's a CTE query that should always fail with a syntax error:

  ```sql
  with foo as (nonsense)
  select
    *
  from
    foo;
  ```

  when we make this query against the default endpoint, we do indeed get a 400 status code the problem is returned to the user: https://global-power-plants.datasettes.com/global-power-plants?sql=with+foo+as+%28nonsense%29+select+*+from+foo%3B

  but, if we use the csv endpoint, we get a 200 status code and no indication of a problem: https://global-power-plants.datasettes.com/global-power-plants.csv?sql=with+foo+as+%28nonsense%29+select+*+from+foo%3B

  same with this bad sql

  ```sql
  select
    a,
  from
    foo;
  ```

  https://global-power-plants.datasettes.com/global-power-plants?sql=select%0D%0A++a%2C%0D%0Afrom%0D%0A++foo%3B

  vs 

  https://global-power-plants.datasettes.com/global-power-plants.csv?sql=select%0D%0A++a%2C%0D%0Afrom%0D%0A++foo%3B

  but, datasette catches this bad sql at both endpoints:

  ```sql
  slect
    a
  from
    foo;
  ```

  https://global-power-plants.datasettes.com/global-power-plants?sql=slect%0D%0A++a%0D%0Afrom%0D%0A++foo%3B
  https://global-power-plants.datasettes.com/global-power-plants.csv?sql=slect%0D%0A++a%0D%0Afrom%0D%0A++foo%3B

reactions:
  {"url": "https://api.github.com/repos/simonw/datasette/issues/2108/reactions", "total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0}


node_id: I_kwDOCGYnMM5sp4lT
title: Add way to export to a csv file using the Python library
state: open
created_at: 2023-07-26T18:09:26Z
updated_at: 2023-07-26T18:09:26Z
author_association: NONE
type: issue
body:
  According to the documentation, we can make a csv output using the CLI tool, but not the Python library. Could we have the latter?

reactions:
  {"url": "https://api.github.com/repos/simonw/sqlite-utils/issues/580/reactions", "total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0}


node_id: I_kwDOBm6k_c5sp8Yj
title: Plan for getting the new JSON format query views working
state: closed
created_at: 2023-07-26T18:20:18Z
updated_at: 2023-07-27T00:24:47Z
closed_at: 2023-07-26T18:25:34Z
author_association: OWNER
type: issue
state_reason: completed
body:
  I've been stuck on this for too long. I'm breaking it down into a full milestone:

  https://github.com/simonw/datasette/milestone/29

reactions:
  {"url": "https://api.github.com/repos/simonw/datasette/issues/2109/reactions", "total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0}


node_id: I_kwDOBm6k_c5sp83J
title: Merge database index page and query view
state: closed
created_at: 2023-07-26T18:21:57Z
updated_at: 2023-07-26T19:53:25Z
closed_at: 2023-07-26T19:53:25Z
author_association: OWNER
type: issue
state_reason: completed
body:
  Refs:
  - #2109

  The idea here is that hitting `/content` without a `?sql=` will show an empty result set AND default to including a bunch of extras about the list of tables in the database.

  Then I won't have to think about `/content` and `/content?sql=` as separate pages any more.

reactions:
  {"url": "https://api.github.com/repos/simonw/datasette/issues/2110/reactions", "total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0}


node_id: I_kwDOBm6k_c5sp9FS
title: Implement new /content.json?sql=...
state: closed
created_at: 2023-07-26T18:22:39Z
updated_at: 2023-08-08T02:00:37Z
closed_at: 2023-08-08T02:00:22Z
author_association: OWNER
body:
  This will be the base that the remaining work builds on top of. Refs:
  - #2109

type: issue
state_reason: completed
reactions:
  {"url": "https://api.github.com/repos/simonw/datasette/issues/2111/reactions", "total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0}


node_id: I_kwDOBm6k_c5sp9Yl
title: Build HTML version of /content?sql=...
state: closed
created_at: 2023-07-26T18:23:34Z
updated_at: 2023-08-08T02:01:09Z
closed_at: 2023-08-08T02:01:01Z
author_association: OWNER
body:
  This will help make the hook as robust as possible.
  - #2109

type: issue
state_reason: completed
reactions:
  {"url": "https://api.github.com/repos/simonw/datasette/issues/2112/reactions", "total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0}


node_id: I_kwDOBm6k_c5sp9iK
title: Implement and document extras for the new query view page
state: open
created_at: 2023-07-26T18:24:01Z
updated_at: 2023-08-09T17:35:22Z
author_association: OWNER
body: - #2109
type: issue
reactions:
  {"url": "https://api.github.com/repos/simonw/datasette/issues/2113/reactions", "total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0}


node_id: I_kwDOBm6k_c5sp9xn
title: Implement canned queries against new query JSON work
state: closed
created_at: 2023-07-26T18:24:50Z
updated_at: 2023-08-09T15:26:58Z
closed_at: 2023-08-09T15:26:57Z
author_association: OWNER
body: - #2109
type: issue
state_reason: completed
reactions:
  {"url": "https://api.github.com/repos/simonw/datasette/issues/2114/reactions", "total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0}


node_id: I_kwDOBm6k_c5sp98k
title: Ensure all tests pass against new query view JSON
state: closed
created_at: 2023-07-26T18:25:20Z
updated_at: 2023-08-08T02:01:39Z
closed_at: 2023-08-08T02:01:38Z
author_association: OWNER
body: - #2109
type: issue
state_reason: completed
reactions:
  {"url": "https://api.github.com/repos/simonw/datasette/issues/2115/reactions", "total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0}


node_id: I_kwDOBm6k_c5sqAF8
title: Turn DatabaseDownload into an async view function
state: closed
created_at: 2023-07-26T18:31:59Z
updated_at: 2023-07-26T18:44:00Z
closed_at: 2023-07-26T18:44:00Z
author_association: OWNER
body:
  A minor refactor, but it is a good starting point for this new branch. Refs:
  - #2109

type: issue
state_reason: completed
reactions:
  {"url": "https://api.github.com/repos/simonw/datasette/issues/2116/reactions", "total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0}


node_id: I_kwDOBm6k_c5sqIMV
title: Figure out what to do about `DatabaseView.name`
state: closed
created_at: 2023-07-26T18:58:06Z
updated_at: 2023-08-08T02:02:07Z
closed_at: 2023-08-08T02:02:07Z
author_association: OWNER
type: issue
state_reason: completed
body:
  In the old code:

  https://github.com/simonw/datasette/blob/08181823990a71ffa5a1b57b37259198eaa43e06/datasette/views/database.py#L34-L35

  This `name` class attribute was later used by some of the plugin hooks, passed as `view_name`: https://github.com/simonw/datasette/blob/18dd88ee4d78fe9d760e9da96028ae06d938a85c/datasette/hookspecs.py#L50-L54

  Figure out how that should work once I've refactored those classes to view functions instead.

  Refs:
  - #2109 

reactions:
  {"url": "https://api.github.com/repos/simonw/datasette/issues/2117/reactions", "total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0}


node_id: I_kwDOCGYnMM5sqzms
title: `sqlite-utils convert --pdb` option
state: closed
created_at: 2023-07-26T21:02:50Z
updated_at: 2023-07-26T21:07:45Z
closed_at: 2023-07-26T21:06:10Z
author_association: OWNER
type: issue
state_reason: completed
body:
  While using `sqlite-utils convert` I realized it would be handy if you could pass `--pdb` to have it open the debugger at the first instance of a failed conversion.

reactions:
  {"url": "https://api.github.com/repos/simonw/sqlite-utils/issues/581/reactions", "total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0}


node_id: PR_kwDOBm6k_c5Wfgd9
title: New JSON design for query views
state: closed
created_at: 2023-07-26T23:29:21Z
updated_at: 2023-08-08T01:47:40Z
closed_at: 2023-08-08T01:47:39Z
author_association: OWNER
pull_request: simonw/datasette/pulls/2118
type: pull
body:
  WIP. Refs:
  - #2109 

  <!-- readthedocs-preview datasette start -->
  ----
  :books: Documentation preview :books:: https://datasette--2118.org.readthedocs.build/en/2118/

  <!-- readthedocs-preview datasette end -->

reactions:
  {"url": "https://api.github.com/repos/simonw/datasette/issues/2118/reactions", "total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0}


node_id: I_kwDOBm6k_c5srsbD
title: database color shows only on index page, not other pages
state: closed
created_at: 2023-07-27T00:19:39Z
updated_at: 2023-08-11T05:25:45Z
closed_at: 2023-08-11T05:16:24Z
author_association: OWNER
type: issue
state_reason: completed
body:
  I think this has been a bug for a long time.

  https://latest.datasette.io/ currently shows:

  <img width="827" alt="image" src="https://github.com/simonw/datasette/assets/9599/fcd08d0c-5b07-40be-bc9f-3ba9199ad858">

  Those colors are based on a hash of the database name. But when you click through to https://latest.datasette.io/fixtures

  <img width="692" alt="image" src="https://github.com/simonw/datasette/assets/9599/7c9dfd66-06e8-47fc-9ed7-ce425da22cb4">

  It's red on all sub-pages too.

reactions:
  {"url": "https://api.github.com/repos/simonw/datasette/issues/2119/reactions", "total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0}


node_id: I_kwDOBm6k_c5sr1Bq
title: Add __all__ to datasette/__init__.py
state: open
created_at: 2023-07-27T01:07:10Z
updated_at: 2023-07-27T01:07:10Z
author_association: OWNER
type: issue
body:
  Currently looks like this: https://github.com/simonw/datasette/blob/08181823990a71ffa5a1b57b37259198eaa43e06/datasette/__init__.py#L1-L6

  Adding `__all__ = ["Permission", "Forbidden"...]` would let me get rid of those `# noqa` comments.

reactions:
  {"url": "https://api.github.com/repos/simonw/datasette/issues/2120/reactions", "total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0}


node_id: PR_kwDOBm6k_c5WjCS8
title: Bump furo from 2023.3.27 to 2023.7.26
state: closed
created_at: 2023-07-27T13:40:48Z
updated_at: 2023-08-07T16:20:23Z
closed_at: 2023-08-07T16:20:20Z
author_association: CONTRIBUTOR
pull_request: simonw/datasette/pulls/2121
type: pull
body:
  Bumps [furo](https://github.com/pradyunsg/furo) from 2023.3.27 to 2023.7.26.
  <details>
  <summary>Changelog</summary>
  <p><em>Sourced from <a href="https://github.com/pradyunsg/furo/blob/main/docs/changelog.md">furo's changelog</a>.</em></p>
  <blockquote>
  <h1>Changelog</h1>
  <!-- raw HTML omitted -->
  <h2>2023.07.26 -- Vigilant Volt</h2>
  <ul>
  <li>Fix compatiblity with Sphinx 7.1.</li>
  <li>Improve how content overflow is handled.</li>
  <li>Improve how literal blocks containing inline code are handled.</li>
  </ul>
  <h2>2023.05.20 -- Unassuming Ultramarine</h2>
  <ul>
  <li>✨ Add support for Sphinx 7.</li>
  <li>Drop support for Sphinx 5.</li>
  <li>Improve the screen-reader label for sidebar collapse.</li>
  <li>Make it easier to create derived themes from Furo.</li>
  <li>Bump all JS dependencies (NodeJS and npm packages).</li>
  </ul>
  <h2>2023.03.27 -- Tasty Tangerine</h2>
  <ul>
  <li>Regenerate with newer version of sphinx-theme-builder, to fix RECORD hashes.</li>
  <li>Add missing class to Font Awesome examples</li>
  </ul>
  <h2>2023.03.23 -- Sassy Saffron</h2>
  <ul>
  <li>Update Python version classifiers.</li>
  <li>Increase the icon size in mobile header.</li>
  <li>Increase admonition title bg opacity.</li>
  <li>Change the default API background to transparent.</li>
  <li>Transition the API background change.</li>
  <li>Remove the &quot;indent&quot; of API entries which have a background.</li>
  <li>Break long inline code literals.</li>
  </ul>
  <h2>2022.12.07 -- Reverent Raspberry</h2>
  <ul>
  <li>✨ Add support for Sphinx 6.</li>
  <li>✨ Improve footnote presentation with docutils 0.18+.</li>
  <li>Drop support for Sphinx 4.</li>
  <li>Improve documentation about what the edit button does.</li>
  <li>Improve handling of empty-flexboxes for better print experience on Chrome.</li>
  <li>Improve styling for inline signatures.</li>
  </ul>
  <!-- raw HTML omitted -->
  </blockquote>
  <p>... (truncated)</p>
  </details>
  <details>
  <summary>Commits</summary>
  <ul>
  <li><a href="https://github.com/pradyunsg/furo/commit/35f5307acc66d63ddb2e50eebc79a389518e881a"><code>35f5307</code></a> Prepare release: 2023.07.26</li>
  <li><a href="https://github.com/pradyunsg/furo/commit/0a8bedc51399777be2d01f2401fd52a32d9f6673"><code>0a8bedc</code></a> Update changelog</li>
  <li><a href="https://github.com/pradyunsg/furo/commit/a92dd0c2bfa398825e239171925a81bdc428e90a"><code>a92dd0c</code></a> Make <code>_add_asset_hashes</code> a no-op with Sphinx 7.1</li>
  <li><a href="https://github.com/pradyunsg/furo/commit/f8db95bed5d1c57b4ea6bf536c65560fa9ae33a9"><code>f8db95b</code></a> Improve literals with inline code are handled</li>
  <li><a href="https://github.com/pradyunsg/furo/commit/1680dbefd61766a28e43880ae05a9f5cc0e7f19b"><code>1680dbe</code></a> Document the use of <code>figclass</code> with <code>figure</code> directive</li>
  <li><a href="https://github.com/pradyunsg/furo/commit/beebd7e676d1538891fef4ead30f79d866fe78c2"><code>beebd7e</code></a> Increase the specificity of the admonition title selector</li>
  <li><a href="https://github.com/pradyunsg/furo/commit/834e951f5567fc4b0aa3564d33c0f0011d459263"><code>834e951</code></a> Setup uploads to Percy</li>
  <li><a href="https://github.com/pradyunsg/furo/commit/27bf2c0e6f1b2c3ae9b0a7beed689c4df9bed1b2"><code>27bf2c0</code></a> [pre-commit.ci] pre-commit autoupdate (<a href="https://redirect.github.com/pradyunsg/furo/issues/672">#672</a>)</li>
  <li><a href="https://github.com/pradyunsg/furo/commit/c8b51d09af3dcaac3046f7e761119e9d1b7c9e37"><code>c8b51d0</code></a> Fix how content overflow is handled</li>
  <li><a href="https://github.com/pradyunsg/furo/commit/80afa27a9a7bd0ac9259636239e349656c4726ab"><code>80afa27</code></a> [pre-commit.ci] pre-commit autoupdate (<a href="https://redirect.github.com/pradyunsg/furo/issues/652">#652</a>)</li>
  <li>Additional commits viewable in <a href="https://github.com/pradyunsg/furo/compare/2023.03.27...2023.07.26">compare view</a></li>
  </ul>
  </details>
  <br />


  [![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.7.26)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

  Dependabot 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`.

  [//]: # (dependabot-automerge-start)
  [//]: # (dependabot-automerge-end)

  ---

  <details>
  <summary>Dependabot commands and options</summary>
  <br />

  You can trigger Dependabot actions by commenting on this PR:
  - `@dependabot rebase` will rebase this PR
  - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
  - `@dependabot merge` will merge this PR after your CI passes on it
  - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it
  - `@dependabot cancel merge` will cancel a previously requested merge and block automerging
  - `@dependabot reopen` will reopen this PR if it is closed
  - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
  - `@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)
  - `@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)
  - `@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)


  </details>

  <!-- readthedocs-preview datasette start -->
  ----
  :books: Documentation preview :books:: https://datasette--2121.org.readthedocs.build/en/2121/

  <!-- readthedocs-preview datasette end -->

reactions:
  {"url": "https://api.github.com/repos/simonw/datasette/issues/2121/reactions", "total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0}


node_id: I_kwDOBm6k_c5svwJa
title: Parameters on canned queries: fixed or query-generated list?
state: open
created_at: 2023-07-27T14:07:07Z
updated_at: 2023-07-27T14:07:07Z
author_association: NONE
type: issue
body:
  Hi,

  currently parameters in canned queries are just text fields. It would be cool to have one of the options below. Would you accept a PR doing something in this direction? (Possibly this could even work as a plugin.)

  * adding facets, which would work like facets on tables or views, giving a list of selectable options (and leaving parameters as is)
  * making it possible to provide a query which returns selectable values for a parameter, e.g.
  ```     
  calendar_entries_current_instrument:
          sql: |      
            select * from calendar_entries 
                where 
                      DTEND_UNIX > UNIXEPOCH() and
                      DTSTART_UNIX < UNIXEPOCH() + :days *24*60*60 and
                      current = 1 and
                      MACHINE = :instrument
                order by
                      DTSTART_UNIX
          params:
              days: 
                sql: "SELECT VALUE FROM generate_series(1, 30, 1)"
                # this obviously requires the corresponding sqlite extension
              instrument:
                sql: "SELECT DISTINCT MACHINE FROM calendar_entries"
  ```
  * making it possible to provide a fixed list of parameters
  ```     
  calendar_entries_current_instrument:
          sql: |      
            select * from calendar_entries 
                where 
                      DTEND_UNIX > UNIXEPOCH() and
                      DTSTART_UNIX < UNIXEPOCH() + :days *24*60*60 and
                      current = 1 and
                      MACHINE = :instrument
                order by
                      DTSTART_UNIX
          params:
              days: 
                values: [1, 2, 3, 5, 10, 20, 30]
              instrument:
                values: [supermachine, crappymachine, boringmachine]
  ```

reactions:
  {"url": "https://api.github.com/repos/simonw/datasette/issues/2122/reactions", "total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0}


node_id: I_kwDOBm6k_c5sx2XV
title: datasette serve when invoked with --reload interprets the serve command as a file
state: open
created_at: 2023-07-27T19:07:22Z
updated_at: 2023-09-18T13:02:46Z
author_association: NONE
type: issue
body:
  When running `datasette serve` with the `--reload` flag, the serve command is picked up as a file argument:

  ```
  $ datasette serve --reload test_db
  Starting monitor for PID 13574.
  Error: Invalid value for '[FILES]...': Path 'serve' does not exist.
  Press ENTER or change a file to reload.
  ```

  If a 'serve' file is created it launches properly (albeit with an empty database called serve):

  ```
  $ touch serve; datasette serve --reload test_db
  Starting monitor for PID 13628.
  INFO:     Started server process [13628]
  INFO:     Waiting for application startup.
  INFO:     Application startup complete.
  INFO:     Uvicorn running on http://127.0.0.1:8001 (Press CTRL+C to quit)
  ```

  Version (running from HEAD on main):

  ```
  $ datasette --version
  datasette, version 1.0a2
  ```

  This issue appears to have existed for awhile as https://github.com/simonw/datasette/issues/1380#issuecomment-953366110 mentions the error in a different context.

  I'm happy to debug and land a patch if it's welcome.

reactions:
  {"url": "https://api.github.com/repos/simonw/datasette/issues/2123/reactions", "total_count": 2, "+1": 2, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0}


node_id: PR_kwDOBm6k_c5Wp6Hs
title: Bump sphinx from 6.1.3 to 7.1.1
state: closed
created_at: 2023-07-28T13:23:11Z
updated_at: 2023-08-02T13:28:47Z
closed_at: 2023-08-02T13:28:44Z
author_association: CONTRIBUTOR
pull_request: simonw/datasette/pulls/2124
type: pull
body:
  Bumps [sphinx](https://github.com/sphinx-doc/sphinx) from 6.1.3 to 7.1.1.
  <details>
  <summary>Release notes</summary>
  <p><em>Sourced from <a href="https://github.com/sphinx-doc/sphinx/releases">sphinx's releases</a>.</em></p>
  <blockquote>
  <h2>Sphinx 7.1.1</h2>
  <p>Changelog: <a href="https://www.sphinx-doc.org/en/master/changes.html">https://www.sphinx-doc.org/en/master/changes.html</a></p>
  <h2>Sphinx 7.1.0</h2>
  <p>Changelog: <a href="https://www.sphinx-doc.org/en/master/changes.html">https://www.sphinx-doc.org/en/master/changes.html</a></p>
  <h2>v7.0.1</h2>
  <p>Changelog: <a href="https://www.sphinx-doc.org/en/master/changes.html">https://www.sphinx-doc.org/en/master/changes.html</a></p>
  <h2>v7.0.0</h2>
  <p>Changelog: <a href="https://www.sphinx-doc.org/en/master/changes.html">https://www.sphinx-doc.org/en/master/changes.html</a></p>
  <h2>v7.0.0rc1</h2>
  <p>Changelog: <a href="https://www.sphinx-doc.org/en/master/changes.html">https://www.sphinx-doc.org/en/master/changes.html</a></p>
  <h2>v6.2.1</h2>
  <p>Changelog: <a href="https://www.sphinx-doc.org/en/master/changes.html">https://www.sphinx-doc.org/en/master/changes.html</a></p>
  <h2>v6.2.0</h2>
  <p>Changelog: <a href="https://www.sphinx-doc.org/en/master/changes.html">https://www.sphinx-doc.org/en/master/changes.html</a></p>
  </blockquote>
  </details>
  <details>
  <summary>Changelog</summary>
  <p><em>Sourced from <a href="https://github.com/sphinx-doc/sphinx/blob/master/CHANGES">sphinx's changelog</a>.</em></p>
  <blockquote>
  <h1>Release 7.1.1 (released Jul 27, 2023)</h1>
  <h2>Bugs fixed</h2>
  <ul>
  <li><a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11514">#11514</a>: Fix <code>SOURCE_DATE_EPOCH</code> in multi-line copyright footer.
  Patch by Bénédikt Tran.</li>
  </ul>
  <h1>Release 7.1.0 (released Jul 24, 2023)</h1>
  <h2>Incompatible changes</h2>
  <ul>
  <li>
  <p>Releases are no longer signed, given the <code>change in PyPI policy</code>_.</p>
  <p>.. _change in PyPI policy: <a href="https://blog.pypi.org/posts/2023-05-23-removing-pgp/">https://blog.pypi.org/posts/2023-05-23-removing-pgp/</a></p>
  </li>
  </ul>
  <h2>Deprecated</h2>
  <ul>
  <li><a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11412">#11412</a>: Emit warnings on using a deprecated Python-specific index entry type
  (namely, <code>module</code>, <code>keyword</code>, <code>operator</code>, <code>object</code>, <code>exception</code>,
  <code>statement</code>, and <code>builtin</code>) in the :rst:dir:<code>index</code> directive, and
  set the removal version to Sphinx 9. Patch by Adam Turner.</li>
  </ul>
  <h2>Features added</h2>
  <ul>
  <li><a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11415">#11415</a>: Add a checksum to JavaScript and CSS asset URIs included within
  generated HTML, using the CRC32 algorithm.</li>
  <li>:meth:<code>~sphinx.application.Sphinx.require_sphinx</code> now allows the version
  requirement to be specified as <code>(major, minor)</code>.</li>
  <li><a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11011">#11011</a>: Allow configuring a line-length limit for object signatures, via
  :confval:<code>maximum_signature_line_length</code> and the domain-specific variants.
  If the length of the signature (in characters) is greater than the configured
  limit, each parameter in the signature will be split to its own logical line.
  This behaviour may also be controlled by options on object description
  directives, for example :rst:dir:<code>py:function:single-line-parameter-list</code>.
  Patch by Thomas Louf, Adam Turner, and Jean-François B.</li>
  <li><a href="https://redirect.github.com/sphinx-doc/sphinx/issues/10983">#10983</a>: Support for multiline copyright statements in the footer block.
  Patch by Stefanie Molin</li>
  <li><code>sphinx.util.display.status_iterator</code> now clears the current line
  with ANSI control codes, rather than overprinting with space characters.</li>
  <li><a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11431">#11431</a>: linkcheck: Treat SSL failures as broken links.
  Patch by Bénédikt Tran</li>
  <li><a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11157">#11157</a>: Keep the <code>translated</code> attribute on translated nodes.</li>
  <li><a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11451">#11451</a>: Improve the traceback displayed when using :option:<code>sphinx-build -T</code>
  in parallel builds. Patch by Bénédikt Tran</li>
  </ul>
  <!-- raw HTML omitted -->
  </blockquote>
  <p>... (truncated)</p>
  </details>
  <details>
  <summary>Commits</summary>
  <ul>
  <li><a href="https://github.com/sphinx-doc/sphinx/commit/d8d73c16b8b86df8f1a32698229a2b818fea2e98"><code>d8d73c1</code></a> Bump to 7.1.1 final</li>
  <li><a href="https://github.com/sphinx-doc/sphinx/commit/a54e630a21a6d9b7e80a22e969e3a86e35678d2d"><code>a54e630</code></a> [internationalisation] Update message catalogues</li>
  <li><a href="https://github.com/sphinx-doc/sphinx/commit/8452300d54dce2da751941d9547dd54dc03e69bf"><code>8452300</code></a> Fix multi-line copyright when <code>SOURCE_DATE_EPOCH</code> is set (<a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11524">#11524</a>)</li>
  <li><a href="https://github.com/sphinx-doc/sphinx/commit/fe08cec019c52c15b7f7365013134e3f3d1b3739"><code>fe08cec</code></a> bump version</li>
  <li><a href="https://github.com/sphinx-doc/sphinx/commit/e560f6334aa87af07304415e6aeaf42d03d1c525"><code>e560f63</code></a> Bump to 7.1.0 final</li>
  <li><a href="https://github.com/sphinx-doc/sphinx/commit/066e0fabc60c55072b3f75876637a44fdcb51332"><code>066e0fa</code></a> Add translation progress information (<a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11509">#11509</a>)</li>
  <li><a href="https://github.com/sphinx-doc/sphinx/commit/0882914d5c5057ad3cec280c0142cfe5f6965844"><code>0882914</code></a> Target PyPI in create-release.yml</li>
  <li><a href="https://github.com/sphinx-doc/sphinx/commit/21fbee5e83a3e9d34e589d06c66d928f3a67923c"><code>21fbee5</code></a> Fix OIDC token payload</li>
  <li><a href="https://github.com/sphinx-doc/sphinx/commit/1a403e4f9ad4d8d7a3e4c7c34f55d9a45ed600bd"><code>1a403e4</code></a> Add informational log messaging</li>
  <li><a href="https://github.com/sphinx-doc/sphinx/commit/258b0ea9fcdd05221ebead5e5c162a7ad37c4412"><code>258b0ea</code></a> Revert &quot;Switch to using <code>github.request</code>&quot;</li>
  <li>Additional commits viewable in <a href="https://github.com/sphinx-doc/sphinx/compare/v6.1.3...v7.1.1">compare view</a></li>
  </ul>
  </details>
  <br />


  [![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.1.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

  Dependabot 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`.

  [//]: # (dependabot-automerge-start)
  [//]: # (dependabot-automerge-end)

  ---

  <details>
  <summary>Dependabot commands and options</summary>
  <br />

  You can trigger Dependabot actions by commenting on this PR:
  - `@dependabot rebase` will rebase this PR
  - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
  - `@dependabot merge` will merge this PR after your CI passes on it
  - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it
  - `@dependabot cancel merge` will cancel a previously requested merge and block automerging
  - `@dependabot reopen` will reopen this PR if it is closed
  - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
  - `@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)
  - `@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)
  - `@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)


  </details>

  <!-- readthedocs-preview datasette start -->
  ----
  :books: Documentation preview :books:: https://datasette--2124.org.readthedocs.build/en/2124/

  <!-- readthedocs-preview datasette end -->

reactions:
  {"url": "https://api.github.com/repos/simonw/datasette/issues/2124/reactions", "total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0}


node_id: PR_kwDOD079W85WtUKG
title: photos-to-sql not found?
state: closed
created_at: 2023-07-29T09:59:42Z
updated_at: 2023-07-29T10:01:27Z
closed_at: 2023-07-29T10:01:23Z
author_association: FIRST_TIME_CONTRIBUTOR
pull_request: dogsheep/dogsheep-photos/pulls/38
type: pull
body:
  I wonder if `photos-to-sql` is an old name for `dogsheep-photos`, because I can't find it anywhere.

  I can't actually get this command to work (`sqlite3.OperationalError: no such table: attached.ZGENERICASSET` thrown) but I don't think that's related

reactions:
  {"url": "https://api.github.com/repos/dogsheep/dogsheep-photos/issues/38/reactions", "total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0}


node_id: PR_kwDOD079W85WtVyk
title: Missing option in datasette instructions
state: open
created_at: 2023-07-29T10:34:48Z
updated_at: 2023-07-29T10:34:48Z
author_association: FIRST_TIME_CONTRIBUTOR
pull_request: dogsheep/dogsheep-photos/pulls/39
body: Gotta tell it where to look
type: pull
reactions:
  {"url": "https://api.github.com/repos/dogsheep/dogsheep-photos/issues/39/reactions", "total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0}


node_id: PR_kwDOBm6k_c5XArm3
title: Bump sphinx from 6.1.3 to 7.1.2
state: closed
created_at: 2023-08-02T13:28:39Z
updated_at: 2023-08-07T16:20:30Z
closed_at: 2023-08-07T16:20:27Z
author_association: CONTRIBUTOR
pull_request: simonw/datasette/pulls/2125
type: pull
body:
  Bumps [sphinx](https://github.com/sphinx-doc/sphinx) from 6.1.3 to 7.1.2.
  <details>
  <summary>Release notes</summary>
  <p><em>Sourced from <a href="https://github.com/sphinx-doc/sphinx/releases">sphinx's releases</a>.</em></p>
  <blockquote>
  <h2>Sphinx 7.1.2</h2>
  <p>Changelog: <a href="https://www.sphinx-doc.org/en/master/changes.html">https://www.sphinx-doc.org/en/master/changes.html</a></p>
  <h2>Sphinx 7.1.1</h2>
  <p>Changelog: <a href="https://www.sphinx-doc.org/en/master/changes.html">https://www.sphinx-doc.org/en/master/changes.html</a></p>
  <h2>Sphinx 7.1.0</h2>
  <p>Changelog: <a href="https://www.sphinx-doc.org/en/master/changes.html">https://www.sphinx-doc.org/en/master/changes.html</a></p>
  <h2>v7.0.1</h2>
  <p>Changelog: <a href="https://www.sphinx-doc.org/en/master/changes.html">https://www.sphinx-doc.org/en/master/changes.html</a></p>
  <h2>v7.0.0</h2>
  <p>Changelog: <a href="https://www.sphinx-doc.org/en/master/changes.html">https://www.sphinx-doc.org/en/master/changes.html</a></p>
  <h2>v7.0.0rc1</h2>
  <p>Changelog: <a href="https://www.sphinx-doc.org/en/master/changes.html">https://www.sphinx-doc.org/en/master/changes.html</a></p>
  <h2>v6.2.1</h2>
  <p>Changelog: <a href="https://www.sphinx-doc.org/en/master/changes.html">https://www.sphinx-doc.org/en/master/changes.html</a></p>
  <h2>v6.2.0</h2>
  <p>Changelog: <a href="https://www.sphinx-doc.org/en/master/changes.html">https://www.sphinx-doc.org/en/master/changes.html</a></p>
  </blockquote>
  </details>
  <details>
  <summary>Changelog</summary>
  <p><em>Sourced from <a href="https://github.com/sphinx-doc/sphinx/blob/master/CHANGES">sphinx's changelog</a>.</em></p>
  <blockquote>
  <h1>Release 7.1.2 (released Aug 02, 2023)</h1>
  <h2>Bugs fixed</h2>
  <ul>
  <li><a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11542">#11542</a>: linkcheck: Properly respect :confval:<code>linkcheck_anchors</code>
  and do not spuriously report failures to validate anchors.
  Patch by James Addison.</li>
  </ul>
  <h1>Release 7.1.1 (released Jul 27, 2023)</h1>
  <h2>Bugs fixed</h2>
  <ul>
  <li><a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11514">#11514</a>: Fix <code>SOURCE_DATE_EPOCH</code> in multi-line copyright footer.
  Patch by Bénédikt Tran.</li>
  </ul>
  <h1>Release 7.1.0 (released Jul 24, 2023)</h1>
  <h2>Incompatible changes</h2>
  <ul>
  <li>
  <p>Releases are no longer signed, given the <code>change in PyPI policy</code>_.</p>
  <p>.. _change in PyPI policy: <a href="https://blog.pypi.org/posts/2023-05-23-removing-pgp/">https://blog.pypi.org/posts/2023-05-23-removing-pgp/</a></p>
  </li>
  </ul>
  <h2>Deprecated</h2>
  <ul>
  <li><a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11412">#11412</a>: Emit warnings on using a deprecated Python-specific index entry type
  (namely, <code>module</code>, <code>keyword</code>, <code>operator</code>, <code>object</code>, <code>exception</code>,
  <code>statement</code>, and <code>builtin</code>) in the :rst:dir:<code>index</code> directive, and
  set the removal version to Sphinx 9. Patch by Adam Turner.</li>
  </ul>
  <h2>Features added</h2>
  <ul>
  <li><a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11415">#11415</a>: Add a checksum to JavaScript and CSS asset URIs included within
  generated HTML, using the CRC32 algorithm.</li>
  <li>:meth:<code>~sphinx.application.Sphinx.require_sphinx</code> now allows the version
  requirement to be specified as <code>(major, minor)</code>.</li>
  <li><a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11011">#11011</a>: Allow configuring a line-length limit for object signatures, via
  :confval:<code>maximum_signature_line_length</code> and the domain-specific variants.
  If the length of the signature (in characters) is greater than the configured
  limit, each parameter in the signature will be split to its own logical line.
  This behaviour may also be controlled by options on object description
  directives, for example :rst:dir:<code>py:function:single-line-parameter-list</code>.</li>
  </ul>
  <!-- raw HTML omitted -->
  </blockquote>
  <p>... (truncated)</p>
  </details>
  <details>
  <summary>Commits</summary>
  <ul>
  <li><a href="https://github.com/sphinx-doc/sphinx/commit/320d0b631cc7d9617f5167cc61c9284674f5b2df"><code>320d0b6</code></a> Bump to 7.1.2 final</li>
  <li><a href="https://github.com/sphinx-doc/sphinx/commit/06c1339bb36378512d2e27bcff86b6bd5db0dc0a"><code>06c1339</code></a> Ensure that <code>linkcheck_anchors</code> is properly respected (<a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11544">#11544</a>)</li>
  <li><a href="https://github.com/sphinx-doc/sphinx/commit/89808c6f49e1738765d18309244dca0156ee28f6"><code>89808c6</code></a> Emend attribution for <a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11431">GH-11431</a> in CHANGES (<a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11547">#11547</a>)</li>
  <li><a href="https://github.com/sphinx-doc/sphinx/commit/4958d2abf1abb1c3a10e77d8297a746cc90d5234"><code>4958d2a</code></a> Fix flake8 E231 reported linting failure</li>
  <li><a href="https://github.com/sphinx-doc/sphinx/commit/4862da883f8c984e8f15a8643c61702f90947d6c"><code>4862da8</code></a> Bump version</li>
  <li><a href="https://github.com/sphinx-doc/sphinx/commit/d8d73c16b8b86df8f1a32698229a2b818fea2e98"><code>d8d73c1</code></a> Bump to 7.1.1 final</li>
  <li><a href="https://github.com/sphinx-doc/sphinx/commit/a54e630a21a6d9b7e80a22e969e3a86e35678d2d"><code>a54e630</code></a> [internationalisation] Update message catalogues</li>
  <li><a href="https://github.com/sphinx-doc/sphinx/commit/8452300d54dce2da751941d9547dd54dc03e69bf"><code>8452300</code></a> Fix multi-line copyright when <code>SOURCE_DATE_EPOCH</code> is set (<a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11524">#11524</a>)</li>
  <li><a href="https://github.com/sphinx-doc/sphinx/commit/fe08cec019c52c15b7f7365013134e3f3d1b3739"><code>fe08cec</code></a> bump version</li>
  <li><a href="https://github.com/sphinx-doc/sphinx/commit/e560f6334aa87af07304415e6aeaf42d03d1c525"><code>e560f63</code></a> Bump to 7.1.0 final</li>
  <li>Additional commits viewable in <a href="https://github.com/sphinx-doc/sphinx/compare/v6.1.3...v7.1.2">compare view</a></li>
  </ul>
  </details>
  <br />


  [![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.1.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

  Dependabot 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`.

  [//]: # (dependabot-automerge-start)
  [//]: # (dependabot-automerge-end)

  ---

  <details>
  <summary>Dependabot commands and options</summary>
  <br />

  You can trigger Dependabot actions by commenting on this PR:
  - `@dependabot rebase` will rebase this PR
  - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
  - `@dependabot merge` will merge this PR after your CI passes on it
  - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it
  - `@dependabot cancel merge` will cancel a previously requested merge and block automerging
  - `@dependabot reopen` will reopen this PR if it is closed
  - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
  - `@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)
  - `@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)
  - `@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)


  </details>

  <!-- readthedocs-preview datasette start -->
  ----
  :books: Documentation preview :books:: https://datasette--2125.org.readthedocs.build/en/2125/

  <!-- readthedocs-preview datasette end -->

reactions:
  {"url": "https://api.github.com/repos/simonw/datasette/issues/2125/reactions", "total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0}


node_id: I_kwDOBm6k_c5tkbnu
title: Permissions in metadata.yml / metadata.json
state: closed
created_at: 2023-08-06T16:24:10Z
updated_at: 2023-08-11T05:52:30Z
closed_at: 2023-08-11T05:52:29Z
author_association: NONE
type: issue
state_reason: completed
body:
  https://docs.datasette.io/en/latest/authentication.html#other-permissions-in-metadata says the following:

  > For all other permissions, you can use one or more "permissions" blocks in your metadata.

  > To grant access to the permissions debug tool to all signed in users you can grant permissions-debug to any actor with an id matching the wildcard * by adding this a the root of your metadata:

  ```yaml
  permissions:
    debug-menu:
      id: '*'
  ```

  I tried this.

  My `metadata.yml` file looks like:

  ```yaml
  permissions:
    debug-menu:
      id: '*'
    permissions-debug:
      id: '*'
  plugins:
    datasette-auth-passwords:
      myuser_password_hash:
        $env: "PASSWORD_HASH_MYUSER"
  ```

  And then I run

  ```zsh
  datasette -m metadata.yml tiddlywiki.db --root
  ```

  And I open a session for the "root" user of datasette with the link given.

  I open a private browser session and log in as "myuser" from http://127.0.0.1:8001/-/login

  Then I check http://127.0.0.1:8001/-/actor which confirms that I am logged in as the "myuser" actor

  ```json
  {
      "actor": {
          "id": "myuser"
      }
  }
  ```

  In the session where I am logged in as "myuser" I then try to go to http://127.0.0.1:8001/-/permissions

  But all I get there as the logged in user "myuser" is

  > Forbidden
  >
  > Permission denied

  And then if I check the http://127.0.0.1:8001/-/permissions as the datasette "root" user from another browser session, I see:

  > permissions-debug checked at 2023-08-06T16:22:58.997841 ✗ (used default)
  >
  > Actor: {"id": "myuser"}

  It seems that in spite of having tried to give the `permissions-debug` permission to the "myuser" user in my `metadata.yml` file, datasette does not agree that "myuser" has permission `permissions-debug`..

  What do I need to do differently so that my "myuser" user is able to access http://127.0.0.1:8001/-/permissions ?

reactions:
  {"url": "https://api.github.com/repos/simonw/datasette/issues/2126/reactions", "total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0}


node_id: I_kwDOBm6k_c5tlNA4
title: Context base class to support documenting the context
state: open
created_at: 2023-08-07T00:01:02Z
updated_at: 2023-08-10T01:30:25Z
author_association: OWNER
type: issue
body:
  This idea first came up here:
  - https://github.com/simonw/datasette/issues/2112#issuecomment-1652751140

  If `datasette.render_template(...)` takes an optional `Context` subclass as an alternative to a context dictionary, I could then use dataclasses to define the context made available to specific templates - which then gives me something I can use to help document what they are.

  Also refs:
  - https://github.com/simonw/datasette/issues/1510

reactions:
  {"url": "https://api.github.com/repos/simonw/datasette/issues/2127/reactions", "total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0}


node_id: I_kwDOCGYnMM5toi1T
title: Handling CSV/file input that contains NUL bytes
state: open
created_at: 2023-08-07T12:24:14Z
updated_at: 2023-08-07T12:24:14Z
author_association: NONE
type: issue
body:
  I was using sqlite-utils to create a DB from a CSV and it turns out the CSV contains a NUL byte.

  When the processing reaches the line that contains the NUL an exception is raised.

  I'm wondering if there is something that can be done in `sqlite-utils` to say "skip lines with encoding errors" or some such. I think it isn't super straightforward though as the exception comes from inside the `csv` module that does all the parsing.

  Concretely the file is the `KernelVersions.csv` from https://www.kaggle.com/datasets/kaggle/meta-kaggle

  This is the command and output:
  ```
  $ sqlite-utils insert --csv kaggle.db kaggle KernelVersions.csv
    [------------------------------------]    0%
    [#####################---------------]   60%  00:04:24Traceback (most recent call last):
    File "/home/foobar/miniconda/envs/meta-kaggle/bin/sqlite-utils", line 10, in <module>
      sys.exit(cli())
    File "/home/foobar/miniconda/envs/meta-kaggle/lib/python3.10/site-packages/click/core.py", line 1128, in __call__
      return self.main(*args, **kwargs)
    File "/home/foobar/miniconda/envs/meta-kaggle/lib/python3.10/site-packages/click/core.py", line 1053, in main
      rv = self.invoke(ctx)
    File "/home/foobar/miniconda/envs/meta-kaggle/lib/python3.10/site-packages/click/core.py", line 1659, in invoke
      return _process_result(sub_ctx.command.invoke(sub_ctx))
    File "/home/foobar/miniconda/envs/meta-kaggle/lib/python3.10/site-packages/click/core.py", line 1395, in invoke
      return ctx.invoke(self.callback, **ctx.params)
    File "/home/foobar/miniconda/envs/meta-kaggle/lib/python3.10/site-packages/click/core.py", line 754, in invoke
      return __callback(*args, **kwargs)
    File "/home/foobar/miniconda/envs/meta-kaggle/lib/python3.10/site-packages/sqlite_utils/cli.py", line 1223, in insert
      insert_upsert_implementation(
    File "/home/foobar/miniconda/envs/meta-kaggle/lib/python3.10/site-packages/sqlite_utils/cli.py", line 1085, in insert_upsert_implementation
      db[table].insert_all(
    File "/home/foobar/miniconda/envs/meta-kaggle/lib/python3.10/site-packages/sqlite_utils/db.py", line 3198, in insert_all
      chunk = list(chunk)
    File "/home/foobar/miniconda/envs/meta-kaggle/lib/python3.10/site-packages/sqlite_utils/db.py", line 3742, in fix_square_braces
      for record in records:
    File "/home/foobar/miniconda/envs/meta-kaggle/lib/python3.10/site-packages/sqlite_utils/cli.py", line 1071, in <genexpr>
      docs = (decode_base64_values(doc) for doc in docs)
    File "/home/foobar/miniconda/envs/meta-kaggle/lib/python3.10/site-packages/sqlite_utils/cli.py", line 1068, in <genexpr>
      docs = (verify_is_dict(doc) for doc in docs)
    File "/home/foobar/miniconda/envs/meta-kaggle/lib/python3.10/site-packages/sqlite_utils/cli.py", line 1003, in <genexpr>
      docs = (dict(zip(headers, row)) for row in reader)
  _csv.Error: line contains NUL
  ```

reactions:
  {"url": "https://api.github.com/repos/simonw/sqlite-utils/issues/582/reactions", "total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0}


node_id: PR_kwDOBm6k_c5XWhWF
title: Bump blacken-docs, furo, blacken-docs
state: closed
created_at: 2023-08-07T15:50:40Z
updated_at: 2023-08-07T16:19:25Z
closed_at: 2023-08-07T16:19:24Z
author_association: CONTRIBUTOR
pull_request: simonw/datasette/pulls/2128
type: pull
body:
  Bumps the python-packages group with 3 updates: [sphinx](https://github.com/sphinx-doc/sphinx), [furo](https://github.com/pradyunsg/furo) and [blacken-docs](https://github.com/asottile/blacken-docs).

  Updates `sphinx` from 6.1.3 to 7.1.2
  <details>
  <summary>Release notes</summary>
  <p><em>Sourced from <a href="https://github.com/sphinx-doc/sphinx/releases">sphinx's releases</a>.</em></p>
  <blockquote>
  <h2>Sphinx 7.1.2</h2>
  <p>Changelog: <a href="https://www.sphinx-doc.org/en/master/changes.html">https://www.sphinx-doc.org/en/master/changes.html</a></p>
  <h2>Sphinx 7.1.1</h2>
  <p>Changelog: <a href="https://www.sphinx-doc.org/en/master/changes.html">https://www.sphinx-doc.org/en/master/changes.html</a></p>
  <h2>Sphinx 7.1.0</h2>
  <p>Changelog: <a href="https://www.sphinx-doc.org/en/master/changes.html">https://www.sphinx-doc.org/en/master/changes.html</a></p>
  <h2>v7.0.1</h2>
  <p>Changelog: <a href="https://www.sphinx-doc.org/en/master/changes.html">https://www.sphinx-doc.org/en/master/changes.html</a></p>
  <h2>v7.0.0</h2>
  <p>Changelog: <a href="https://www.sphinx-doc.org/en/master/changes.html">https://www.sphinx-doc.org/en/master/changes.html</a></p>
  <h2>v7.0.0rc1</h2>
  <p>Changelog: <a href="https://www.sphinx-doc.org/en/master/changes.html">https://www.sphinx-doc.org/en/master/changes.html</a></p>
  <h2>v6.2.1</h2>
  <p>Changelog: <a href="https://www.sphinx-doc.org/en/master/changes.html">https://www.sphinx-doc.org/en/master/changes.html</a></p>
  <h2>v6.2.0</h2>
  <p>Changelog: <a href="https://www.sphinx-doc.org/en/master/changes.html">https://www.sphinx-doc.org/en/master/changes.html</a></p>
  </blockquote>
  </details>
  <details>
  <summary>Changelog</summary>
  <p><em>Sourced from <a href="https://github.com/sphinx-doc/sphinx/blob/master/CHANGES">sphinx's changelog</a>.</em></p>
  <blockquote>
  <h1>Release 7.1.2 (released Aug 02, 2023)</h1>
  <h2>Bugs fixed</h2>
  <ul>
  <li><a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11542">#11542</a>: linkcheck: Properly respect :confval:<code>linkcheck_anchors</code>
  and do not spuriously report failures to validate anchors.
  Patch by James Addison.</li>
  </ul>
  <h1>Release 7.1.1 (released Jul 27, 2023)</h1>
  <h2>Bugs fixed</h2>
  <ul>
  <li><a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11514">#11514</a>: Fix <code>SOURCE_DATE_EPOCH</code> in multi-line copyright footer.
  Patch by Bénédikt Tran.</li>
  </ul>
  <h1>Release 7.1.0 (released Jul 24, 2023)</h1>
  <h2>Incompatible changes</h2>
  <ul>
  <li>
  <p>Releases are no longer signed, given the <code>change in PyPI policy</code>_.</p>
  <p>.. _change in PyPI policy: <a href="https://blog.pypi.org/posts/2023-05-23-removing-pgp/">https://blog.pypi.org/posts/2023-05-23-removing-pgp/</a></p>
  </li>
  </ul>
  <h2>Deprecated</h2>
  <ul>
  <li><a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11412">#11412</a>: Emit warnings on using a deprecated Python-specific index entry type
  (namely, <code>module</code>, <code>keyword</code>, <code>operator</code>, <code>object</code>, <code>exception</code>,
  <code>statement</code>, and <code>builtin</code>) in the :rst:dir:<code>index</code> directive, and
  set the removal version to Sphinx 9. Patch by Adam Turner.</li>
  </ul>
  <h2>Features added</h2>
  <ul>
  <li><a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11415">#11415</a>: Add a checksum to JavaScript and CSS asset URIs included within
  generated HTML, using the CRC32 algorithm.</li>
  <li>:meth:<code>~sphinx.application.Sphinx.require_sphinx</code> now allows the version
  requirement to be specified as <code>(major, minor)</code>.</li>
  <li><a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11011">#11011</a>: Allow configuring a line-length limit for object signatures, via
  :confval:<code>maximum_signature_line_length</code> and the domain-specific variants.
  If the length of the signature (in characters) is greater than the configured
  limit, each parameter in the signature will be split to its own logical line.
  This behaviour may also be controlled by options on object description
  directives, for example :rst:dir:<code>py:function:single-line-parameter-list</code>.</li>
  </ul>
  <!-- raw HTML omitted -->
  </blockquote>
  <p>... (truncated)</p>
  </details>
  <details>
  <summary>Commits</summary>
  <ul>
  <li><a href="https://github.com/sphinx-doc/sphinx/commit/320d0b631cc7d9617f5167cc61c9284674f5b2df"><code>320d0b6</code></a> Bump to 7.1.2 final</li>
  <li><a href="https://github.com/sphinx-doc/sphinx/commit/06c1339bb36378512d2e27bcff86b6bd5db0dc0a"><code>06c1339</code></a> Ensure that <code>linkcheck_anchors</code> is properly respected (<a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11544">#11544</a>)</li>
  <li><a href="https://github.com/sphinx-doc/sphinx/commit/89808c6f49e1738765d18309244dca0156ee28f6"><code>89808c6</code></a> Emend attribution for <a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11431">GH-11431</a> in CHANGES (<a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11547">#11547</a>)</li>
  <li><a href="https://github.com/sphinx-doc/sphinx/commit/4958d2abf1abb1c3a10e77d8297a746cc90d5234"><code>4958d2a</code></a> Fix flake8 E231 reported linting failure</li>
  <li><a href="https://github.com/sphinx-doc/sphinx/commit/4862da883f8c984e8f15a8643c61702f90947d6c"><code>4862da8</code></a> Bump version</li>
  <li><a href="https://github.com/sphinx-doc/sphinx/commit/d8d73c16b8b86df8f1a32698229a2b818fea2e98"><code>d8d73c1</code></a> Bump to 7.1.1 final</li>
  <li><a href="https://github.com/sphinx-doc/sphinx/commit/a54e630a21a6d9b7e80a22e969e3a86e35678d2d"><code>a54e630</code></a> [internationalisation] Update message catalogues</li>
  <li><a href="https://github.com/sphinx-doc/sphinx/commit/8452300d54dce2da751941d9547dd54dc03e69bf"><code>8452300</code></a> Fix multi-line copyright when <code>SOURCE_DATE_EPOCH</code> is set (<a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11524">#11524</a>)</li>
  <li><a href="https://github.com/sphinx-doc/sphinx/commit/fe08cec019c52c15b7f7365013134e3f3d1b3739"><code>fe08cec</code></a> bump version</li>
  <li><a href="https://github.com/sphinx-doc/sphinx/commit/e560f6334aa87af07304415e6aeaf42d03d1c525"><code>e560f63</code></a> Bump to 7.1.0 final</li>
  <li>Additional commits viewable in <a href="https://github.com/sphinx-doc/sphinx/compare/v6.1.3...v7.1.2">compare view</a></li>
  </ul>
  </details>
  <br />

  Updates `furo` from 2023.3.27 to 2023.7.26
  <details>
  <summary>Changelog</summary>
  <p><em>Sourced from <a href="https://github.com/pradyunsg/furo/blob/main/docs/changelog.md">furo's changelog</a>.</em></p>
  <blockquote>
  <h1>Changelog</h1>
  <!-- raw HTML omitted -->
  <h2>2023.07.26 -- Vigilant Volt</h2>
  <ul>
  <li>Fix compatiblity with Sphinx 7.1.</li>
  <li>Improve how content overflow is handled.</li>
  <li>Improve how literal blocks containing inline code are handled.</li>
  </ul>
  <h2>2023.05.20 -- Unassuming Ultramarine</h2>
  <ul>
  <li>✨ Add support for Sphinx 7.</li>
  <li>Drop support for Sphinx 5.</li>
  <li>Improve the screen-reader label for sidebar collapse.</li>
  <li>Make it easier to create derived themes from Furo.</li>
  <li>Bump all JS dependencies (NodeJS and npm packages).</li>
  </ul>
  <h2>2023.03.27 -- Tasty Tangerine</h2>
  <ul>
  <li>Regenerate with newer version of sphinx-theme-builder, to fix RECORD hashes.</li>
  <li>Add missing class to Font Awesome examples</li>
  </ul>
  <h2>2023.03.23 -- Sassy Saffron</h2>
  <ul>
  <li>Update Python version classifiers.</li>
  <li>Increase the icon size in mobile header.</li>
  <li>Increase admonition title bg opacity.</li>
  <li>Change the default API background to transparent.</li>
  <li>Transition the API background change.</li>
  <li>Remove the &quot;indent&quot; of API entries which have a background.</li>
  <li>Break long inline code literals.</li>
  </ul>
  <h2>2022.12.07 -- Reverent Raspberry</h2>
  <ul>
  <li>✨ Add support for Sphinx 6.</li>
  <li>✨ Improve footnote presentation with docutils 0.18+.</li>
  <li>Drop support for Sphinx 4.</li>
  <li>Improve documentation about what the edit button does.</li>
  <li>Improve handling of empty-flexboxes for better print experience on Chrome.</li>
  <li>Improve styling for inline signatures.</li>
  </ul>
  <!-- raw HTML omitted -->
  </blockquote>
  <p>... (truncated)</p>
  </details>
  <details>
  <summary>Commits</summary>
  <ul>
  <li><a href="https://github.com/pradyunsg/furo/commit/35f5307acc66d63ddb2e50eebc79a389518e881a"><code>35f5307</code></a> Prepare release: 2023.07.26</li>
  <li><a href="https://github.com/pradyunsg/furo/commit/0a8bedc51399777be2d01f2401fd52a32d9f6673"><code>0a8bedc</code></a> Update changelog</li>
  <li><a href="https://github.com/pradyunsg/furo/commit/a92dd0c2bfa398825e239171925a81bdc428e90a"><code>a92dd0c</code></a> Make <code>_add_asset_hashes</code> a no-op with Sphinx 7.1</li>
  <li><a href="https://github.com/pradyunsg/furo/commit/f8db95bed5d1c57b4ea6bf536c65560fa9ae33a9"><code>f8db95b</code></a> Improve literals with inline code are handled</li>
  <li><a href="https://github.com/pradyunsg/furo/commit/1680dbefd61766a28e43880ae05a9f5cc0e7f19b"><code>1680dbe</code></a> Document the use of <code>figclass</code> with <code>figure</code> directive</li>
  <li><a href="https://github.com/pradyunsg/furo/commit/beebd7e676d1538891fef4ead30f79d866fe78c2"><code>beebd7e</code></a> Increase the specificity of the admonition title selector</li>
  <li><a href="https://github.com/pradyunsg/furo/commit/834e951f5567fc4b0aa3564d33c0f0011d459263"><code>834e951</code></a> Setup uploads to Percy</li>
  <li><a href="https://github.com/pradyunsg/furo/commit/27bf2c0e6f1b2c3ae9b0a7beed689c4df9bed1b2"><code>27bf2c0</code></a> [pre-commit.ci] pre-commit autoupdate (<a href="https://redirect.github.com/pradyunsg/furo/issues/672">#672</a>)</li>
  <li><a href="https://github.com/pradyunsg/furo/commit/c8b51d09af3dcaac3046f7e761119e9d1b7c9e37"><code>c8b51d0</code></a> Fix how content overflow is handled</li>
  <li><a href="https://github.com/pradyunsg/furo/commit/80afa27a9a7bd0ac9259636239e349656c4726ab"><code>80afa27</code></a> [pre-commit.ci] pre-commit autoupdate (<a href="https://redirect.github.com/pradyunsg/furo/issues/652">#652</a>)</li>
  <li>Additional commits viewable in <a href="https://github.com/pradyunsg/furo/compare/2023.03.27...2023.07.26">compare view</a></li>
  </ul>
  </details>
  <br />

  Updates `blacken-docs` from 1.14.0 to 1.15.0
  <details>
  <summary>Changelog</summary>
  <p><em>Sourced from <a href="https://github.com/adamchainz/blacken-docs/blob/main/CHANGELOG.rst">blacken-docs's changelog</a>.</em></p>
  <blockquote>
  <h2>1.15.0 (2023-07-09)</h2>
  <ul>
  <li>Drop Python 3.7 support.</li>
  </ul>
  </blockquote>
  </details>
  <details>
  <summary>Commits</summary>
  <ul>
  <li><a href="https://github.com/adamchainz/blacken-docs/commit/2e74dc4c30c336176e76e0426c66f09a4e79df9c"><code>2e74dc4</code></a> Version 1.15.0</li>
  <li><a href="https://github.com/adamchainz/blacken-docs/commit/8ddb2f1269b7652a9b668faa92c9d63d764696c0"><code>8ddb2f1</code></a> [pre-commit.ci] pre-commit autoupdate (<a href="https://redirect.github.com/asottile/blacken-docs/issues/257">#257</a>)</li>
  <li><a href="https://github.com/adamchainz/blacken-docs/commit/64fbca6cad36db1822528ece7f97a8152d29e05f"><code>64fbca6</code></a> Drop Python 3.7 support (<a href="https://redirect.github.com/asottile/blacken-docs/issues/256">#256</a>)</li>
  <li><a href="https://github.com/adamchainz/blacken-docs/commit/f6a0817dbb7957f96ea6cc251edf3a50bf1c3c08"><code>f6a0817</code></a> [pre-commit.ci] pre-commit autoupdate (<a href="https://redirect.github.com/asottile/blacken-docs/issues/255">#255</a>)</li>
  <li><a href="https://github.com/adamchainz/blacken-docs/commit/cbdcb50b125b4f2fdb470122b2ba5e3c15de241a"><code>cbdcb50</code></a> [pre-commit.ci] pre-commit autoupdate (<a href="https://redirect.github.com/asottile/blacken-docs/issues/254">#254</a>)</li>
  <li><a href="https://github.com/adamchainz/blacken-docs/commit/37fc70ee00c7063777ed7343c1bd26fceb5422a6"><code>37fc70e</code></a> Upgrade requirements (<a href="https://redirect.github.com/asottile/blacken-docs/issues/253">#253</a>)</li>
  <li><a href="https://github.com/adamchainz/blacken-docs/commit/7bbe434415ce9f590cb057010590a648e7bea072"><code>7bbe434</code></a> [pre-commit.ci] pre-commit autoupdate (<a href="https://redirect.github.com/asottile/blacken-docs/issues/250">#250</a>)</li>
  <li>See full diff in <a href="https://github.com/asottile/blacken-docs/compare/1.14.0...1.15.0">compare view</a></li>
  </ul>
  </details>
  <br />


  Dependabot 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`.

  [//]: # (dependabot-automerge-start)
  [//]: # (dependabot-automerge-end)

  ---

  <details>
  <summary>Dependabot commands and options</summary>
  <br />

  You can trigger Dependabot actions by commenting on this PR:
  - `@dependabot rebase` will rebase this PR
  - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
  - `@dependabot merge` will merge this PR after your CI passes on it
  - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it
  - `@dependabot cancel merge` will cancel a previously requested merge and block automerging
  - `@dependabot reopen` will reopen this PR if it is closed
  - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually


  </details>

  <!-- readthedocs-preview datasette start -->
  ----
  :books: Documentation preview :books:: https://datasette--2128.org.readthedocs.build/en/2128/

  <!-- readthedocs-preview datasette end -->

reactions:
  {"url": "https://api.github.com/repos/simonw/datasette/issues/2128/reactions", "total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0}


node_id: I_kwDOBm6k_c5tsSCd
title: CSV ?sql= should indicate errors
state: open
created_at: 2023-08-07T23:13:04Z
updated_at: 2023-08-08T02:02:21Z
author_association: OWNER
type: issue
body:
  > https://latest.datasette.io/_memory.csv?sql=select+blah is a blank page right now:

  ```bash
  curl -I 'https://latest.datasette.io/_memory.csv?sql=select+blah'
  ```
  ```
  HTTP/2 200 
  access-control-allow-origin: *
  access-control-allow-headers: Authorization, Content-Type
  access-control-expose-headers: Link
  access-control-allow-methods: GET, POST, HEAD, OPTIONS
  access-control-max-age: 3600
  content-type: text/plain; charset=utf-8
  x-databases: _memory, _internal, fixtures, fixtures2, extra_database, ephemeral
  date: Mon, 07 Aug 2023 23:12:15 GMT
  server: Google Frontend
  ```

  _Originally posted by @simonw in https://github.com/simonw/datasette/issues/2118#issuecomment-1668688947_

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}


node_id: I_kwDOBm6k_c5tsTOP
title: Render plugin mechanism needs `error` and `truncated` fields
state: closed
created_at: 2023-08-07T23:19:19Z
updated_at: 2023-08-08T01:51:54Z
closed_at: 2023-08-08T01:47:42Z
author_association: OWNER
type: issue
state_reason: completed
body:
  While working on:
  - https://github.com/simonw/datasette/pull/2118

  It became clear that the `render` callback function documented here: https://docs.datasette.io/en/0.64.3/plugin_hooks.html#register-output-renderer-datasette

  Needs to grow the ability to be told if an error occurred (an `error` string) and if the results were truncated (a `truncated` boolean).

reactions:
  {"url": "https://api.github.com/repos/simonw/datasette/issues/2130/reactions", "total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0}


node_id: I_kwDOBm6k_c5tsoxv
title: Refactor code that supports templates_considered comment
state: open
created_at: 2023-08-08T01:28:36Z
updated_at: 2023-08-09T15:27:41Z
author_association: OWNER
type: issue
body:
  I ended up duplicating it here: https://github.com/simonw/datasette/blob/7532feb424b1dce614351e21b2265c04f9669fe2/datasette/views/database.py#L164-L167

  I think it should move to `datasette.render_template()` - and maybe have a renamed template variable too.

reactions:
  {"url": "https://api.github.com/repos/simonw/datasette/issues/2131/reactions", "total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0}


node_id: I_kwDOBm6k_c5twKrF
title: Get form fields on query page working again
state: closed
created_at: 2023-08-08T13:39:05Z
updated_at: 2023-08-08T13:45:10Z
closed_at: 2023-08-08T13:45:09Z
author_association: OWNER
type: issue
state_reason: completed
body:
  Caused by:
  - #2112

  https://latest.datasette.io/fixtures?sql=select+pk1%2C+pk2%2C+pk3%2C+content+from+compound_three_primary_keys+where+%22pk1%22+%3D+%3Ap0+order+by+pk1%2C+pk2%2C+pk3+limit+101&p0=b

  <img width="1100" alt="image" src="https://github.com/simonw/datasette/assets/9599/7ca20120-923b-4b7d-988d-cdb0e7c30afb">

  The `:p0` form field is missing. Submitting the form results in this error:

  <img width="687" alt="image" src="https://github.com/simonw/datasette/assets/9599/f900ee16-71fd-42aa-86d7-0058af8457aa">

reactions:
  {"url": "https://api.github.com/repos/simonw/datasette/issues/2132/reactions", "total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0}


node_id: I_kwDOBm6k_c5twxcX
title: [feature request]`datasette install plugins.json` options
state: closed
created_at: 2023-08-08T15:06:50Z
updated_at: 2023-08-10T00:31:24Z
closed_at: 2023-08-09T22:04:46Z
author_association: NONE
type: issue
state_reason: completed
body:
  Hi, simon ❤️ 

  `datasette plugins  --all > plugins.json` could generate all plugins info. On another machine, it would be great to install all plugins just by `datasette install plugins.json`

reactions:
  {"url": "https://api.github.com/repos/simonw/datasette/issues/2133/reactions", "total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0}


node_id: I_kwDOBm6k_c5t3-xh
title: Add writable canned query demo to latest.datasette.io
state: closed
created_at: 2023-08-09T14:31:30Z
updated_at: 2023-08-10T01:22:46Z
closed_at: 2023-08-10T01:05:56Z
author_association: OWNER
body:
  This would be useful while working on:
  - #2114

type: issue
state_reason: completed
reactions:
  {"url": "https://api.github.com/repos/simonw/datasette/issues/2134/reactions", "total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0}


node_id: I_kwDOBm6k_c5t4xrX
title: Release notes for 1.0a3
state: closed
created_at: 2023-08-09T16:09:26Z
updated_at: 2023-08-09T19:17:07Z
closed_at: 2023-08-09T19:17:06Z
author_association: OWNER
type: issue
state_reason: completed
body:
  118 commits! https://github.com/simonw/datasette/compare/1.0a2...26be9f0445b753fb84c802c356b0791a72269f25

reactions:
  {"url": "https://api.github.com/repos/simonw/datasette/issues/2135/reactions", "total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0}


node_id: I_kwDOBm6k_c5t5Mja
title: Query view shouldn't return `columns`
state: closed
created_at: 2023-08-09T17:23:57Z
updated_at: 2023-08-09T19:03:04Z
closed_at: 2023-08-09T19:03:04Z
author_association: OWNER
type: issue
state_reason: completed
body:
  I just noticed that https://latest.datasette.io/fixtures/roadside_attraction_characteristics.json?_labels=on&_size=1 returns:
  ```json
  {
    "ok": true,
    "next": "1",
    "rows": [
      {
        "rowid": 1,
        "attraction_id": {
          "value": 1,
          "label": "The Mystery Spot"
        },
        "characteristic_id": {
          "value": 2,
          "label": "Paranormal"
        }
      }
    ],
    "truncated": false
  }
  ```
  But https://latest.datasette.io/fixtures.json?sql=select+rowid%2C+attraction_id%2C+characteristic_id+from+roadside_attraction_characteristics+order+by+rowid+limit+1 returns:
  ```json
  {
    "rows": [
      {
        "rowid": 1,
        "attraction_id": 1,
        "characteristic_id": 2
      }
    ],
    "columns": [
      "rowid",
      "attraction_id",
      "characteristic_id"
    ],
    "ok": true,
    "truncated": false
  }
  ```
  The `columns` key in the query response is inconsistent with the table response.

reactions:
  {"url": "https://api.github.com/repos/simonw/datasette/issues/2136/reactions", "total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0}


node_id: I_kwDOBm6k_c5t5n2C
title: Redesign row default JSON
state: open
created_at: 2023-08-09T18:49:11Z
updated_at: 2023-08-09T19:02:47Z
author_association: OWNER
type: issue
body:
  This URL here:

  https://latest.datasette.io/fixtures/simple_primary_key/1.json?_extras=foreign_key_tables

  ```json
  {
    "database": "fixtures",
    "table": "simple_primary_key",
    "rows": [
      {
        "id": "1",
        "content": "hello"
      }
    ],
    "columns": [
      "id",
      "content"
    ],
    "primary_keys": [
      "id"
    ],
    "primary_key_values": [
      "1"
    ],
    "units": {},
    "foreign_key_tables": [
      {
        "other_table": "foreign_key_references",
        "column": "id",
        "other_column": "foreign_key_with_blank_label",
        "count": 0,
        "link": "/fixtures/foreign_key_references?foreign_key_with_blank_label=1"
      },
      {
        "other_table": "foreign_key_references",
        "column": "id",
        "other_column": "foreign_key_with_label",
        "count": 1,
        "link": "/fixtures/foreign_key_references?foreign_key_with_label=1"
      },
      {
        "other_table": "complex_foreign_keys",
        "column": "id",
        "other_column": "f3",
        "count": 1,
        "link": "/fixtures/complex_foreign_keys?f3=1"
      },
      {
        "other_table": "complex_foreign_keys",
        "column": "id",
        "other_column": "f2",
        "count": 0,
        "link": "/fixtures/complex_foreign_keys?f2=1"
      },
      {
        "other_table": "complex_foreign_keys",
        "column": "id",
        "other_column": "f1",
        "count": 1,
        "link": "/fixtures/complex_foreign_keys?f1=1"
      }
    ],
    "query_ms": 4.226590999678592,
    "source": "tests/fixtures.py",
    "source_url": "https://github.com/simonw/datasette/blob/main/tests/fixtures.py",
    "license": "Apache License 2.0",
    "license_url": "https://github.com/simonw/datasette/blob/main/LICENSE",
    "ok": true,
    "truncated": false
  }
  ```

  That `?_extras=` should be `?_extra=` - plus the row JSON should be redesigned to fit the new default JSON representation.

reactions:
  {"url": "https://api.github.com/repos/simonw/datasette/issues/2137/reactions", "total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0}


node_id: I_kwDOBm6k_c5t7HV7
title: on_success_message_sql option for writable canned queries
state: closed
created_at: 2023-08-10T00:20:14Z
updated_at: 2023-08-10T00:39:40Z
closed_at: 2023-08-10T00:34:26Z
author_association: OWNER
type: issue
state_reason: completed
body:
  > Or... how about if the `on_success_message` option could define a SQL query to be executed to generate that message? Maybe `on_success_message_sql`.

  - https://github.com/simonw/datasette/issues/2134

reactions:
  {"url": "https://api.github.com/repos/simonw/datasette/issues/2138/reactions", "total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0}


node_id: I_kwDOBm6k_c5uCONl
title: border-color: ##ff0000 bug - two hashes
state: closed
created_at: 2023-08-11T01:22:58Z
updated_at: 2023-08-11T05:16:24Z
closed_at: 2023-08-11T05:16:24Z
author_association: OWNER
type: issue
state_reason: completed
body:
  Spotted this on https://latest.datasette.io/extra_database

  ```html
  <div class="page-header" style="border-color: ##ff0000">
  ```

reactions:
  {"url": "https://api.github.com/repos/simonw/datasette/issues/2139/reactions", "total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0}


node_id: I_kwDOBm6k_c5uGg3v
title: Remove all remaining documentation instances of '$ '
state: closed
created_at: 2023-08-11T17:42:13Z
updated_at: 2023-08-11T17:52:25Z
closed_at: 2023-08-11T17:45:00Z
author_association: OWNER
type: issue
state_reason: completed
body:
  For example this: https://github.com/simonw/datasette/blob/4535568f2ce907af646304d0ebce2500ebd55677/docs/authentication.rst?plain=1#L33-L35

  The problem with that `$ ` prefix is that it prevents users from copying and pasting the raw command.

  <img width="773" alt="image" src="https://github.com/simonw/datasette/assets/9599/9414437d-1eb9-416b-ae51-0f4f5d665b80">

  https://docs.datasette.io/en/stable/authentication.html#using-the-root-actor

reactions:
  {"url": "https://api.github.com/repos/simonw/datasette/issues/2140/reactions", "total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0}


node_id: PR_kwDOBm6k_c5YEUBK
title: Bump the python-packages group with 1 update
state: closed
created_at: 2023-08-16T13:47:35Z
updated_at: 2023-08-17T13:07:48Z
closed_at: 2023-08-17T13:07:45Z
author_association: CONTRIBUTOR
pull_request: simonw/datasette/pulls/2141
type: pull
body:
  Bumps the python-packages group with 1 update: [blacken-docs](https://github.com/asottile/blacken-docs).

  <details>
  <summary>Changelog</summary>
  <p><em>Sourced from <a href="https://github.com/adamchainz/blacken-docs/blob/main/CHANGELOG.rst">blacken-docs's changelog</a>.</em></p>
  <blockquote>
  <h2>1.16.0 (2023-08-16)</h2>
  <ul>
  <li>
  <p>Allow Markdown fence options.</p>
  <p>Thanks to initial work from Matthew Anderson in <code>PR [#246](https://github.com/asottile/blacken-docs/issues/246) &lt;https://github.com/adamchainz/blacken-docs/pull/246&gt;</code>__.</p>
  </li>
  <li>
  <p>Expand Markdown detection to all Python language names from Pygments: <code>py</code>, <code>sage</code>, <code>python3</code>, <code>py3</code>, and <code>numpy</code>.</p>
  </li>
  <li>
  <p>Preserve leading whitespace lines in reStructuredText code blocks.</p>
  <p>Thanks to Julianus Pfeuffer for the report in <code>Issue [#217](https://github.com/asottile/blacken-docs/issues/217) &lt;https://github.com/adamchainz/blacken-docs/issues/217&gt;</code>__.</p>
  </li>
  <li>
  <p>Use exit code 2 to indicate errors from Black, whilst exit code 1 remains for “files have been formatted”.</p>
  <p>Thanks to Julianus Pfeuffer for the report in <code>Issue [#218](https://github.com/asottile/blacken-docs/issues/218) &lt;https://github.com/adamchainz/blacken-docs/issues/218&gt;</code>__.</p>
  </li>
  <li>
  <p>Support passing the <code>--preview</code> option through to Black, to select the future style.</p>
  </li>
  <li>
  <p>Remove <code>language_version</code> from <code>.pre-commit-hooks.yaml</code>.
  This change allows <code>default_language_version</code> in ``.pre-commit-config.yaml` to take precedence.</p>
  <p>Thanks to Aneesh Agrawal in <code>PR [#258](https://github.com/asottile/blacken-docs/issues/258) &lt;https://github.com/adamchainz/blacken-docs/pull/258&gt;</code>__.</p>
  </li>
  </ul>
  </blockquote>
  </details>
  <details>
  <summary>Commits</summary>
  <ul>
  <li><a href="https://github.com/adamchainz/blacken-docs/commit/960ead214cd1184149d366c6d27ca6c369ce46b6"><code>960ead2</code></a> Version 1.16.0</li>
  <li><a href="https://github.com/adamchainz/blacken-docs/commit/8f0ed18ce69d35e7e631d2b01983ecf8248667a0"><code>8f0ed18</code></a> Support passing --preview through to Black (<a href="https://redirect.github.com/asottile/blacken-docs/issues/273">#273</a>)</li>
  <li><a href="https://github.com/adamchainz/blacken-docs/commit/4eb4e4cdbff31cde3d9ffdd7693d5b7dce4dc506"><code>4eb4e4c</code></a> Tweak changelog note</li>
  <li><a href="https://github.com/adamchainz/blacken-docs/commit/6c7450cfa90581b482d71b451b2d007361aa47c1"><code>6c7450c</code></a> Use exit code 2 to indicate errors (<a href="https://redirect.github.com/asottile/blacken-docs/issues/272">#272</a>)</li>
  <li><a href="https://github.com/adamchainz/blacken-docs/commit/99dfc8d0b402b9b7b0f0e723fc1d030063249eac"><code>99dfc8d</code></a> Preserve leading whitespace lines in rST (<a href="https://redirect.github.com/asottile/blacken-docs/issues/271">#271</a>)</li>
  <li><a href="https://github.com/adamchainz/blacken-docs/commit/94465e83e7253b4caef1e00fcb30b74ced33f08e"><code>94465e8</code></a> Reformat markdown tests with dedent() (<a href="https://redirect.github.com/asottile/blacken-docs/issues/270">#270</a>)</li>
  <li><a href="https://github.com/adamchainz/blacken-docs/commit/7cd5f30f0f9e014bda566a1893df3b9c7f9a2c48"><code>7cd5f30</code></a> Use .md in glob example</li>
  <li><a href="https://github.com/adamchainz/blacken-docs/commit/f97e56994178e079ab807cebe54c2044f7b2ae55"><code>f97e569</code></a> Document applying to many files (<a href="https://redirect.github.com/asottile/blacken-docs/issues/269">#269</a>)</li>
  <li><a href="https://github.com/adamchainz/blacken-docs/commit/ae612b095b5005eee8c3ab9fe65a248d7654582d"><code>ae612b0</code></a> Expand Markdown detection to all Python language names (<a href="https://redirect.github.com/asottile/blacken-docs/issues/268">#268</a>)</li>
  <li><a href="https://github.com/adamchainz/blacken-docs/commit/da9b4557afc9b820c40b8d6bdb8f515c6cdec0f5"><code>da9b455</code></a> Replace NamedTuple with plain class (<a href="https://redirect.github.com/asottile/blacken-docs/issues/267">#267</a>)</li>
  <li>Additional commits viewable in <a href="https://github.com/asottile/blacken-docs/compare/1.15.0...1.16.0">compare view</a></li>
  </ul>
  </details>
  <br />


  [![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=blacken-docs&package-manager=pip&previous-version=1.15.0&new-version=1.16.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

  Dependabot 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`.

  [//]: # (dependabot-automerge-start)
  [//]: # (dependabot-automerge-end)

  ---

  <details>
  <summary>Dependabot commands and options</summary>
  <br />

  You can trigger Dependabot actions by commenting on this PR:
  - `@dependabot rebase` will rebase this PR
  - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
  - `@dependabot merge` will merge this PR after your CI passes on it
  - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it
  - `@dependabot cancel merge` will cancel a previously requested merge and block automerging
  - `@dependabot reopen` will reopen this PR if it is closed
  - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
  - `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency
  - `@dependabot ignore <dependency name> major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself)
  - `@dependabot ignore <dependency name> minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself)
  - `@dependabot ignore <dependency name> dependency` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself)
  - `@dependabot unignore <dependency name> dependency` will remove all of the ignore conditions of the specified dependency
  - `@dependabot unignore <dependency name> <ignore condition>` will remove the ignore condition of the specified dependency and ignore conditions


  </details>

  <!-- readthedocs-preview datasette start -->
  ----
  :books: Documentation preview :books:: https://datasette--2141.org.readthedocs.build/en/2141/

  <!-- readthedocs-preview datasette end -->

reactions:
  {"url": "https://api.github.com/repos/simonw/datasette/issues/2141/reactions", "total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0}


node_id: PR_kwDOBm6k_c5YKAZ4
title: Bump the python-packages group with 2 updates
state: closed
created_at: 2023-08-17T13:07:53Z
updated_at: 2023-08-18T13:49:29Z
closed_at: 2023-08-18T13:49:26Z
author_association: CONTRIBUTOR
pull_request: simonw/datasette/pulls/2142
type: pull
body:
  Bumps the python-packages group with 2 updates: [sphinx](https://github.com/sphinx-doc/sphinx) and [blacken-docs](https://github.com/asottile/blacken-docs).

  Updates `sphinx` from 7.1.2 to 7.2.0
  <details>
  <summary>Release notes</summary>
  <p><em>Sourced from <a href="https://github.com/sphinx-doc/sphinx/releases">sphinx's releases</a>.</em></p>
  <blockquote>
  <h2>Sphinx 7.2.0</h2>
  <p>Changelog: <a href="https://www.sphinx-doc.org/en/master/changes.html">https://www.sphinx-doc.org/en/master/changes.html</a></p>
  </blockquote>
  </details>
  <details>
  <summary>Changelog</summary>
  <p><em>Sourced from <a href="https://github.com/sphinx-doc/sphinx/blob/master/CHANGES">sphinx's changelog</a>.</em></p>
  <blockquote>
  <h1>Release 7.2.0 (released Aug 17, 2023)</h1>
  <h2>Dependencies</h2>
  <ul>
  <li><a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11511">#11511</a>: Drop Python 3.8 support.</li>
  <li><a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11576">#11576</a>: Require Pygments 2.14 or later.</li>
  </ul>
  <h2>Deprecated</h2>
  <ul>
  <li><a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11512">#11512</a>: Deprecate <code>sphinx.util.md5</code> and <code>sphinx.util.sha1</code>.
  Use <code>hashlib</code> instead.</li>
  <li><a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11526">#11526</a>: Deprecate <code>sphinx.testing.path</code>.
  Use <code>os.path</code> or <code>pathlib</code> instead.</li>
  <li><a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11528">#11528</a>: Deprecate <code>sphinx.util.split_index_msg</code> and <code>sphinx.util.split_into</code>.
  Use <code>sphinx.util.index_entries.split_index_msg</code> instead.</li>
  <li>Deprecate <code>sphinx.builders.html.Stylesheet</code>
  and <code>sphinx.builders.html.Javascript</code>.
  Use <code>sphinx.application.Sphinx.add_css_file()</code>
  and <code>sphinx.application.Sphinx.add_js_file()</code> instead.</li>
  <li><a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11582">#11582</a>: Deprecate <code>sphinx.builders.html.StandaloneHTMLBuilder.css_files</code> and
  <code>sphinx.builders.html.StandaloneHTMLBuilder.script_files</code>.
  Use <code>sphinx.application.Sphinx.add_css_file()</code>
  and <code>sphinx.application.Sphinx.add_js_file()</code> instead.</li>
  <li><a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11459">#11459</a>: Deprecate <code>sphinx.ext.autodoc.preserve_defaults.get_function_def()</code>.
  Patch by Bénédikt Tran.</li>
  </ul>
  <h2>Features added</h2>
  <ul>
  <li><a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11526">#11526</a>: Support <code>os.PathLike</code> types and <code>pathlib.Path</code> objects
  in many more places.</li>
  <li><a href="https://redirect.github.com/sphinx-doc/sphinx/issues/5474">#5474</a>: coverage: Print summary statistics tables.
  Patch by Jorge Leitao.</li>
  <li><a href="https://redirect.github.com/sphinx-doc/sphinx/issues/6319">#6319</a>: viewcode: Add :confval:<code>viewcode_line_numbers</code> to control
  whether line numbers are added to rendered source code.
  Patch by Ben Krikler.</li>
  <li><a href="https://redirect.github.com/sphinx-doc/sphinx/issues/9662">#9662</a>: Add the <code>:no-typesetting:</code> option to suppress textual output
  and only create a linkable anchor.
  Patch by Latosha Maltba.</li>
  <li><a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11221">#11221</a>: C++: Support domain objects in the table of contents.
  Patch by Rouslan Korneychuk.</li>
  <li><a href="https://redirect.github.com/sphinx-doc/sphinx/issues/10938">#10938</a>: doctest: Add :confval:<code>doctest_show_successes</code> option.
  Patch by Trey Hunner.</li>
  <li><a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11533">#11533</a>: Add <code>:no-index:</code>, <code>:no-index-entry:</code>, and <code>:no-contents-entry:</code>.</li>
  <li><a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11572">#11572</a>: Improve <code>debug</code> logging of reasons why files are detected as out of
  date.
  Patch by Eric Larson.</li>
  </ul>
  <!-- raw HTML omitted -->
  </blockquote>
  <p>... (truncated)</p>
  </details>
  <details>
  <summary>Commits</summary>
  <ul>
  <li><a href="https://github.com/sphinx-doc/sphinx/commit/da9f8a5c33ad5eeef05dd780f2988f3ff7351ef3"><code>da9f8a5</code></a> Bump to 7.2.0 final</li>
  <li><a href="https://github.com/sphinx-doc/sphinx/commit/794324ac000095aa6409a4958b44a17dc25d3b49"><code>794324a</code></a> Declare support for Python 3.13</li>
  <li><a href="https://github.com/sphinx-doc/sphinx/commit/03bceac43ff1e69a33fe973612504738182cf217"><code>03bceac</code></a> [bot]: Update message catalogues (<a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11538">#11538</a>)</li>
  <li><a href="https://github.com/sphinx-doc/sphinx/commit/aecebcea9a3f6cbd3f379bc34f99d2ffb0f87220"><code>aecebce</code></a> Make <code>_resolve_toctree()</code> keyword-only</li>
  <li><a href="https://github.com/sphinx-doc/sphinx/commit/76658c49a931745da45fa4d5c8d482b7c6facd4f"><code>76658c4</code></a> Fix <code>sphinx.ext.autodoc.preserve_defaults</code> (<a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11550">#11550</a>)</li>
  <li><a href="https://github.com/sphinx-doc/sphinx/commit/4dee1629901f5e5c2aefc274da42483e16770e50"><code>4dee162</code></a> Fix layout issues in the agogo theme for smaller viewports (<a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11594">#11594</a>)</li>
  <li><a href="https://github.com/sphinx-doc/sphinx/commit/4ddbee4a7cdf14a7d064ffaea6cbb0c4fdb63f23"><code>4ddbee4</code></a> Fix <code>console_scripts</code> entry points</li>
  <li><a href="https://github.com/sphinx-doc/sphinx/commit/4add50a5f0c3ff7954edcec3d33dd1c0fa40a1a6"><code>4add50a</code></a> Remove unneeded type annotation</li>
  <li><a href="https://github.com/sphinx-doc/sphinx/commit/9d8ef833dbf9d7bb04771e622d6ceea738ac9d18"><code>9d8ef83</code></a> Fix <code>test_inspect_main_noargs</code></li>
  <li><a href="https://github.com/sphinx-doc/sphinx/commit/ddf8a8e7d4756170d5ee6dff7fc88ecd12912e59"><code>ddf8a8e</code></a> Add CHANGES entry for <a href="https://redirect.github.com/sphinx-doc/sphinx/issues/11533">GH-11533</a></li>
  <li>Additional commits viewable in <a href="https://github.com/sphinx-doc/sphinx/compare/v7.1.2...v7.2.0">compare view</a></li>
  </ul>
  </details>
  <br />

  Updates `blacken-docs` from 1.15.0 to 1.16.0
  <details>
  <summary>Changelog</summary>
  <p><em>Sourced from <a href="https://github.com/adamchainz/blacken-docs/blob/main/CHANGELOG.rst">blacken-docs's changelog</a>.</em></p>
  <blockquote>
  <h2>1.16.0 (2023-08-16)</h2>
  <ul>
  <li>
  <p>Allow Markdown fence options.</p>
  <p>Thanks to initial work from Matthew Anderson in <code>PR [#246](https://github.com/asottile/blacken-docs/issues/246) &lt;https://github.com/adamchainz/blacken-docs/pull/246&gt;</code>__.</p>
  </li>
  <li>
  <p>Expand Markdown detection to all Python language names from Pygments: <code>py</code>, <code>sage</code>, <code>python3</code>, <code>py3</code>, and <code>numpy</code>.</p>
  </li>
  <li>
  <p>Preserve leading whitespace lines in reStructuredText code blocks.</p>
  <p>Thanks to Julianus Pfeuffer for the report in <code>Issue [#217](https://github.com/asottile/blacken-docs/issues/217) &lt;https://github.com/adamchainz/blacken-docs/issues/217&gt;</code>__.</p>
  </li>
  <li>
  <p>Use exit code 2 to indicate errors from Black, whilst exit code 1 remains for “files have been formatted”.</p>
  <p>Thanks to Julianus Pfeuffer for the report in <code>Issue [#218](https://github.com/asottile/blacken-docs/issues/218) &lt;https://github.com/adamchainz/blacken-docs/issues/218&gt;</code>__.</p>
  </li>
  <li>
  <p>Support passing the <code>--preview</code> option through to Black, to select the future style.</p>
  </li>
  <li>
  <p>Remove <code>language_version</code> from <code>.pre-commit-hooks.yaml</code>.
  This change allows <code>default_language_version</code> in ``.pre-commit-config.yaml` to take precedence.</p>
  <p>Thanks to Aneesh Agrawal in <code>PR [#258](https://github.com/asottile/blacken-docs/issues/258) &lt;https://github.com/adamchainz/blacken-docs/pull/258&gt;</code>__.</p>
  </li>
  </ul>
  </blockquote>
  </details>
  <details>
  <summary>Commits</summary>
  <ul>
  <li><a href="https://github.com/adamchainz/blacken-docs/commit/960ead214cd1184149d366c6d27ca6c369ce46b6"><code>960ead2</code></a> Version 1.16.0</li>
  <li><a href="https://github.com/adamchainz/blacken-docs/commit/8f0ed18ce69d35e7e631d2b01983ecf8248667a0"><code>8f0ed18</code></a> Support passing --preview through to Black (<a href="https://redirect.github.com/asottile/blacken-docs/issues/273">#273</a>)</li>
  <li><a href="https://github.com/adamchainz/blacken-docs/commit/4eb4e4cdbff31cde3d9ffdd7693d5b7dce4dc506"><code>4eb4e4c</code></a> Tweak changelog note</li>
  <li><a href="https://github.com/adamchainz/blacken-docs/commit/6c7450cfa90581b482d71b451b2d007361aa47c1"><code>6c7450c</code></a> Use exit code 2 to indicate errors (<a href="https://redirect.github.com/asottile/blacken-docs/issues/272">#272</a>)</li>
  <li><a href="https://github.com/adamchainz/blacken-docs/commit/99dfc8d0b402b9b7b0f0e723fc1d030063249eac"><code>99dfc8d</code></a> Preserve leading whitespace lines in rST (<a href="https://redirect.github.com/asottile/blacken-docs/issues/271">#271</a>)</li>
  <li><a href="https://github.com/adamchainz/blacken-docs/commit/94465e83e7253b4caef1e00fcb30b74ced33f08e"><code>94465e8</code></a> Reformat markdown tests with dedent() (<a href="https://redirect.github.com/asottile/blacken-docs/issues/270">#270</a>)</li>
  <li><a href="https://github.com/adamchainz/blacken-docs/commit/7cd5f30f0f9e014bda566a1893df3b9c7f9a2c48"><code>7cd5f30</code></a> Use .md in glob example</li>
  <li><a href="https://github.com/adamchainz/blacken-docs/commit/f97e56994178e079ab807cebe54c2044f7b2ae55"><code>f97e569</code></a> Document applying to many files (<a href="https://redirect.github.com/asottile/blacken-docs/issues/269">#269</a>)</li>
  <li><a href="https://github.com/adamchainz/blacken-docs/commit/ae612b095b5005eee8c3ab9fe65a248d7654582d"><code>ae612b0</code></a> Expand Markdown detection to all Python language names (<a href="https://redirect.github.com/asottile/blacken-docs/issues/268">#268</a>)</li>
  <li><a href="https://github.com/adamchainz/blacken-docs/commit/da9b4557afc9b820c40b8d6bdb8f515c6cdec0f5"><code>da9b455</code></a> Replace NamedTuple with plain class (<a href="https://redirect.github.com/asottile/blacken-docs/issues/267">#267</a>)</li>
  <li>Additional commits viewable in <a href="https://github.com/asottile/blacken-docs/compare/1.15.0...1.16.0">compare view</a></li>
  </ul>
  </details>
  <br />


  Dependabot 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`.

  [//]: # (dependabot-automerge-start)
  [//]: # (dependabot-automerge-end)

  ---

  <details>
  <summary>Dependabot commands and options</summary>
  <br />

  You can trigger Dependabot actions by commenting on this PR:
  - `@dependabot rebase` will rebase this PR
  - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
  - `@dependabot merge` will merge this PR after your CI passes on it
  - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it
  - `@dependabot cancel merge` will cancel a previously requested merge and block automerging
  - `@dependabot reopen` will reopen this PR if it is closed
  - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
  - `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency
  - `@dependabot ignore <dependency name> major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself)
  - `@dependabot ignore <dependency name> minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself)
  - `@dependabot ignore <dependency name> dependency` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself)
  - `@dependabot unignore <dependency name> dependency` will remove all of the ignore conditions of the specified dependency
  - `@dependabot unignore <dependency name> <ignore condition>` will remove the ignore condition of the specified dependency and ignore conditions


  </details>

  <!-- readthedocs-preview datasette start -->
  ----
  :books: Documentation preview :books:: https://datasette--2142.org.readthedocs.build/en/2142/

  <!-- readthedocs-preview datasette end -->

reactions:
  {"url": "https://api.github.com/repos/simonw/datasette/issues/2142/reactions", "total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0}


