issue_comments
9,947 rows sorted by id descending
This data as json, CSV (advanced)
id ▲ | html_url | issue_url | node_id | user | created_at | updated_at | author_association | body | reactions | issue | performed_via_github_app |
---|---|---|---|---|---|---|---|---|---|---|---|
1537277919 | https://github.com/simonw/datasette/issues/2069#issuecomment-1537277919 | https://api.github.com/repos/simonw/datasette/issues/2069 | IC_kwDOBm6k_c5boP_f | yqlbu 31861128 | 2023-05-07T03:17:35Z | 2023-05-07T03:17:35Z | NONE | Some updates: I notice that there is an option in the CLI where we can explicitly set `immutable` mode when spinning up the server ```console Options: -i, --immutable PATH Database files to open in immutable mode ``` Then, the question is - how can I disable immutable mode in the deployed instance on Vercel? | {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} | [BUG] Cannot insert new data to deployed instance 1698865182 | |
1532481862 | https://github.com/simonw/sqlite-utils/issues/496#issuecomment-1532481862 | https://api.github.com/repos/simonw/sqlite-utils/issues/496 | IC_kwDOCGYnMM5bV9FG | xavdid 1231935 | 2023-05-03T05:53:26Z | 2023-05-03T05:53:26Z | NONE | Would love to put our heads together for improvements here. I _think_ anything that is `argname=DEFAULT` needs to be typed as `argname: str | Default = DEFAULT` (replacing `str` with the appropriate type(s)). We may be able to get clever and tie the types to that key in the `_defaults` dict (definitely possible in Typescript, but I'm less familiar with advanced python types). Right now, all args are typed as `Default`, which means all callers get type errors. As for table/view, given that they don't have the same methods, it would be nice to be able to get one or the other specifically. | {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} | devrel/python api: Pylance type hinting 1393202060 | |
1532304714 | https://github.com/simonw/datasette/issues/2067#issuecomment-1532304714 | https://api.github.com/repos/simonw/datasette/issues/2067 | IC_kwDOBm6k_c5bVR1K | justmars 39538958 | 2023-05-03T00:16:03Z | 2023-05-03T00:16:03Z | NONE | Curiously, after running commands on the database that was litestream-restored, datasette starts to work again, e.g. ```sh litestream restore -o data/db.sqlite s3://mytestbucketxx/db datasette data/db.sqlite # fails (OperationalError described above) ``` ```sh litestream restore -o data/db.sqlite s3://mytestbucketxx/db sqlite-utils enable-wal data/db.sqlite datasette data/db.sqlite # works ``` ```sh litestream restore -o data/db.sqlite s3://mytestbucketxx/db sqlite-utils optimize data/db.sqlite datasette data/db.sqlite # works ``` ```sh litestream restore -o data/db.sqlite s3://mytestbucketxx/db sqlite3 data/db.sqlite ".clone test.db" datasette test.db # works ``` | {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} | Litestream-restored db: errors on 3.11 and 3.10.8; but works on py3.10.7 and 3.10.6 1690765434 | |
1530822437 | https://github.com/simonw/datasette/pull/2052#issuecomment-1530822437 | https://api.github.com/repos/simonw/datasette/issues/2052 | IC_kwDOBm6k_c5bPn8l | cldellow 193185 | 2023-05-02T03:35:30Z | 2023-05-02T16:02:38Z | CONTRIBUTOR | Also, just checking - is this how I'd write bulletproof plugin registration code that is robust against the order in which the script tags load (eg if both my code and the Datasette code are loaded via a `<script async src='...'/>` tag)? ```js if (window.__DATASETTE__) go(window.__DATASETTE__); else document.addEventListener("datasette_init", (evt) => go(evt.detail)); function go(manager) { manager.registerPlugin(...) } ``` I don't know if it'd make sense, but you could also consider the asynchronous queuing pattern that Google Analytics uses (see [this Stack Overflow post](https://stackoverflow.com/questions/6963779/whats-the-name-of-google-analytics-async-design-pattern-and-where-is-it-used) for more details): ```js __DATASETTE__ = __DATASETTE__ || []; __DATASETTE__.push(go); function go(manager) { manager.registerPlugin(...); } ``` | {"total_count": 2, "+1": 1, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 1} | feat: Javascript Plugin API (Custom panels, column menu items with JS actions) 1651082214 | |
1530817667 | https://github.com/simonw/datasette/pull/2052#issuecomment-1530817667 | https://api.github.com/repos/simonw/datasette/issues/2052 | IC_kwDOBm6k_c5bPmyD | cldellow 193185 | 2023-05-02T03:24:53Z | 2023-05-02T03:24:53Z | CONTRIBUTOR | Thanks for putting this together! I've been slammed with work/personal stuff so haven't been able to actually prototype anything with this. :( tl;dr: I think this would be useful immediately as is. It might also be nice if the plugins could return `Promise`s. The long version: I read the design notes and example plugin. I think I'd be able to use this in [datasette-ui-extras](https://github.com/cldellow/datasette-ui-extras) for my lazy-facets feature. The lazy-facets feature tries to provide a snappier user experience. It does this by altering how suggested facets work. First, at page render time: (A) it lies to Datasette and claims that no columns support facets, this avoids the lengthy delays/timeouts that can happen if the dataset is large. (B) there's a python plugin that implements the [extra_body_script](https://docs.datasette.io/en/stable/plugin_hooks.html#extra-body-script-template-database-table-columns-view-name-request-datasette) hook, to write out the list of column names for future use by JavaScript Second, at page load time: there is some JavaScript that: (C) makes AJAX requests to suggest facets for each column - it makes 1 request per column, using the data from (B) (D) wires up the column menus to add Facet-by-this options for each facet With the currently proposed plugin scheme, I think (D) could be moved into the plugin. I'd do the ajax requests, then register the plugin. If the plugin scheme also supported promises, I think (B) and (C) could also be moved into the plugin. Does that make sense? Sorry for the wall of text! | {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} | feat: Javascript Plugin API (Custom panels, column menu items with JS actions) 1651082214 | |
1529737426 | https://github.com/simonw/datasette/pull/2064#issuecomment-1529737426 | https://api.github.com/repos/simonw/datasette/issues/2064 | IC_kwDOBm6k_c5bLfDS | dependabot[bot] 49699333 | 2023-05-01T13:58:50Z | 2023-05-01T13:58:50Z | CONTRIBUTOR | Superseded by #2068. | {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} | Bump sphinx from 6.1.3 to 6.2.1 1683229834 | |
1524709988 | https://github.com/simonw/datasette/issues/2065#issuecomment-1524709988 | https://api.github.com/repos/simonw/datasette/issues/2065 | IC_kwDOBm6k_c5a4Tpk | simonw 9599 | 2023-04-27T05:09:36Z | 2023-04-27T05:09:36Z | OWNER | That fixed it - after installing `main.zip` again I ran this and it worked: ~/.rye/tools/main-zip/bin/datasette install datasette-graphql ``` % ~/.rye/tools/main-zip/bin/datasette plugins [ { "name": "datasette-graphql", "static": true, "templates": true, "version": "2.2", "hooks": [ "database_actions", "extra_template_vars", "menu_links", "register_routes", "startup", "table_actions" ] } ] ``` | {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} | Datasette cannot be installed with Rye 1686033652 | |
1524707628 | https://github.com/simonw/datasette/issues/2065#issuecomment-1524707628 | https://api.github.com/repos/simonw/datasette/issues/2065 | IC_kwDOBm6k_c5a4TEs | simonw 9599 | 2023-04-27T05:06:44Z | 2023-04-27T05:06:44Z | OWNER | I need `pip` as a dependency too: ``` % ~/.rye/tools/main-zip/bin/datasette install datasette-graphql Traceback (most recent call last): File "/Users/simon/.rye/tools/main-zip/bin/datasette", line 8, in <module> sys.exit(cli()) ^^^^^ File "/Users/simon/.rye/tools/main-zip/lib/python3.11/site-packages/click/core.py", line 1130, in __call__ return self.main(*args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/Users/simon/.rye/tools/main-zip/lib/python3.11/site-packages/click/core.py", line 1055, in main rv = self.invoke(ctx) ^^^^^^^^^^^^^^^^ File "/Users/simon/.rye/tools/main-zip/lib/python3.11/site-packages/click/core.py", line 1657, in invoke return _process_result(sub_ctx.command.invoke(sub_ctx)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/Users/simon/.rye/tools/main-zip/lib/python3.11/site-packages/click/core.py", line 1404, in invoke return ctx.invoke(self.callback, **ctx.params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/Users/simon/.rye/tools/main-zip/lib/python3.11/site-packages/click/core.py", line 760, in invoke return __callback(*args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/Users/simon/.rye/tools/main-zip/lib/python3.11/site-packages/datasette/cli.py", line 365, in install run_module("pip", run_name="__main__") File "<frozen runpy>", line 222, in run_module File "<frozen runpy>", line 142, in _get_module_details ImportError: No module named pip ``` | {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} | Datasette cannot be installed with Rye 1686033652 | |
1524699863 | https://github.com/simonw/datasette/issues/2065#issuecomment-1524699863 | https://api.github.com/repos/simonw/datasette/issues/2065 | IC_kwDOBm6k_c5a4RLX | simonw 9599 | 2023-04-27T04:56:22Z | 2023-04-27T04:56:22Z | OWNER | Turned this into a TIL: https://til.simonwillison.net/python/rye | {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} | Datasette cannot be installed with Rye 1686033652 | |
1524680160 | https://github.com/simonw/datasette/issues/2066#issuecomment-1524680160 | https://api.github.com/repos/simonw/datasette/issues/2066 | IC_kwDOBm6k_c5a4MXg | simonw 9599 | 2023-04-27T04:27:50Z | 2023-04-27T04:27:50Z | OWNER | That fixed it. | {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} | Failing test: httpx.InvalidURL: URL too long 1686042269 | |
1524675817 | https://github.com/simonw/datasette/issues/2066#issuecomment-1524675817 | https://api.github.com/repos/simonw/datasette/issues/2066 | IC_kwDOBm6k_c5a4LTp | simonw 9599 | 2023-04-27T04:21:03Z | 2023-04-27T04:21:03Z | OWNER | I went with this to generate the long string: https://github.com/simonw/datasette/blob/0b0c5cd7a94fe3f151a3e10261b5c84ee64f2f18/tests/test_csv.py#L157-L176 | {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} | Failing test: httpx.InvalidURL: URL too long 1686042269 | |
1524669124 | https://github.com/simonw/datasette/issues/2066#issuecomment-1524669124 | https://api.github.com/repos/simonw/datasette/issues/2066 | IC_kwDOBm6k_c5a4JrE | simonw 9599 | 2023-04-27T04:10:44Z | 2023-04-27T04:10:52Z | OWNER | I need an alternative way of generating a long string with a shorter URL. ```sql select group_concat('abcabcabc', '') from json_each(json_array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)) ``` https://latest.datasette.io/_memory?sql=select+group_concat%28%27abcabcabc%27%2C+%27%27%29+from+json_each%28json_array%281%2C+2%2C+3%2C+4%2C+5%2C+6%2C+7%2C+8%2C+9%2C+10%29%29 | {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} | Failing test: httpx.InvalidURL: URL too long 1686042269 | |
1524666049 | https://github.com/simonw/datasette/issues/2066#issuecomment-1524666049 | https://api.github.com/repos/simonw/datasette/issues/2066 | IC_kwDOBm6k_c5a4I7B | simonw 9599 | 2023-04-27T04:06:18Z | 2023-04-27T04:06:18Z | OWNER | Most recent `httpx` release is 0.24 a couple of weeks ago. Here's what changed in that version: https://github.com/encode/httpx/compare/0.23.3...0.24.0 It looks like that URL limit is new: https://github.com/encode/httpx/commit/57daabf673705954afa94686c0002801c93d31f3#diff-78d8d93b5dd4c77d99c3e2b46b7286ba71a8fd60e92d8bd4eee5fb200b4f87bfR149-R155 ```python 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") ``` https://github.com/encode/httpx/blob/32e25497a36e6222cc64a758c98275b450dac28d/httpx/_urlparse.py#L153-L155 | {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} | Failing test: httpx.InvalidURL: URL too long 1686042269 | |
1524660603 | https://github.com/simonw/datasette/issues/2066#issuecomment-1524660603 | https://api.github.com/repos/simonw/datasette/issues/2066 | IC_kwDOBm6k_c5a4Hl7 | simonw 9599 | 2023-04-27T04:02:55Z | 2023-04-27T04:02:55Z | OWNER | In the debugger: ``` (Pdb) MAX_URL_LENGTH 65536 ``` Weird this only seems to be a problem with `httpx` on Python 3.7 though. | {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} | Failing test: httpx.InvalidURL: URL too long 1686042269 | |
1524659084 | https://github.com/simonw/datasette/issues/2066#issuecomment-1524659084 | https://api.github.com/repos/simonw/datasette/issues/2066 | IC_kwDOBm6k_c5a4HOM | simonw 9599 | 2023-04-27T04:02:07Z | 2023-04-27T04:02:07Z | OWNER | This is the failing test: https://github.com/simonw/datasette/blob/249fcf8e3e2a90e763f41b080c1b9ec8017f5005/tests/test_csv.py#L156-L167 | {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} | Failing test: httpx.InvalidURL: URL too long 1686042269 | |
1524655203 | https://github.com/simonw/datasette/issues/2066#issuecomment-1524655203 | https://api.github.com/repos/simonw/datasette/issues/2066 | IC_kwDOBm6k_c5a4GRj | simonw 9599 | 2023-04-27T03:59:56Z | 2023-04-27T03:59:56Z | OWNER | In a fresh Datasette checkout I ran: pipenv shell --python /Users/simon/.pyenv/versions/3.7.16/bin/python That gave me a virtual environment with 3.7.16 Python. Then I ran: pip install -e '.[test]' Weirdly that gave me a `which pytest` of `/opt/homebrew/bin/pytest` which ran the tests on 3.11. I figured out the location of the virtual environment with `which python` and then ran this: ``` % /Users/simon/.local/share/virtualenvs/datasette-cZYvnUqY/bin/pytest tests/test_csv.py ============================================================================================== test session starts =============================================================================================== platform darwin -- Python 3.7.16, pytest-7.3.1, pluggy-1.0.0 SQLite: 3.39.5 rootdir: /private/tmp/datasette configfile: pytest.ini plugins: asyncio-0.21.0, timeout-2.1.0, xdist-3.2.1, anyio-3.6.2 asyncio: mode=strict collected 15 items tests/test_csv.py ..........F.... [100%] ==================================================================================================== FAILURES ==================================================================================================== ________________________________________________________________________________________________ test_max_csv_mb _________________________________________________________________________________________________ app_client_csv_max_mb_one = <datasette.utils.testing.TestClient object at 0x107ab5c08> def test_max_csv_mb(app_client_csv_max_mb_one): response = app_client_csv_max_mb_one.get( ( "/fixtures.csv?sql=selec… | {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} | Failing test: httpx.InvalidURL: URL too long 1686042269 | |
1524648995 | https://github.com/simonw/datasette/issues/2066#issuecomment-1524648995 | https://api.github.com/repos/simonw/datasette/issues/2066 | IC_kwDOBm6k_c5a4Ewj | simonw 9599 | 2023-04-27T03:56:42Z | 2023-04-27T03:57:11Z | OWNER | I don't have 3.7 locally. Trying to install it with `pyenv`. brew install pyenv Then: pyenv install --list | grep 3.7 Installing: pyenv install 3.7.16 Output: Installed Python-3.7.16 to /Users/simon/.pyenv/versions/3.7.16 So the executable is `/Users/simon/.pyenv/versions/3.7.16/bin/python`. | {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} | Failing test: httpx.InvalidURL: URL too long 1686042269 | |
1524638233 | https://github.com/simonw/datasette/issues/2066#issuecomment-1524638233 | https://api.github.com/repos/simonw/datasette/issues/2066 | IC_kwDOBm6k_c5a4CIZ | simonw 9599 | 2023-04-27T03:50:51Z | 2023-04-27T03:50:51Z | OWNER | Failure was on 3.7. I'll try that. | {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} | Failing test: httpx.InvalidURL: URL too long 1686042269 | |
1524637376 | https://github.com/simonw/datasette/issues/2066#issuecomment-1524637376 | https://api.github.com/repos/simonw/datasette/issues/2066 | IC_kwDOBm6k_c5a4B7A | simonw 9599 | 2023-04-27T03:50:19Z | 2023-04-27T03:50:19Z | OWNER | Having trouble replicating this on my laptop. I tried a fresh virtual environment with fresh packages (in case this is a `httpx` change) but this passed: pytest tests/test_csv.py | {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} | Failing test: httpx.InvalidURL: URL too long 1686042269 | |
1524616740 | https://github.com/simonw/datasette/issues/2065#issuecomment-1524616740 | https://api.github.com/repos/simonw/datasette/issues/2065 | IC_kwDOBm6k_c5a384k | simonw 9599 | 2023-04-27T03:38:21Z | 2023-04-27T03:38:21Z | OWNER | Tried this: rye install https://github.com/simonw/datasette/archive/refs/heads/main.zip But got this error: Error: Expected one of `@`, `(`, `<`, `=`, `>`, `~`, `!`, `;`, found `:` I instead downloaded that file and ran: rye install main.zip This worked! And now: ``` ~/.rye/tools/main-zip/bin/datasette --version ``` ``` datasette, version 1.0a2 ``` | {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} | Datasette cannot be installed with Rye 1686033652 | |
1521837780 | https://github.com/simonw/datasette/pull/2063#issuecomment-1521837780 | https://api.github.com/repos/simonw/datasette/issues/2063 | IC_kwDOBm6k_c5atWbU | dependabot[bot] 49699333 | 2023-04-25T13:57:52Z | 2023-04-25T13:57:52Z | CONTRIBUTOR | Superseded by #2064. | {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} | Bump sphinx from 6.1.3 to 6.2.0 1681339696 | |
1515694393 | https://github.com/simonw/datasette/pull/2052#issuecomment-1515694393 | https://api.github.com/repos/simonw/datasette/issues/2052 | IC_kwDOBm6k_c5aV6k5 | hydrosquall 9020979 | 2023-04-20T04:25:55Z | 2023-04-20T04:25:55Z | NONE | Thanks for the thoughtful review and generous examples @asg017 ! I'll make the changes you suggested soon. Bonus thoughts inlined below. > comments These were very much appreciated, it's important to a plugin system that details like this feel right! I'll address them in batch later in the week. > I know TypeScript can be a little controversial FWIW I am in favor of doing Typescript - I just wanted to keep the initial set of files in this PR as simple as possible to review. Really appreciate you scaffolding this initial set of types + I think it would be a welcome addition to maintain a set of types.d.ts files. I'm entertaining the idea of writing the actual source code in Typescript as long as the compiled output is readable b/c it can be tricky to keep the types and plain JS files in sync. Curious if you have encountered projects that are good at preventing drift. > Maybe they should have more "action-y" names This is a great observation. I'm inclined towards something like `make*` or `build*` since to me `add*` make me think the thing the method is attached to is being mutated, but I agree that any of these may be clearer than the current `get*` setup. I'll go through and update these. > Maybe we can make it easier to do pure-js datasette plugins? I really like this idea! It'll be easier to get contributors if they don't have to touch the python side at _all_. > And then do the PERMITTED_VIEWS filtering in JS rather than Python. One cost of doing this is that pages that won't use the JS would still have to load the unused code (given that I'm not sending up anything complex like lazy loading). But hopefully the manager core size is close to negligible, and it won't be a big deal. | {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} | feat: Javascript Plugin API (Custom panels, column menu items with JS actions) 1651082214 | |
1510423215 | https://github.com/simonw/datasette/pull/2052#issuecomment-1510423215 | https://api.github.com/repos/simonw/datasette/issues/2052 | IC_kwDOBm6k_c5aBzqv | hydrosquall 9020979 | 2023-04-16T16:12:59Z | 2023-04-16T16:12:59Z | NONE | ## Research notes - I stuck to the "minimal dependencies" ethos of datasette (no React, Typescript, JS linting, etc). - Main threads on JS plugin development - Main: sketch of pluggy-inspired system: https://github.com/simonw/datasette/issues/983 - Main: provide locations in Datasette HTML that are designed for multiple plugins to safely cooperate with each other (starting with the panel, but eventually could extend to "search boxes"): https://github.com/simonw/datasette/issues/1191 - Main: HTML hooks for JS plugin authors: https://github.com/simonw/datasette/issues/987 - Prior threads on JS plugins in Datasette for future design directions - Idea: pass useful strings to JS plugins: https://github.com/simonw/datasette/issues/1565 - Idea: help with plugin dependency loading: https://github.com/simonw/datasette/issues/1542 . (IMO - the plugin providing the dependency can emit an event once it's done. Other plugins can listen for it, or ask the manager to inform them when the dependency is available). - Idea: help plugins to manage state in shareable URLs (plugins shouldn't have to interact with the URL directly, should have some basic insulation from clobbering each others' keys): https://github.com/simonw/datasette/issues/1144 - Articles on plugins reviewed - https://css-tricks.com/designing-a-javascript-plugin-system/ - Plugin/Extension systems reviewed (mostly JS). - Yarn: https://yarnpkg.com/advanced/plugin-tutorial - Tappable https://github.com/webpack/tapable (used by Auto, webpack) - Pluggy: https://pluggy.readthedocs.io/en/stable/ - VSCode: https://code.visualstudio.com/api/get-started/your-first-extension - Chrome: https://developer.chrome.com/docs/extensions/reference/ - Figma/Figjam Widget: https://www.figma.com/widget-docs/ - Datadog Apps: [Programming Model](https://github.com/DataDog/apps/blob/master/docs/en/programming-model.md) - Storybook: https://storybook.js.org/docs/react/addons/addons-api | {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} | feat: Javascript Plugin API (Custom panels, column menu items with JS actions) 1651082214 | |
1510423051 | https://github.com/simonw/datasette/pull/2052#issuecomment-1510423051 | https://api.github.com/repos/simonw/datasette/issues/2052 | IC_kwDOBm6k_c5aBzoL | hydrosquall 9020979 | 2023-04-16T16:12:14Z | 2023-04-20T05:14:39Z | NONE | # Javascript Plugin Docs (alpha) ## Motivation The Datasette JS Plugin API allows developers to add interactive features to the UI, without having to modify the Python source code. ## Setup No external/NPM dependencies are needed. Plugin behavior is coordinated by the Datasette `manager`. Every page has 1 `manager`. There are 2 ways to add your plugin to the `manager`. 1. Read `window.__DATASETTE__` if the manager was already loaded. ```js const manager = window.__DATASETTE__; ``` 2. Wait for the `datasette_init` event to fire if your code was loaded before the manager is ready. ```js document.addEventListener("datasette_init", function (evt) { const { detail: manager } = evt; // register plugin here }); ``` 3. Add plugin to the manager by calling `manager.registerPlugin` in a JS file. Each plugin will supply 1 or more hooks with - unique name (`YOUR_PLUGIN_NAME`) - a numeric version (starting at `0.1`), - configuration value, the details vary by hook. (In this example, `getColumnActions` takes a function) ```js manager.registerPlugin("YOUR_PLUGIN_NAME", { version: 0.1, makeColumnActions: (columnMeta) => { return [ { label: "Copy name to clipboard", // evt = native click event onClick: (evt) => copyToClipboard(columnMeta.column), } ]; }, }); ``` There are 2 plugin hooks available to `manager.registerPlugin`: - `makeColumnActions` - Add items to the cog menu for headers on datasette table pages - `makeAboveTablePanelConfigs` - Add items to "tabbed" panel above the `<table/>` on pages that use the Datasette table template. While there are additional properties on the `manager`, but it's not advised to depend on them directly as the shape is subject to change. 4. To make your JS file available as a Datasette plugin from the Python side, you can add a python file resembling [this](https://github.com/simonw/datasette/pull/2052/files#diff-c5ecf3d22075a60d04a4e95da2… | {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} | feat: Javascript Plugin API (Custom panels, column menu items with JS actions) 1651082214 | |
1509951952 | https://github.com/simonw/sqlite-utils/issues/425#issuecomment-1509951952 | https://api.github.com/repos/simonw/sqlite-utils/issues/425 | IC_kwDOCGYnMM5aAAnQ | Dhyanesh97 89400147 | 2023-04-15T20:14:58Z | 2023-04-15T20:14:58Z | NONE | is this change released ? Because when we run docker containers issue still persists for production deployments. | {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} | `sqlite3.NotSupportedError`: deterministic=True requires SQLite 3.8.3 or higher 1203842656 | |
1509852821 | https://github.com/simonw/datasette/pull/2056#issuecomment-1509852821 | https://api.github.com/repos/simonw/datasette/issues/2056 | IC_kwDOBm6k_c5Z_oaV | cclauss 3709715 | 2023-04-15T14:24:45Z | 2023-04-15T14:24:45Z | NONE | Status? | {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} | GitHub Action to lint Python code with ruff 1661860507 | |
1509461324 | https://github.com/simonw/datasette/pull/2052#issuecomment-1509461324 | https://api.github.com/repos/simonw/datasette/issues/2052 | IC_kwDOBm6k_c5Z-I1M | hydrosquall 9020979 | 2023-04-15T01:57:06Z | 2023-04-15T01:57:06Z | NONE | Notes from 1:1 - it _is_ possible to pass in URL params into a ObservableHQ notebook: https://observablehq.com/@bherbertlc/pass-values-as-url-parameters | {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} | feat: Javascript Plugin API (Custom panels, column menu items with JS actions) 1651082214 | |
1508784533 | https://github.com/dogsheep/apple-notes-to-sqlite/issues/6#issuecomment-1508784533 | https://api.github.com/repos/dogsheep/apple-notes-to-sqlite/issues/6 | IC_kwDOJHON9s5Z7jmV | sirnacnud 579727 | 2023-04-14T15:22:09Z | 2023-04-14T15:22:09Z | NONE | Just changing the encoding in `extract_notes` to `utf8` seems to fix it for my titles that were messed up. ![Screen Shot 2023-04-14 at 5 14 18 PM](https://user-images.githubusercontent.com/579727/232086062-e7edc4d1-0880-417a-925b-fd6c65b05155.png) | {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} | Character encoding problem 1617602868 | |
1507264934 | https://github.com/simonw/datasette/issues/2058#issuecomment-1507264934 | https://api.github.com/repos/simonw/datasette/issues/2058 | IC_kwDOBm6k_c5Z1wmm | esagara 1138559 | 2023-04-13T16:35:21Z | 2023-04-13T16:35:21Z | NONE | I tried deploying the fix you submitted, but still getting the same errors. I can past the logs here if needed, but I really don't see anything new in them. | {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} | 500 "attempt to write a readonly database" error caused by "PRAGMA schema_version" 1663399821 | |
1506485287 | https://github.com/simonw/datasette/pull/2056#issuecomment-1506485287 | https://api.github.com/repos/simonw/datasette/issues/2056 | IC_kwDOBm6k_c5ZyyQn | cclauss 3709715 | 2023-04-13T07:29:38Z | 2023-04-13T07:41:55Z | NONE | Ruff (written in Rust, not Python) is a 23MB executable so the time to download and pip install it dwarfs its runtime. Let's run ruff with and without GitHub Actions pip cache side-by-side to see the relative performance. Once you approve the workflows below, `ruff_with_cache` should echo `cache-hit = false` but if you rerun that job hopefully it should echo `cache-hit = true`. That will be the execution time that we are interested to compare. There are two great problems in computer science: ;-) 1. Naming things 2. Cache invalidation 3. Off-by-one errors For 2., https://github.com/actions/setup-python#caching-packages-dependencies is vital reading. Only _exactly pinned requirements_ can be cached. Currently in `setup.py` the only pinned dependencies are: 1. Sphinx==6.1.3 2. furo==2023.3.27 3. black==23.3.0 4. blacken-docs==1.13.0 # but unpinned elsewhere in `setup.py` This means that there will be very few cache hits in the current actions. See the link below to print out cache hits: https://github.com/actions/setup-python/blob/main/docs/advanced-usage.md#cache-hit > PyPI uses Fastly's CDN to quickly serve content to end-users, allowing us to minimize our hosting infrastructure and obscure possible downtime. -- https://pypi.org/sponsors I would be shocked if Fastly does not have beefy CDN nodes in the same datacenters where GitHub Actions run so GHA requests to download `ruff` probably never hit a PyPI server. | {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} | GitHub Action to lint Python code with ruff 1661860507 | |
1506223848 | https://github.com/simonw/sqlite-utils/issues/527#issuecomment-1506223848 | https://api.github.com/repos/simonw/sqlite-utils/issues/527 | IC_kwDOCGYnMM5Zxybo | simonw 9599 | 2023-04-13T02:08:16Z | 2023-04-13T02:08:16Z | OWNER | I agree, this is a design flaw. It's technically a breaking change. As such, I would need to bump to v4 to responsibly release this. I'd rather bundle in a few more breaking changes before shipping that version. One thing we could do here is add an extra argument to `.convert()` - something like this: ```python table.convert(col, lambda x: x+1, skip_false=False) ``` This would trigger the new, improved behaviour without breaking existing code that depends on how it works at the moment. Then in `sqlite-utils` 4 we can change the default of that option. What do you think? (I'm open to suggestions for better names for this parameter too) | {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} | `Table.convert()` skips falsey values 1578790070 | |
1506203550 | https://github.com/simonw/datasette/issues/2058#issuecomment-1506203550 | https://api.github.com/repos/simonw/datasette/issues/2058 | IC_kwDOBm6k_c5Zxtee | cephillips 547438 | 2023-04-13T01:48:21Z | 2023-04-13T01:48:21Z | NONE | Really interesting how you are using ChatGPT in this. | {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} | 500 "attempt to write a readonly database" error caused by "PRAGMA schema_version" 1663399821 | |
1506200813 | https://github.com/simonw/sqlite-utils/pull/537#issuecomment-1506200813 | https://api.github.com/repos/simonw/sqlite-utils/issues/537 | IC_kwDOCGYnMM5Zxszt | codecov[bot] 22429695 | 2023-04-13T01:45:22Z | 2023-04-13T01:45:22Z | NONE | ## [Codecov](https://codecov.io/gh/simonw/sqlite-utils/pull/537?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Simon+Willison) Report Patch coverage: **`100.00`**% and no project coverage change. > Comparison is base [(`c0251cc`)](https://codecov.io/gh/simonw/sqlite-utils/commit/c0251cc9271260de73b4227859a51fab9b4cb745?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Simon+Willison) 96.25% compared to head [(`a75abeb`)](https://codecov.io/gh/simonw/sqlite-utils/pull/537?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Simon+Willison) 96.25%. <details><summary>Additional details and impacted files</summary> ```diff @@ Coverage Diff @@ ## main #537 +/- ## ======================================= Coverage 96.25% 96.25% ======================================= Files 6 6 Lines 2671 2673 +2 ======================================= + Hits 2571 2573 +2 Misses 100 100 ``` | [Impacted Files](https://codecov.io/gh/simonw/sqlite-utils/pull/537?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Simon+Willison) | Coverage Δ | | |---|---|---| | [sqlite\_utils/db.py](https://codecov.io/gh/simonw/sqlite-utils/pull/537?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Simon+Willison#diff-c3FsaXRlX3V0aWxzL2RiLnB5) | `97.33% <100.00%> (+<0.01%)` | :arrow_up: | Help us with your feedback. Take ten seconds to tell us [how you rate us](https://about.codecov.io/nps?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Simon+Willison). Have a feature suggestion? [Share it here.](https://app.codecov.io/gh/feedback/?utm_medium=referral&utm_source=github&utm_content=comment&u… | {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} | Support self-referencing FKs in `Table.create` 1665200812 | |
1506179555 | https://github.com/simonw/datasette/pull/2056#issuecomment-1506179555 | https://api.github.com/repos/simonw/datasette/issues/2056 | IC_kwDOBm6k_c5Zxnnj | simonw 9599 | 2023-04-13T01:21:05Z | 2023-04-13T01:22:08Z | OWNER | OK, I'm sold - this is a really neat improvement. One thing to change in the PR: right now it runs `pip install --user ruff` on every commit, which hits PyPI to install the package. I prefer to avoid hitting PyPI every time, so I like to use the GitHub Actions cache. My usual pattern for that looks like this: https://github.com/simonw/datasette/blob/5890a20c374fb0812d88c9b0ef26a838bfa06c76/.github/workflows/test-pyodide.yml#L16-L20 Then a separate command that runs `pip install ...` will benefit from that cache. Are you OK to make that change? | {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} | GitHub Action to lint Python code with ruff 1661860507 | |
1506177857 | https://github.com/simonw/datasette/pull/2056#issuecomment-1506177857 | https://api.github.com/repos/simonw/datasette/issues/2056 | IC_kwDOBm6k_c5ZxnNB | simonw 9599 | 2023-04-13T01:18:18Z | 2023-04-13T01:18:18Z | OWNER | Cool - and now https://github.com/simonw/datasette/pull/2056/files is showing me those inline annotations: <img width="868" alt="image" src="https://user-images.githubusercontent.com/9599/231620660-4843d113-b671-494e-8265-24226446abba.png"> | {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} | GitHub Action to lint Python code with ruff 1661860507 | |
1506177115 | https://github.com/simonw/datasette/pull/2056#issuecomment-1506177115 | https://api.github.com/repos/simonw/datasette/issues/2056 | IC_kwDOBm6k_c5ZxnBb | simonw 9599 | 2023-04-13T01:17:16Z | 2023-04-13T01:17:16Z | OWNER | Here are the failures: https://github.com/simonw/datasette/actions/runs/4684460653/jobs/8300630794?pr=2056 <img width="902" alt="CleanShot 2023-04-12 at 18 16 45@2x" src="https://user-images.githubusercontent.com/9599/231620533-bce286b7-8173-4a61-aac1-b772832fb893.png"> | {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} | GitHub Action to lint Python code with ruff 1661860507 | |
1506175208 | https://github.com/simonw/datasette/pull/2056#issuecomment-1506175208 | https://api.github.com/repos/simonw/datasette/issues/2056 | IC_kwDOBm6k_c5Zxmjo | simonw 9599 | 2023-04-13T01:14:13Z | 2023-04-13T01:14:13Z | OWNER | https://github.com/simonw/datasette/actions/runs/4664796647/jobs/8300596121?pr=2056 it's pretty fast - that finished in 9s. | {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} | GitHub Action to lint Python code with ruff 1661860507 | |
1506174353 | https://github.com/simonw/datasette/issues/2059#issuecomment-1506174353 | https://api.github.com/repos/simonw/datasette/issues/2059 | IC_kwDOBm6k_c5ZxmWR | simonw 9599 | 2023-04-13T01:13:00Z | 2023-04-13T01:13:00Z | OWNER | Can you provide a URL to an example, and/or a screenshot of this? Is it a browser warning or is it a warning from Heroku itself? | {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} | "Deceptive site ahead" alert on Heroku deployment 1665053646 | |
1504426792 | https://github.com/simonw/datasette/issues/2058#issuecomment-1504426792 | https://api.github.com/repos/simonw/datasette/issues/2058 | IC_kwDOBm6k_c5Zq7so | simonw 9599 | 2023-04-12T02:02:42Z | 2023-04-12T02:02:42Z | OWNER | I tightened up the benchmark (it was measuring the time taken to create the tables too) and got this: ![image](https://user-images.githubusercontent.com/9599/231328328-85ca35ac-a11b-46f4-b132-dae367103570.png) | {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} | 500 "attempt to write a readonly database" error caused by "PRAGMA schema_version" 1663399821 | |
1504328395 | https://github.com/simonw/datasette/issues/2058#issuecomment-1504328395 | https://api.github.com/repos/simonw/datasette/issues/2058 | IC_kwDOBm6k_c5ZqjrL | simonw 9599 | 2023-04-12T00:28:38Z | 2023-04-12T00:28:38Z | OWNER | Here's a much better chart, which shows that MD5 performance unsurprisingly gets worse as the number of tables increases while `schema_version` remains constant: ![image](https://user-images.githubusercontent.com/9599/231316778-513bd99f-5ea4-495c-b86d-c572a7106369.png) | {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} | 500 "attempt to write a readonly database" error caused by "PRAGMA schema_version" 1663399821 | |
1504315697 | https://github.com/simonw/datasette/issues/2058#issuecomment-1504315697 | https://api.github.com/repos/simonw/datasette/issues/2058 | IC_kwDOBm6k_c5Zqgkx | simonw 9599 | 2023-04-12T00:16:22Z | 2023-04-12T00:27:12Z | OWNER | I got ChatGPT (code execution alpha) to run a micro-benchmark for me. This was the conclusion: > The benchmark using `PRAGMA schema_version` is approximately 1.36 times faster than the benchmark using `hashlib.md5` for the case with 100 tables. For the case with 200 tables, the benchmark using `PRAGMA schema_version` is approximately 2.33 times faster than the benchmark using `hashlib.md5`. Here's the chart it drew me: ![image](https://user-images.githubusercontent.com/9599/231315366-3a12b6d3-08d7-419d-a1fd-36eb24da0d85.png) (It's a pretty rubbish chart though, it only took measurements at 100 and 200 and drew a line between the two, I should have told it to measure every 10 and plot that) And the full transcript: https://gist.github.com/simonw/2fc46effbfbe49e6de0bcfdc9e31b235 The benchmark looks good enough on first glance that I don't feel the need to be more thorough with it. `PRAGMA schema_version` is faster, but not so fast that I feel like the MD5 hack is worth worrying about too much. I'm tempted to add something to the `/-/versions` page that tries to identify if this is a problem or not though. | {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} | 500 "attempt to write a readonly database" error caused by "PRAGMA schema_version" 1663399821 | |
1504298448 | https://github.com/simonw/datasette/issues/2058#issuecomment-1504298448 | https://api.github.com/repos/simonw/datasette/issues/2058 | IC_kwDOBm6k_c5ZqcXQ | simonw 9599 | 2023-04-12T00:04:01Z | 2023-04-12T00:04:01Z | OWNER | Here's a potential workaround: when I store the schema versions, I could also score an MD5 hash of the full schema (`select group_concat(sql) from sqlite_master`). When I read the schema version with `PRAGMA schema_version` I could catch that exception and, if I see it, I could calculate that MD5 hash again as a fallback and use that to determine if the schema has changed instead. The performance overhead of this needs investigating - how much more expensive is `md5(... that SQL query result)` compared to just `PRAGMA schema_version`, especially on a database with a lot of tables? | {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} | 500 "attempt to write a readonly database" error caused by "PRAGMA schema_version" 1663399821 | |
1504295345 | https://github.com/simonw/datasette/issues/2058#issuecomment-1504295345 | https://api.github.com/repos/simonw/datasette/issues/2058 | IC_kwDOBm6k_c5Zqbmx | simonw 9599 | 2023-04-12T00:01:42Z | 2023-04-12T00:02:26Z | OWNER | Here's the relevant code: https://github.com/simonw/datasette/blob/5890a20c374fb0812d88c9b0ef26a838bfa06c76/datasette/app.py#L421-L437 This function is called on almost every request (everything that subclasses `BaseView` at least - need to remember that for the refactor in #2053 etc). https://github.com/simonw/datasette/blob/5890a20c374fb0812d88c9b0ef26a838bfa06c76/datasette/views/base.py#L101-L103 It uses `PRAGMA schema_version` as a cheap way to determine if the schema has changed, in which case it needs to refresh the internal schema tables. This was already the cause of a subtle bug here: - #1231 | {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} | 500 "attempt to write a readonly database" error caused by "PRAGMA schema_version" 1663399821 | |
1504292145 | https://github.com/simonw/datasette/issues/2058#issuecomment-1504292145 | https://api.github.com/repos/simonw/datasette/issues/2058 | IC_kwDOBm6k_c5Zqa0x | simonw 9599 | 2023-04-11T23:58:59Z | 2023-04-11T23:58:59Z | OWNER | Asked on the SQLite Forum if anyone has seen this before: https://sqlite.org/forum/forumpost/793a2ed75b | {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} | 500 "attempt to write a readonly database" error caused by "PRAGMA schema_version" 1663399821 | |
1504291892 | https://github.com/simonw/datasette/issues/2058#issuecomment-1504291892 | https://api.github.com/repos/simonw/datasette/issues/2058 | IC_kwDOBm6k_c5Zqaw0 | simonw 9599 | 2023-04-11T23:58:45Z | 2023-04-11T23:58:45Z | OWNER | I thought it might relate to the "defensive mode" issue described here: - https://github.com/simonw/sqlite-utils/issues/235 But I have since determined that the Datasette official Docker image does NOT run anything in defensive mode, so I don't think it's related to that. | {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} | 500 "attempt to write a readonly database" error caused by "PRAGMA schema_version" 1663399821 | |
1504288134 | https://github.com/simonw/sqlite-utils/issues/235#issuecomment-1504288134 | https://api.github.com/repos/simonw/sqlite-utils/issues/235 | IC_kwDOCGYnMM5ZqZ2G | simonw 9599 | 2023-04-11T23:55:06Z | 2023-04-12T03:34:32Z | OWNER | Also checked the official Datasette Docker image - I had to run that in Codespaces because it doesn't currently work on my M2 Mac: ``` codespace@codespaces-112c61:/workspaces/sqlite-utils$ docker pull datasetteproject/datasette Using default tag: latest ... codespace@codespaces-112c61:/workspaces/sqlite-utils$ docker run -it datasetteproject/datasette / bin/bash root@75ba34f501ec:/# python Python 3.11.0 (main, Dec 6 2022, 13:31:55) [GCC 10.2.1 20210110] on linux Type "help", "copyright", "credits" or "license" for more information. >>> import sqlite3 .executescript(""" PRAGMA writable_schema = 1; UPDATE sqlite_master SET sql = 'CREATE TABLE [foos] (id integer primary key)'; PRAGMA writable_schema = 0; """)>>> db = sqlite3.connect(":memory:") >>> db.executescript(""" ... PRAGMA writable_schema = 1; ... UPDATE sqlite_master SET sql = 'CREATE TABLE [foos] (id integer primary key)'; ... PRAGMA writable_schema = 0; ... """) <sqlite3.Cursor object at 0x7fd9b0561140> >>> ``` So that confirms that the official image also has a Python with a SQLite that's not in defensive mode. | {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} | Extract columns cannot create foreign key relation: sqlite3.OperationalError: table sqlite_master may not be modified 810618495 | |
1504245029 | https://github.com/simonw/sqlite-utils/issues/235#issuecomment-1504245029 | https://api.github.com/repos/simonw/sqlite-utils/issues/235 | IC_kwDOCGYnMM5ZqPUl | simonw 9599 | 2023-04-11T23:13:41Z | 2023-04-11T23:14:39Z | OWNER | I also tested this against the current `ubuntu:latest` Docker image (on an M2 Mac), in Python 3.10 and 3.11: ``` docker run -it ubuntu:latest /bin/bash ``` Then in the container: ``` apt-get update apt-get install python3 python3 # pasted in the above recipe apt install software-properties-common add-apt-repository ppa:deadsnakes/ppa apt install python3.11 python3.11 # pasted it in again ``` In both cases the Python code did not raise an exception, which suggests that on Ubuntu those two Python versions do not have the defensive mode set. | {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} | Extract columns cannot create foreign key relation: sqlite3.OperationalError: table sqlite_master may not be modified 810618495 | |
1503838640 | https://github.com/simonw/datasette/issues/2057#issuecomment-1503838640 | https://api.github.com/repos/simonw/datasette/issues/2057 | IC_kwDOBm6k_c5ZosGw | simonw 9599 | 2023-04-11T17:48:23Z | 2023-04-11T17:48:23Z | OWNER | > This looks wrong to me - I would expect something like `is_directory()` not `is_file()` for telling if `static/` is a directory. I was right about that: ```pycon >>> importlib.resources.files('datasette_graphql') PosixPath('/Users/simon/.local/share/virtualenvs/datasette-big-local-6Yn-280V/lib/python3.11/site-packages/datasette_graphql') >>> importlib.resources.files('datasette_graphql').joinpath("static") PosixPath('/Users/simon/.local/share/virtualenvs/datasette-big-local-6Yn-280V/lib/python3.11/site-packages/datasette_graphql/static') >>> p = importlib.resources.files('datasette_graphql').joinpath("static") >>> p PosixPath('/Users/simon/.local/share/virtualenvs/datasette-big-local-6Yn-280V/lib/python3.11/site-packages/datasette_graphql/static') >>> p.is_ p.is_absolute() p.is_char_device() p.is_fifo() p.is_mount() p.is_reserved() p.is_symlink() p.is_block_device() p.is_dir() p.is_file() p.is_relative_to( p.is_socket() >>> p.is_dir() True >>> p.is_file() False ``` | {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} | DeprecationWarning: pkg_resources is deprecated as an API 1662951875 | |
1503833906 | https://github.com/simonw/datasette/issues/2057#issuecomment-1503833906 | https://api.github.com/repos/simonw/datasette/issues/2057 | IC_kwDOBm6k_c5Zoq8y | simonw 9599 | 2023-04-11T17:44:16Z | 2023-04-11T17:45:45Z | OWNER | Another prompt: > How to fix this: > > `pkg_resources.get_distribution(package).version` Response: <img width="641" alt="image" src="https://user-images.githubusercontent.com/9599/231245559-dd943527-818a-45aa-9833-b9db8c7ca87e.png"> ```python import importlib.metadata # Get the version number of the specified package package_version = importlib.metadata.version(package) ``` That seems to work: ```pycon >>> import importlib.metadata >>> importlib.metadata.version("datasette") '0.64.2' >>> importlib.metadata.version("pluggy") '1.0.0' >>> importlib.metadata.version("not-a-package") ... importlib.metadata.PackageNotFoundError: No package metadata was found for not-a-package ``` | {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} | DeprecationWarning: pkg_resources is deprecated as an API 1662951875 | |
1503832422 | https://github.com/simonw/datasette/issues/2057#issuecomment-1503832422 | https://api.github.com/repos/simonw/datasette/issues/2057 | IC_kwDOBm6k_c5Zoqlm | simonw 9599 | 2023-04-11T17:42:57Z | 2023-04-11T17:46:42Z | OWNER | I ran this prompt against ChatGPT with the Browsing alpha: > ```python > if pkg_resources.resource_isdir(plugin.__name__, "static"): > static_path = pkg_resources.resource_filename( > plugin.__name__, "static" > ) > if pkg_resources.resource_isdir(plugin.__name__, "templates"): > templates_path = pkg_resources.resource_filename( > plugin.__name__, "templates" > ) > ``` > This code gives a deprecation warning in Python 3.11 - fix it It looked up the fix for me: <img width="632" alt="image" src="https://user-images.githubusercontent.com/9599/231245259-af4d962c-e631-420b-8312-fd9657a23bbd.png"> And suggested: ```python import importlib.resources # Replace pkg_resources.resource_isdir with importlib.resources.files().is_file() if importlib.resources.files(plugin.__name__).joinpath("static").is_file(): static_path = importlib.resources.as_file( importlib.resources.files(plugin.__name__).joinpath("static") ) if importlib.resources.files(plugin.__name__).joinpath("templates").is_file(): templates_path = importlib.resources.as_file( importlib.resources.files(plugin.__name__).joinpath("templates") ) ``` This looks wrong to me - I would expect something like `is_directory()` not `is_file()` for telling if `static/` is a directory. | {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} | DeprecationWarning: pkg_resources is deprecated as an API 1662951875 | |
1502629404 | https://github.com/dogsheep/swarm-to-sqlite/issues/13#issuecomment-1502629404 | https://api.github.com/repos/dogsheep/swarm-to-sqlite/issues/13 | IC_kwDODD6af85ZkE4c | simonw 9599 | 2023-04-11T03:15:47Z | 2023-04-11T03:46:17Z | MEMBER | I think `swarm-to-sqlite` needs to avoid this error, maybe by setting up foreign keys in another way - or even by skipping foreign keys entirely on databases that don't support this kind of operation. | {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} | fails before generating views. ERR: table sqlite_master may not be modified 1373210675 | |
1502629219 | https://github.com/dogsheep/swarm-to-sqlite/issues/13#issuecomment-1502629219 | https://api.github.com/repos/dogsheep/swarm-to-sqlite/issues/13 | IC_kwDODD6af85ZkE1j | simonw 9599 | 2023-04-11T03:15:26Z | 2023-04-11T03:15:26Z | MEMBER | OK, I figured this out. Unfortunately it's an error that occurs on Python versions that have defensive mode turned on, and it doesn't look like there's a way to turn that mode off. See notes above. | {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} | fails before generating views. ERR: table sqlite_master may not be modified 1373210675 | |
1502559442 | https://github.com/simonw/sqlite-utils/issues/235#issuecomment-1502559442 | https://api.github.com/repos/simonw/sqlite-utils/issues/235 | IC_kwDOCGYnMM5ZjzzS | simonw 9599 | 2023-04-11T01:32:30Z | 2023-04-11T01:33:27Z | OWNER | This seems to work: ```python import sqlite3 db = sqlite3.connect(":memory:") db.executescript(""" PRAGMA writable_schema = 1; UPDATE sqlite_master SET sql = 'CREATE TABLE [foos] (id integer primary key)'; PRAGMA writable_schema = 0; """) ``` It succeeds on my Python 3.11 and raises the following exception on my broken Python 3.9: ``` sqlite3.OperationalError: table sqlite_master may not be modified ``` Removing the `PRAGMA writable_schema = 1;` causes the same exception to be raised on both Pythons. | {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} | Extract columns cannot create foreign key relation: sqlite3.OperationalError: table sqlite_master may not be modified 810618495 | |
1502557629 | https://github.com/simonw/sqlite-utils/issues/235#issuecomment-1502557629 | https://api.github.com/repos/simonw/sqlite-utils/issues/235 | IC_kwDOCGYnMM5ZjzW9 | simonw 9599 | 2023-04-11T01:30:12Z | 2023-04-11T01:30:12Z | OWNER | I'll ask on the SQLite forum if it's possible to toggle that mode on and off using regular SQL. My hunch is that it isn't. In which case `sqlite-utils` should at least know how to catch this error and display a much more readable error message, maybe with a link to further documentation. A utility function that can detect this mode would be really useful too. I'd probably have to do a test that tries to modify `sqlite_master` on a new in-memory database to catch if it's possible or not. | {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} | Extract columns cannot create foreign key relation: sqlite3.OperationalError: table sqlite_master may not be modified 810618495 | |
1502556111 | https://github.com/simonw/sqlite-utils/issues/235#issuecomment-1502556111 | https://api.github.com/repos/simonw/sqlite-utils/issues/235 | IC_kwDOCGYnMM5Zjy_P | simonw 9599 | 2023-04-11T01:28:41Z | 2023-04-11T01:28:41Z | OWNER | Investigating this one now. The `sqlite-utils` test suite passes without errors on my Python 3.11.2 installation... but it fails with this error on a Python 3.9.6 installation. In the broken version's virtual environment directory I ran this: ``` cat pyvenv.cfg home = /Applications/Xcode.app/Contents/Developer/usr/bin implementation = CPython version_info = 3.9.6.final.0 virtualenv = 20.17.1 include-system-site-packages = false base-prefix = /Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9 base-exec-prefix = /Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.9 base-executable = /Applications/Xcode.app/Contents/Developer/usr/bin/python3 ``` So it looks like the Xcode `python3` has "defensive" mode turned on for SQLite. As far as I can tell there's no way to turn it OFF again in Python. My virtual environment that DOES work has this: ``` home = /opt/homebrew/opt/python@3.11/bin implementation = CPython version_info = 3.11.2.final.0 virtualenv = 20.17.1 include-system-site-packages = false base-prefix = /opt/homebrew/opt/python@3.11/Frameworks/Python.framework/Versions/3.11 base-exec-prefix = /opt/homebrew/opt/python@3.11/Frameworks/Python.framework/Versions/3.11 base-executable = /opt/homebrew/opt/python@3.11/bin/python3.11 ``` So the Python 3.11 I installed through Homebrew doesn't exhibit this bug. | {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} | Extract columns cannot create foreign key relation: sqlite3.OperationalError: table sqlite_master may not be modified 810618495 | |
1502546045 | https://github.com/dogsheep/swarm-to-sqlite/issues/13#issuecomment-1502546045 | https://api.github.com/repos/dogsheep/swarm-to-sqlite/issues/13 | IC_kwDODD6af85Zjwh9 | simonw 9599 | 2023-04-11T01:14:50Z | 2023-04-11T01:14:50Z | MEMBER | Related: - https://github.com/simonw/sqlite-utils/issues/235 | {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} | fails before generating views. ERR: table sqlite_master may not be modified 1373210675 | |
1502543165 | https://github.com/dogsheep/swarm-to-sqlite/issues/13#issuecomment-1502543165 | https://api.github.com/repos/dogsheep/swarm-to-sqlite/issues/13 | IC_kwDODD6af85Zjv09 | simonw 9599 | 2023-04-11T01:10:36Z | 2023-04-11T01:11:47Z | MEMBER | I just had that error myself on macOS while running the tests: ``` ERROR tests/test_save_checkin.py::test_tables - sqlite3.OperationalError: table sqlite_master may not be modified ERROR tests/test_save_checkin.py::test_venue - sqlite3.OperationalError: table sqlite_master may not be modified ERROR tests/test_save_checkin.py::test_event - sqlite3.OperationalError: table sqlite_master may not be modified ERROR tests/test_save_checkin.py::test_sticker - sqlite3.OperationalError: table sqlite_master may not be modified ERROR tests/test_save_checkin.py::test_likes - sqlite3.OperationalError: table sqlite_master may not be modified ERROR tests/test_save_checkin.py::test_with_ - sqlite3.OperationalError: table sqlite_master may not be modified ERROR tests/test_save_checkin.py::test_users - sqlite3.OperationalError: table sqlite_master may not be modified ERROR tests/test_save_checkin.py::test_photos - sqlite3.OperationalError: table sqlite_master may not be modified ERROR tests/test_save_checkin.py::test_posts - sqlite3.OperationalError: table sqlite_master may not be modified ERROR tests/test_save_checkin.py::test_view - sqlite3.OperationalError: table sqlite_master may not be modified ``` `pytest --pdb` shows it happening in the bit that adds foreign keys: ``` > /Users/simon/.local/share/virtualenvs/swarm-to-sqlite-daPW7yIJ/lib/python3.9/site-packages/sqlite_utils/db.py(1096)add_foreign_keys() -> cursor.execute( (Pdb) list 1096 >> cursor.execute( 1097 "UPDATE sqlite_master SET sql = ? WHERE name = ?", 1098 (new_sql, table_name), 1099 ) 1100 cursor.execute("PRAGMA schema_version = %d" % (schema_version + 1)) 1101 -> cursor.execute("PRAGMA writable_schema = 0") 1102 # Have to VACUUM outside the transaction to ensure .foreign_keys property 1103 # can see the newly created foreign key. 1104 self.vacuum() ``` | {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} | fails before generating views. ERR: table sqlite_master may not be modified 1373210675 | |
1501017004 | https://github.com/simonw/sqlite-utils/pull/531#issuecomment-1501017004 | https://api.github.com/repos/simonw/sqlite-utils/issues/531 | IC_kwDOCGYnMM5Zd7Os | eyeseast 25778 | 2023-04-09T01:49:43Z | 2023-04-09T01:49:43Z | CONTRIBUTOR | I'm going to close this in favor of #536. Will try a cleaner approach to custom paths once that one is merge. | {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} | Add paths for homebrew on Apple silicon 1620164673 | |
1500893216 | https://github.com/simonw/sqlite-utils/pull/536#issuecomment-1500893216 | https://api.github.com/repos/simonw/sqlite-utils/issues/536 | IC_kwDOCGYnMM5ZddAg | codecov[bot] 22429695 | 2023-04-08T13:35:42Z | 2023-04-08T13:35:42Z | NONE | ## [Codecov](https://codecov.io/gh/simonw/sqlite-utils/pull/536?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Simon+Willison) Report Patch and project coverage have no change. > Comparison is base [(`c0251cc`)](https://codecov.io/gh/simonw/sqlite-utils/commit/c0251cc9271260de73b4227859a51fab9b4cb745?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Simon+Willison) 96.25% compared to head [(`cea05dc`)](https://codecov.io/gh/simonw/sqlite-utils/pull/536?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Simon+Willison) 96.25%. <details><summary>Additional details and impacted files</summary> ```diff @@ Coverage Diff @@ ## main #536 +/- ## ======================================= Coverage 96.25% 96.25% ======================================= Files 6 6 Lines 2671 2671 ======================================= Hits 2571 2571 Misses 100 100 ``` | [Impacted Files](https://codecov.io/gh/simonw/sqlite-utils/pull/536?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Simon+Willison) | Coverage Δ | | |---|---|---| | [sqlite\_utils/utils.py](https://codecov.io/gh/simonw/sqlite-utils/pull/536?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Simon+Willison#diff-c3FsaXRlX3V0aWxzL3V0aWxzLnB5) | `95.13% <ø> (ø)` | | Help us with your feedback. Take ten seconds to tell us [how you rate us](https://about.codecov.io/nps?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Simon+Willison). Have a feature suggestion? [Share it here.](https://app.codecov.io/gh/feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Si… | {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} | Add paths for homebrew on Apple silicon 1659525418 | |
1500608101 | https://github.com/simonw/datasette/issues/2054#issuecomment-1500608101 | https://api.github.com/repos/simonw/datasette/issues/2054 | IC_kwDOBm6k_c5ZcXZl | simonw 9599 | 2023-04-07T20:14:38Z | 2023-04-07T20:14:38Z | OWNER | Ooh that one's really interesting - very different from the others: ```ruby # app.rb require "roda" class App < Roda route do |r| r.root do "Home page" end r.on "pages" do r.get ":slug" do |slug| "Page: #{slug}" end end r.on "news" do r.get ":yyyy/:mm/:dd" do |yyyy, mm, dd| "News for #{yyyy}/#{mm}/#{dd}" end end end end # config.ru require_relative "app" run App.freeze.app ``` | {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} | Make detailed notes on how table, query and row views work right now 1657861026 | |
1499797384 | https://github.com/simonw/datasette/issues/2054#issuecomment-1499797384 | https://api.github.com/repos/simonw/datasette/issues/2054 | IC_kwDOBm6k_c5ZZReI | dsisnero 6213 | 2023-04-07T00:46:50Z | 2023-04-07T00:46:50Z | NONE | you should have a look at Roda written in ruby . | {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} | Make detailed notes on how table, query and row views work right now 1657861026 | |
1499604822 | https://github.com/simonw/datasette/issues/2054#issuecomment-1499604822 | https://api.github.com/repos/simonw/datasette/issues/2054 | IC_kwDOBm6k_c5ZYidW | simonw 9599 | 2023-04-06T20:48:19Z | 2023-04-06T20:48:55Z | OWNER | I actually quite like that. I could even use `@classmethod` and have utility methods defined on that class that both `get()` and `post()` could call. The crucial rule here is NO INSTANCE STATE - that's what makes routing to classes particularly damaging, and encourages code that's hard to maintain. | {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} | Make detailed notes on how table, query and row views work right now 1657861026 | |
1499604066 | https://github.com/simonw/datasette/issues/2054#issuecomment-1499604066 | https://api.github.com/repos/simonw/datasette/issues/2054 | IC_kwDOBm6k_c5ZYiRi | simonw 9599 | 2023-04-06T20:47:30Z | 2023-04-06T20:47:30Z | OWNER | I'm contemplating a new approach: using a class with static methods. Something like this: ```python class TableView(MethodRouter): @staticmethod async def get(request): return Response.text("GET") @staticmethod async def post(request): return Response.text("POST") ``` So effectively the class is just there to bundle together verb implementations, and to provide a `route(request)` method which knows how to dispatch them to the right place. It can offer default HEAD and OPTIONS methods too. | {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} | Make detailed notes on how table, query and row views work right now 1657861026 | |
1499596941 | https://github.com/simonw/datasette/issues/2054#issuecomment-1499596941 | https://api.github.com/repos/simonw/datasette/issues/2054 | IC_kwDOBm6k_c5ZYgiN | simonw 9599 | 2023-04-06T20:39:35Z | 2023-04-06T20:39:35Z | OWNER | I think there are two main approaches: - Map path to a function, that function then behaves differently on GET/POST/etc - Map method AND path to a function - the `app.get('/example')` v.s. `app.post('/example')` ones The decorator approach is calling out to me a bit now. | {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} | Make detailed notes on how table, query and row views work right now 1657861026 | |
1499530921 | https://github.com/simonw/datasette/issues/2054#issuecomment-1499530921 | https://api.github.com/repos/simonw/datasette/issues/2054 | IC_kwDOBm6k_c5ZYQap | simonw 9599 | 2023-04-06T19:41:52Z | 2023-04-06T19:42:09Z | OWNER | Turned this into a TIL: https://til.simonwillison.net/gpt3/gpt4-api-design | {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} | Make detailed notes on how table, query and row views work right now 1657861026 | |
1499491258 | https://github.com/simonw/datasette/issues/2054#issuecomment-1499491258 | https://api.github.com/repos/simonw/datasette/issues/2054 | IC_kwDOBm6k_c5ZYGu6 | simonw 9599 | 2023-04-06T19:00:16Z | 2023-04-06T20:40:16Z | OWNER | I asked GPT-4 to compare URL routing based on path and verb approaches in different languages and frameworks and spit out some examples. Full transcript here: https://gist.github.com/simonw/fa2379b97420404a81b0fcdb4db79657 Initial prompt: > Show me code examples of different web frameworks in Python and JavaScript and Go illustrating how HTTP routing works - in particular the problem of mapping an incoming HTTP request to some code based on both the URL path and the HTTP verb > > Don't show installation instructions, just get straight to the code snippets Flask: ```python from flask import Flask app = Flask(__name__) @app.route('/example', methods=['GET']) def get_example(): return "This is a GET request." @app.route('/example', methods=['POST']) def post_example(): return "This is a POST request." if __name__ == '__main__': app.run() ``` Express: ```javascript const express = require('express'); const app = express(); app.get('/example', (req, res) => { res.send('This is a GET request.'); }); app.post('/example', (req, res) => { res.send('This is a POST request.'); }); app.listen(3000, () => { console.log('Server is running on port 3000'); }); ``` Gin: ```go package main import ( "github.com/gin-gonic/gin" ) func main() { r := gin.Default() r.GET("/example", func(c *gin.Context) { c.String(200, "This is a GET request.") }) r.POST("/example", func(c *gin.Context) { c.String(200, "This is a POST request.") }) r.Run() } ``` Actix-web: ```rust use actix_web::{web, App, HttpResponse, HttpServer, Responder}; async fn get_example() -> impl Responder { HttpResponse::Ok().body("This is a GET request.") } async fn post_example() -> impl Responder { HttpResponse::Ok().body("This is a POST request.") } #[actix_web::main] async fn main() -> std::io::Result<()> { HttpServer::new(|| { App::new() .route("/example", web::get().to(get_example)) .route("/example… | {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} | Make detailed notes on how table, query and row views work right now 1657861026 | |
1499467703 | https://github.com/simonw/datasette/issues/2054#issuecomment-1499467703 | https://api.github.com/repos/simonw/datasette/issues/2054 | IC_kwDOBm6k_c5ZYA-3 | simonw 9599 | 2023-04-06T18:37:22Z | 2023-04-06T18:57:22Z | OWNER | I've been hoping to move entirely away from class-based views, but now I'm wondering if that's the right decision given the need to support HTTP verbs. It is cleaner to have a class that has methods for each verb, or to have a single function that can behave differently depending on the verb? Or should I have a mechanism for dispatching to separate functions based on the verbs that isn't implemented in a base class? The trouble with using base classes is that I've already shown that they tempt me to put logic in weird places, which makes code harder to modify later on. The thing here is that the ONLY thing I want to use the base class for is as an HTTP verb switcher - which makes me doubt that I should risk taking on the other temptations of having a base class. | {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} | Make detailed notes on how table, query and row views work right now 1657861026 | |
1499465648 | https://github.com/simonw/datasette/issues/2054#issuecomment-1499465648 | https://api.github.com/repos/simonw/datasette/issues/2054 | IC_kwDOBm6k_c5ZYAew | simonw 9599 | 2023-04-06T18:35:03Z | 2023-04-06T18:35:03Z | OWNER | There are actually five classes that subclass `DataView`: https://github.com/simonw/datasette/blob/8b9d7fdbd8de7e74414cc29e3005382669a812dc/datasette/views/row.py#L16 https://github.com/simonw/datasette/blob/8b9d7fdbd8de7e74414cc29e3005382669a812dc/datasette/views/database.py#L34 https://github.com/simonw/datasette/blob/8b9d7fdbd8de7e74414cc29e3005382669a812dc/datasette/views/database.py#L172 https://github.com/simonw/datasette/blob/8b9d7fdbd8de7e74414cc29e3005382669a812dc/datasette/views/database.py#L215 https://github.com/simonw/datasette/blob/8b9d7fdbd8de7e74414cc29e3005382669a812dc/datasette/views/table.py#L72 I don't think `DatabaseView` and `DatabaseDownload` should have subclassed that at all, since they don't return a table of data. | {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} | Make detailed notes on how table, query and row views work right now 1657861026 | |
1499462324 | https://github.com/simonw/datasette/issues/2054#issuecomment-1499462324 | https://api.github.com/repos/simonw/datasette/issues/2054 | IC_kwDOBm6k_c5ZX_q0 | simonw 9599 | 2023-04-06T18:31:56Z | 2023-04-06T18:31:56Z | OWNER | The `DataView` class does a LOT of work - mostly involving CSV responses. https://github.com/simonw/datasette/blob/8b9d7fdbd8de7e74414cc29e3005382669a812dc/datasette/views/base.py#L160-L544 It has a `redirect()` method with some complex logic and CORS handling: https://github.com/simonw/datasette/blob/8b9d7fdbd8de7e74414cc29e3005382669a812dc/datasette/views/base.py#L163-L172 It uses this method a lot, which has to be over-ridden in the `TableView` and `RowView` and `QueryView` subclasses: https://github.com/simonw/datasette/blob/8b9d7fdbd8de7e74414cc29e3005382669a812dc/datasette/views/base.py#L174-L175 This method: https://github.com/simonw/datasette/blob/8b9d7fdbd8de7e74414cc29e3005382669a812dc/datasette/views/base.py#L180 Is the bulk of the complexity, because it knows how to both turn a list of SQLite rows into a CSV file but also knows how to call `.data()` repeatedly with different pagination arguments in order to stream CSV back for a large table. The `async def get()` method for GET requests is also very complicated. It mainly handles format stuff - knowing how to render HTML v.s. JSON v.s. CSV v.s. other formats specified using this plugin hook: https://docs.datasette.io/en/1.0a2/plugin_hooks.html#register-output-renderer-datasette Plus it catches interrupted queries and returns a special error page for those (and other error messages too): https://github.com/simonw/datasette/blob/8b9d7fdbd8de7e74414cc29e3005382669a812dc/datasette/views/base.py#L381-L408 It adds the time taken to execute the queries: https://github.com/simonw/datasette/blob/8b9d7fdbd8de7e74414cc29e3005382669a812dc/datasette/views/base.py#L410-L411 | {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} | Make detailed notes on how table, query and row views work right now 1657861026 | |
1499457291 | https://github.com/simonw/datasette/issues/2054#issuecomment-1499457291 | https://api.github.com/repos/simonw/datasette/issues/2054 | IC_kwDOBm6k_c5ZX-cL | simonw 9599 | 2023-04-06T18:26:45Z | 2023-04-06T18:26:45Z | OWNER | Here's `BaseView`: https://github.com/simonw/datasette/blob/8b9d7fdbd8de7e74414cc29e3005382669a812dc/datasette/views/base.py#L56-L145 It has methods for the `options`, `get`, `post`, `delete`, `put`, `patch` and `head` HTTP verbs, most defaulting to returinng a 405 Method not allowed message in plain text or JSON, depending on this check: https://github.com/simonw/datasette/blob/8b9d7fdbd8de7e74414cc29e3005382669a812dc/datasette/views/base.py#L71-L81 Also adds CORS headers to anything if CORS mode is on: https://github.com/simonw/datasette/blob/8b9d7fdbd8de7e74414cc29e3005382669a812dc/datasette/views/base.py#L106-L107 And adds the `database_color` (weirdly) and the `select_templates` variables to the template context: https://github.com/simonw/datasette/blob/8b9d7fdbd8de7e74414cc29e3005382669a812dc/datasette/views/base.py#L112-L122 And has special code for setting the `Link: ...; rel="alternate"` HTTP header: https://github.com/simonw/datasette/blob/8b9d7fdbd8de7e74414cc29e3005382669a812dc/datasette/views/base.py#L124-L136 | {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} | Make detailed notes on how table, query and row views work right now 1657861026 | |
1499457201 | https://github.com/simonw/datasette/issues/2054#issuecomment-1499457201 | https://api.github.com/repos/simonw/datasette/issues/2054 | IC_kwDOBm6k_c5ZX-ax | simonw 9599 | 2023-04-06T18:26:39Z | 2023-04-06T18:26:39Z | OWNER | These classes - `TableView` and `RowView` and `QueryView` - all subclass `DataView` which subclasses` BaseView`. | {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} | Make detailed notes on how table, query and row views work right now 1657861026 | |
1499452122 | https://github.com/simonw/datasette/issues/2054#issuecomment-1499452122 | https://api.github.com/repos/simonw/datasette/issues/2054 | IC_kwDOBm6k_c5ZX9La | simonw 9599 | 2023-04-06T18:21:51Z | 2023-04-06T18:21:51Z | OWNER | I'm going to make notes against the code in the most recent alpha release, ignoring the recent work I did to refactor `TableView`. https://github.com/simonw/datasette/tree/1.0a2/datasette/views | {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} | Make detailed notes on how table, query and row views work right now 1657861026 | |
1498279469 | https://github.com/simonw/datasette/pull/2053#issuecomment-1498279469 | https://api.github.com/repos/simonw/datasette/issues/2053 | IC_kwDOBm6k_c5ZTe4t | simonw 9599 | 2023-04-05T23:28:53Z | 2023-04-05T23:28:53Z | OWNER | Table errors page currently does this: ```json { "ok": false, "error": "no such column: blah", "status": 400, "title": "Invalid SQL" } ``` | {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} | WIP new JSON for queries 1656432059 | |
1498275621 | https://github.com/simonw/datasette/issues/2049#issuecomment-1498275621 | https://api.github.com/repos/simonw/datasette/issues/2049 | IC_kwDOBm6k_c5ZTd8l | simonw 9599 | 2023-04-05T23:23:01Z | 2023-04-05T23:23:01Z | OWNER | The default representation here can be even smaller. For rows it's this: ```json { "ok": true, "next": "d,v", "rows": [...] } ``` For SQL queries I'm considering this: ```json { "ok": true, "rows": [...] } ``` I considered adding `"sql"` and `"params"` too, but on further thought those would be entirely a waste of bytes the majority of the time. If a user wants those they can request them with an `?_extra=query` as seen here: http://localhost:8001/content/releases.json?_size=0&_extra=query ```json { "ok": true, "next": null, "query": { "sql": "select html_url, id, author, node_id, tag_name, target_commitish, name, draft, prerelease, created_at, published_at, body, repo, reactions, mentions_count from releases order by id limit 1", "params": {} }, "rows": [] } ``` | {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} | Custom SQL queries should use new JSON ?_extra= format 1646734246 | |
1498167714 | https://github.com/dogsheep/github-to-sqlite/issues/79#issuecomment-1498167714 | https://api.github.com/repos/dogsheep/github-to-sqlite/issues/79 | IC_kwDODFdgUs5ZTDmi | simonw 9599 | 2023-04-05T21:12:55Z | 2023-04-05T21:12:55Z | MEMBER | It's a rate limiting problem: https://github.com/dogsheep/github-to-sqlite/actions/runs/4622674009/jobs/8175633155 ``` File "/home/runner/work/github-to-sqlite/github-to-sqlite/github_to_sqlite/cli.py", line 407, in commits utils.save_commits(db, commits, repo_full["id"]) File "/home/runner/work/github-to-sqlite/github-to-sqlite/github_to_sqlite/utils.py", line 635, in save_commits for commit in commits: File "/home/runner/work/github-to-sqlite/github-to-sqlite/github_to_sqlite/utils.py", line 417, in fetch_commits for commits in paginate(url, headers): File "/home/runner/work/github-to-sqlite/github-to-sqlite/github_to_sqlite/utils.py", line 478, in paginate raise GitHubError.from_response(response) github_to_sqlite.utils.GitHubError: ('API rate limit exceeded for user ID 9599.', 403) Error: Process completed with exit code 1. ``` | {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} | Deploy demo job is failing due to rate limit 1570375808 | |
1495780111 | https://github.com/simonw/sqlite-utils/issues/235#issuecomment-1495780111 | https://api.github.com/repos/simonw/sqlite-utils/issues/235 | IC_kwDOCGYnMM5ZJ8sP | Thomascountz 19786848 | 2023-04-04T11:09:56Z | 2023-04-04T11:13:40Z | NONE | @wpears' workaround also worked for me, but also required me to manually set `PRAGMA writable_schema`. ```sql PRAGMA writable_schema = 1; UPDATE sqlite_master SET sql = 'CREATE TABLE [foos] (...)' PRAGMA writable_schema = 0; ``` ```shell $ python --version Python 3.11.2 $ sqlite3 --version 3.41.2 2023-03-22 11:56:21 0d1fc92f94cb6b76bffe3ec34d69cffde2924203304e8ffc4155597af0c191da $ sqlite-utils --version sqlite-utils, version 3.30 ``` | {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} | Extract columns cannot create foreign key relation: sqlite3.OperationalError: table sqlite_master may not be modified 810618495 | |
1493442956 | https://github.com/dogsheep/apple-notes-to-sqlite/issues/6#issuecomment-1493442956 | https://api.github.com/repos/dogsheep/apple-notes-to-sqlite/issues/6 | IC_kwDOJHON9s5ZBCGM | amlestin 14314871 | 2023-04-02T21:20:43Z | 2023-04-02T21:25:37Z | NONE | I'm experiencing something similar. My apostrophes (') turn into (’) and the output is truncated. Hoping to debug next weekend <img width="814" alt="Screenshot 2023-04-02 at 4 24 10 PM" src="https://user-images.githubusercontent.com/14314871/229379762-f622205a-7bba-4598-b0da-a6b86e5c0a44.png"> | {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} | Character encoding problem 1617602868 | |
1493052396 | https://github.com/simonw/sqlite-utils/issues/265#issuecomment-1493052396 | https://api.github.com/repos/simonw/sqlite-utils/issues/265 | IC_kwDOCGYnMM5Y_ivs | dracos 154364 | 2023-04-01T17:27:18Z | 2023-04-01T17:27:18Z | NONE | `enable_fts` is a function in datasette, not in this repo, which doesn't do any escaping of search terms. It sounds like from https://docs.datasette.io/en/stable/full_text_search.html#advanced-sqlite-search-queries you might want to enable raw searching, as otherwise it's disabled and everything is escaped by default. | {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} | Using enable_fts before search term 907795562 | |
1493051222 | https://github.com/simonw/sqlite-utils/issues/159#issuecomment-1493051222 | https://api.github.com/repos/simonw/sqlite-utils/issues/159 | IC_kwDOCGYnMM5Y_idW | dracos 154364 | 2023-04-01T17:21:05Z | 2023-04-01T17:21:05Z | NONE | In a related issue, nearly a year later I just stumbled across this again, as I wondered why none of my rebuild-fts were rebuilding. It looks like: disable_fts in db.py commits; enable_fts partly commits except the last step (due to executescript committing a pending transaction); rebuild_fts won't commit unless manually done as above with e.g. a context manager. | {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} | .delete_where() does not auto-commit (unlike .insert() or .upsert()) 702386948 | |
1492777509 | https://github.com/simonw/sqlite-utils/issues/235#issuecomment-1492777509 | https://api.github.com/repos/simonw/sqlite-utils/issues/235 | IC_kwDOCGYnMM5Y-fol | hydrosquall 9020979 | 2023-04-01T01:31:48Z | 2023-04-01T01:31:48Z | NONE | My current workaround is to use this library from a python script instead of as a CLI tool. This lets me set the foreign key constraint at table creation time, instead of trying to modify an existing table. [docs](https://sqlite-utils.datasette.io/en/stable/python-api.html#specifying-foreign-keys) I found this [stackoverflow helpful](https://stackoverflow.com/a/1884841/5129731), as it explained that Sqlite doesn't support modifying existing tables directly. | {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} | Extract columns cannot create foreign key relation: sqlite3.OperationalError: table sqlite_master may not be modified 810618495 | |
1492387771 | https://github.com/simonw/datasette/issues/2050#issuecomment-1492387771 | https://api.github.com/repos/simonw/datasette/issues/2050 | IC_kwDOBm6k_c5Y9Ae7 | simonw 9599 | 2023-03-31T17:59:48Z | 2023-03-31T17:59:48Z | OWNER | Some of the extras from the table view make sense here. A few custom ones make sense too - including this already existing but undocumented one: https://github.com/simonw/datasette/blob/5890a20c374fb0812d88c9b0ef26a838bfa06c76/datasette/views/row.py#L86-L89 | {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} | Row page JSON should use new ?_extra= format 1649791661 | |
1492206593 | https://github.com/simonw/datasette/issues/2035#issuecomment-1492206593 | https://api.github.com/repos/simonw/datasette/issues/2035 | IC_kwDOBm6k_c5Y8UQB | simonw 9599 | 2023-03-31T16:09:08Z | 2023-03-31T16:09:08Z | OWNER | I could ship this as part of: - #2049 | {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} | Potential feature: special support for `?a=1&a=2` on the query page 1615692818 | |
1491357104 | https://github.com/simonw/datasette/issues/1989#issuecomment-1491357104 | https://api.github.com/repos/simonw/datasette/issues/1989 | IC_kwDOBm6k_c5Y5E2w | xavdid 1231935 | 2023-03-31T06:17:23Z | 2023-03-31T06:18:05Z | NONE | I'm running into a similar use case as pax above- I made a `nice` view that just has the data I'm interested in (which doesn't include the `id`, since it's not important in this case). But, by excluding `id` from the view, I can't do fts queries against it because the view has no `id` field to tie to `rowid`: ``` ERROR: conn=<sqlite3.Connection object at 0x106521210>, sql = 'select time, text, permalink, num_children from nice where id in (select rowid from items_fts where items_fts match :search) limit 101', params = {'search': 'whatever'}: no such column: id ``` It works fine when I include `id` in my view, but now my `nice` view is cluttered up. Would be great to hide it permanently in the `config.json`. | {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} | Suggestion: Hiding columns 1531991339 | |
1489530555 | https://github.com/simonw/datasette/issues/2049#issuecomment-1489530555 | https://api.github.com/repos/simonw/datasette/issues/2049 | IC_kwDOBm6k_c5YyG67 | simonw 9599 | 2023-03-30T00:51:27Z | 2023-03-30T00:51:27Z | OWNER | I'd really like to refactor all of the extras functions into a `datasette/extras.py` module. The table ones currently rely a LOT on local variables in scope though, so I would need to rewrite those such that EVERY dependency they take is passed to `asyncinject` explicitly. | {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} | Custom SQL queries should use new JSON ?_extra= format 1646734246 | |
1489530037 | https://github.com/simonw/datasette/issues/2049#issuecomment-1489530037 | https://api.github.com/repos/simonw/datasette/issues/2049 | IC_kwDOBm6k_c5YyGy1 | simonw 9599 | 2023-03-30T00:50:30Z | 2023-03-30T00:50:30Z | OWNER | Two things to consider here: `_shape=` and `_extra=`. Most of the shapes make sense, with the exception of `?_shape=object` since we don't know which column we would use as a primary key. Looking at the (undocumented) list of extras from the table view, here are the ones I think make sense: - `count` - YES - `facet_results` - no - `facets_timed_out` - no - `suggested_facets` - no - `human_description_en` - no - `next_url` - MAYBE - `columns` - YES - `primary_keys` - no - `display_columns` - YES - `display_rows` - YES - `debug` - YES? - `request` - YES - `query` - YES - `metadata` - YES - `extras` - YES - `database` - YES - `table` - no - `database_color` - no? - `table_actions` - no - `filters` - no - `renderers` - YES - `custom_table_templates` - no - `sorted_facet_results` - no - `table_definition` - no - `view_definition` - no - `is_view` - no - `private` - YES - `expandable_columns` - no - `form_hidden_args` - no Just the YES ones: - `count` - this is new - `columns` - `display_columns` - `display_rows` - `debug` - `request` - `query` - `metadata` - `extras` - `database` - `renderers` - `private` The `count` one is interesting - I think I can provide that by optionally running `select count(*) from (inner query)`. It's a new feature though and not one I want to expose on the HTML view since it could result in poor performance - but having it as an extra that API users can opt into may make sense. | {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} | Custom SQL queries should use new JSON ?_extra= format 1646734246 | |
1489526501 | https://github.com/simonw/datasette/issues/2049#issuecomment-1489526501 | https://api.github.com/repos/simonw/datasette/issues/2049 | IC_kwDOBm6k_c5YyF7l | simonw 9599 | 2023-03-30T00:44:05Z | 2023-03-30T00:44:05Z | OWNER | As part of this I should be able to figure out which bits of the new code I wrote for the table view should actually be shared with the query view. That stuff is mostly going to be from this commit: https://github.com/simonw/datasette/commit/d97e82df3c8a3f2e97038d7080167be9bb74a68d Here's the existing QueryView class I need to replace: https://github.com/simonw/datasette/blob/4c1e277edbd783d06840d3f9b20bf00783478ce4/datasette/views/database.py#L215-L532 | {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} | Custom SQL queries should use new JSON ?_extra= format 1646734246 | |
1489306198 | https://github.com/simonw/datasette/pull/2034#issuecomment-1489306198 | https://api.github.com/repos/simonw/datasette/issues/2034 | IC_kwDOBm6k_c5YxQJW | wenhoujx 4370201 | 2023-03-29T20:56:19Z | 2023-03-29T20:56:19Z | NONE | @simonw any idea why the test coverage check fails? | {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} | remove an unused `app` var in cli.py 1613974869 | |
1489110168 | https://github.com/dogsheep/hacker-news-to-sqlite/pull/6#issuecomment-1489110168 | https://api.github.com/repos/dogsheep/hacker-news-to-sqlite/issues/6 | IC_kwDODtX3eM5YwgSY | xavdid 1231935 | 2023-03-29T18:36:16Z | 2023-03-29T18:36:16Z | NONE | @simonw can you take a look when you have a chance? | {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} | Add permalink virtual field to items table 1641117021 | |
1488010837 | https://github.com/simonw/datasette/issues/262#issuecomment-1488010837 | https://api.github.com/repos/simonw/datasette/issues/262 | IC_kwDOBm6k_c5YsT5V | simonw 9599 | 2023-03-29T06:22:21Z | 2023-03-29T06:22:21Z | OWNER | I need to get the arbitrary query page to return the same format. It likely won't have nearly as many extras. | {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} | Add ?_extra= mechanism for requesting extra properties in JSON 323658641 | |
1487999503 | https://github.com/simonw/datasette/pull/2014#issuecomment-1487999503 | https://api.github.com/repos/simonw/datasette/issues/2014 | IC_kwDOBm6k_c5YsRIP | dependabot[bot] 49699333 | 2023-03-29T06:09:11Z | 2023-03-29T06:09:11Z | CONTRIBUTOR | Superseded by #2047. | {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} | Bump black from 22.12.0 to 23.1.0 1566081801 | |
1487998788 | https://github.com/simonw/datasette/pull/2014#issuecomment-1487998788 | https://api.github.com/repos/simonw/datasette/issues/2014 | IC_kwDOBm6k_c5YsQ9E | simonw 9599 | 2023-03-29T06:08:23Z | 2023-03-29T06:08:23Z | OWNER | @dependabot recreate | {"total_count": 1, "+1": 1, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} | Bump black from 22.12.0 to 23.1.0 1566081801 | |
1486944644 | https://github.com/simonw/datasette/pull/2043#issuecomment-1486944644 | https://api.github.com/repos/simonw/datasette/issues/2043 | IC_kwDOBm6k_c5YoPmE | dependabot[bot] 49699333 | 2023-03-28T13:58:20Z | 2023-03-28T13:58:20Z | CONTRIBUTOR | Superseded by #2046. | {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} | Bump furo from 2022.12.7 to 2023.3.23 1639446870 | |
1484277416 | https://github.com/simonw/sqlite-utils/issues/388#issuecomment-1484277416 | https://api.github.com/repos/simonw/sqlite-utils/issues/388 | IC_kwDOCGYnMM5YeEao | simonw 9599 | 2023-03-26T23:43:12Z | 2023-03-26T23:43:12Z | OWNER | Fixed: https://sqlite-utils.datasette.io/en/latest/reference.html | {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} | Link to stable docs from older versions 1114543475 | |
1484276946 | https://github.com/simonw/datasette/issues/1608#issuecomment-1484276946 | https://api.github.com/repos/simonw/datasette/issues/1608 | IC_kwDOBm6k_c5YeETS | simonw 9599 | 2023-03-26T23:41:11Z | 2023-03-26T23:41:11Z | OWNER | It's working again now: https://docs.datasette.io/en/latest/sql_queries.html | {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} | Documentation should clarify /stable/ vs /latest/ 1109808154 | |
1484276302 | https://github.com/simonw/sqlite-utils/issues/388#issuecomment-1484276302 | https://api.github.com/repos/simonw/sqlite-utils/issues/388 | IC_kwDOCGYnMM5YeEJO | simonw 9599 | 2023-03-26T23:39:27Z | 2023-03-26T23:39:27Z | OWNER | Actually final Datasette fix was: ```html+jinja {% block scripts %} {{ super() }} <script> document.addEventListener("DOMContentLoaded", function() { // Show banner linking to /stable/ if this is a /latest/ page if (!/\/latest\//.test(location.pathname)) { return; } var stableUrl = location.pathname.replace("/latest/", "/stable/"); // Check it's not a 404 fetch(stableUrl, { method: "HEAD" }).then((response) => { if (response.status === 200) { var warning = document.createElement("div"); warning.className = "admonition warning"; warning.innerHTML = ` <p class="first admonition-title">Note</p> <p class="last"> This documentation covers the <strong>development version</strong> of Datasette. </p> <p> See <a href="${stableUrl}">this page</a> for the current stable release. </p> `; var mainArticle = document.querySelector("article[role=main]"); mainArticle.insertBefore(warning, mainArticle.firstChild); } }); }); </script> {% endblock %} ``` | {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} | Link to stable docs from older versions 1114543475 | |
1484274796 | https://github.com/simonw/datasette/issues/1608#issuecomment-1484274796 | https://api.github.com/repos/simonw/datasette/issues/1608 | IC_kwDOBm6k_c5YeDxs | simonw 9599 | 2023-03-26T23:38:18Z | 2023-03-26T23:38:18Z | OWNER | ChatGPT prompt: > ``` > jQuery(function ($) { > // Show banner linking to /stable/ if this is a /latest/ page > if (!/\/latest\//.test(location.pathname)) { > return; > } > var stableUrl = location.pathname.replace("/latest/", "/stable/"); > // Check it's not a 404 > fetch(stableUrl, { method: "HEAD" }).then((response) => { > if (response.status == 200) { > var warning = $( > `<div class="admonition warning"> > <p class="first admonition-title">Note</p> > <p class="last"> > This documentation covers the <strong>development version</strong> of Datasette.</p> > <p>See <a href="${stableUrl}">this page</a> for the current stable release. > </p> > </div>` > ); > warning.find("a").attr("href", stableUrl); > $("article[role=main]").prepend(warning); > } > }); > }); > > Rewrite this to use vanilla JavaScript, no jQuery > ``` Got back: ```javascript document.addEventListener("DOMContentLoaded", function() { // Show banner linking to /stable/ if this is a /latest/ page if (!/\/latest\//.test(location.pathname)) { return; } var stableUrl = location.pathname.replace("/latest/", "/stable/"); // Check it's not a 404 fetch(stableUrl, { method: "HEAD" }).then((response) => { if (response.status === 200) { var warning = document.createElement("div"); warning.className = "admonition warning"; warning.innerHTML = ` <p class="first admonition-title">Note</p> <p class="last"> This documentation covers the <strong>development version</strong> of Datasette. </p> <p> See <a href="${stableUrl}">this page</a> for the current stable release. </p> `; var mainArticle = document.querySelector("article[role=main]"); mainArticle.insertBefore(warning, mainArticle.firstChild); } }); }); ``` | {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} | Documentation should clarify /stable/ vs /latest/ 1109808154 | |
1484272313 | https://github.com/simonw/datasette/issues/1608#issuecomment-1484272313 | https://api.github.com/repos/simonw/datasette/issues/1608 | IC_kwDOBm6k_c5YeDK5 | simonw 9599 | 2023-03-26T23:36:17Z | 2023-03-26T23:36:17Z | OWNER | Still getting this error: <img width="537" alt="image" src="https://user-images.githubusercontent.com/9599/227811947-a35a6758-cf94-4196-89ce-85ae2f48ab06.png"> Weird because `jQuery` is present in the devtools console. | {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} | Documentation should clarify /stable/ vs /latest/ 1109808154 | |
1484270067 | https://github.com/simonw/datasette/issues/1608#issuecomment-1484270067 | https://api.github.com/repos/simonw/datasette/issues/1608 | IC_kwDOBm6k_c5YeCnz | simonw 9599 | 2023-03-26T23:26:10Z | 2023-03-26T23:27:42Z | OWNER | That didn't work, because `jQuery` isn't yet defined that high up the template. I should use `{% block scripts %}` instead: https://github.com/pradyunsg/furo/blob/05350110cf02d033ebb57147eb54e9371a63545a/src/furo/theme/furo/base.html#L89-L102 | {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} | Documentation should clarify /stable/ vs /latest/ 1109808154 | |
1484269326 | https://github.com/simonw/sqlite-utils/issues/388#issuecomment-1484269326 | https://api.github.com/repos/simonw/sqlite-utils/issues/388 | IC_kwDOCGYnMM5YeCcO | simonw 9599 | 2023-03-26T23:24:12Z | 2023-03-26T23:28:14Z | OWNER | This broke on the upgrade to Furo. I fixed it in Datasette like this: https://github.com/simonw/datasette/commit/5c1cfa451d78e3935193f5e10eba59bf741241a1 and https://github.com/simonw/datasette/commit/db8cf899e286fbaa0a40f3a9ae8d5aaa1478822e | {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} | Link to stable docs from older versions 1114543475 | |
1484268146 | https://github.com/simonw/datasette/issues/1608#issuecomment-1484268146 | https://api.github.com/repos/simonw/datasette/issues/1608 | IC_kwDOBm6k_c5YeCJy | simonw 9599 | 2023-03-26T23:23:22Z | 2023-03-26T23:23:22Z | OWNER | This broke when I upgraded to the Furo theme. | {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} | Documentation should clarify /stable/ vs /latest/ 1109808154 |
Advanced export
JSON shape: default, array, newline-delimited, object
CREATE TABLE [issue_comments] ( [html_url] TEXT, [issue_url] TEXT, [id] INTEGER PRIMARY KEY, [node_id] TEXT, [user] INTEGER REFERENCES [users]([id]), [created_at] TEXT, [updated_at] TEXT, [author_association] TEXT, [body] TEXT, [reactions] TEXT, [issue] INTEGER REFERENCES [issues]([id]) , [performed_via_github_app] TEXT); CREATE INDEX [idx_issue_comments_issue] ON [issue_comments] ([issue]); CREATE INDEX [idx_issue_comments_user] ON [issue_comments] ([user]);
reactions 20 ✖