{"sha": "12f7e1dc5624d14f644abead18bd90b420b6d97e", "message": "Hashed URLs now have far-future cache expiry\n\nSince the URL now includes a hash of the database, we can return a Cache-\nControl: max-age=31536000 header for every response.\n\nThe exception is our 302 redirects. These we now serve with a Link: header\nthat tells any HTTP/2 server-push aware fronting proxies (such as Cloudfront)\nto push the target of the redirect.\n\nCloses #4", "author_date": "2017-10-24T02:36:44Z", "committer_date": "2017-10-24T02:36:44Z", "raw_author": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "raw_committer": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "repo": {"value": 107914493, "label": "datasette"}, "author": {"value": 9599, "label": "simonw"}, "committer": {"value": 9599, "label": "simonw"}} {"sha": "195a5b36349d0d24a6bbb758cebb719b6de303b6", "message": "Heroku --include-vcs-ignore (#407)\n\nMeans `datasette publish heroku` can work under Travis, unlike this failure:\r\n\r\nhttps://travis-ci.org/simonw/fivethirtyeight-datasette/builds/488047550\r\n\r\n```\r\n2.25s$ datasette publish heroku fivethirtyeight.db -m metadata.json -n fivethirtyeight-datasette\r\ntar: unrecognized option '--exclude-vcs-ignores'\r\nTry 'tar --help' or 'tar --usage' for more information.\r\n \u25b8 Command failed: tar cz -C /tmp/tmpuaxm7i8f --exclude-vcs-ignores --exclude\r\n \u25b8 .git --exclude .gitmodules . >\r\n \u25b8 /tmp/f49440e0-1bf3-4d3f-9eb0-fbc2967d1fd4.tar.gz\r\n \u25b8 tar: unrecognized option '--exclude-vcs-ignores'\r\n \u25b8 Try 'tar --help' or 'tar --usage' for more information.\r\n \u25b8 \r\nThe command \"datasette publish heroku fivethirtyeight.db -m metadata.json -n fivethirtyeight-datasette\" exited with 0.\r\n```\r\n\r\nThe fix for that issue is to call the heroku command like this:\r\n\r\n heroku builds:create -a app_name --include-vcs-ignore", "author_date": "2019-02-06T04:15:46Z", "committer_date": "2019-02-06T04:15:46Z", "raw_author": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "raw_committer": {"value": "cd792325681cbad9f663f2879d8b69f1edbb678f", "label": "GitHub"}, "repo": {"value": 107914493, "label": "datasette"}, "author": {"value": 9599, "label": "simonw"}, "committer": {"value": 19864447, "label": "web-flow"}} {"sha": "65e350ca2a4845c25752a62c16ba58cfe2c14b9b", "message": "Implemented 'datasette publish one.db two.db' command\n\nCloses #26", "author_date": "2017-11-11T07:25:22Z", "committer_date": "2017-11-11T07:25:22Z", "raw_author": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "raw_committer": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "repo": {"value": 107914493, "label": "datasette"}, "author": {"value": 9599, "label": "simonw"}, "committer": {"value": 9599, "label": "simonw"}} {"sha": "21c9c04310dffcdb8cf6fee0f74fc9e7ac1ecf19", "message": "Implemented cursor-based pagination for table view\n\nCloses #5", "author_date": "2017-11-10T20:41:14Z", "committer_date": "2017-11-10T20:41:14Z", "raw_author": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "raw_committer": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "repo": {"value": 107914493, "label": "datasette"}, "author": {"value": 9599, "label": "simonw"}, "committer": {"value": 9599, "label": "simonw"}} {"sha": "59580d02da80eb963d5bce897c539c6489042025", "message": "Implemented custom SQL via textarea\n\nCloses #65", "author_date": "2017-11-12T02:35:35Z", "committer_date": "2017-11-12T02:35:35Z", "raw_author": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "raw_committer": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "repo": {"value": 107914493, "label": "datasette"}, "author": {"value": 9599, "label": "simonw"}, "committer": {"value": 9599, "label": "simonw"}} {"sha": "2a9799bae651558a23ae5074edad7cc13ff0fbdc", "message": "Implemented database summary on index page\n\nCloses #41", "author_date": "2017-10-27T04:05:13Z", "committer_date": "2017-10-27T04:05:17Z", "raw_author": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "raw_committer": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "repo": {"value": 107914493, "label": "datasette"}, "author": {"value": 9599, "label": "simonw"}, "committer": {"value": 9599, "label": "simonw"}} {"sha": "b2372605d63248f422b6e67cb5c392236a3aa612", "message": "Implemented multi-db support plus initial URL structure\n\nRefs #24\n\nFixes #15", "author_date": "2017-10-24T02:00:37Z", "committer_date": "2017-10-24T02:00:37Z", "raw_author": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "raw_committer": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "repo": {"value": 107914493, "label": "datasette"}, "author": {"value": 9599, "label": "simonw"}, "committer": {"value": 9599, "label": "simonw"}} {"sha": "fd3a33989aaf2533c4928de3b251c24614003f1e", "message": "Implemented new database view and template\n\nCloses #53 - see comments there for screenshots.", "author_date": "2017-11-12T01:50:21Z", "committer_date": "2017-11-12T01:50:21Z", "raw_author": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "raw_committer": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "repo": {"value": 107914493, "label": "datasette"}, "author": {"value": 9599, "label": "simonw"}, "committer": {"value": 9599, "label": "simonw"}} {"sha": "847f3e0c92b5ac17200b2090bedcc5443bb08e4b", "message": "Implemented offset/limit pagination for views\n\nCloses #70", "author_date": "2017-11-13T21:10:55Z", "committer_date": "2017-11-13T21:10:55Z", "raw_author": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "raw_committer": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "repo": {"value": 107914493, "label": "datasette"}, "author": {"value": 9599, "label": "simonw"}, "committer": {"value": 9599, "label": "simonw"}} {"sha": "7d81083d40fb2749be897d89c9a094d6521ef20c", "message": "Implemented responsive tables, removed bootstrap\n\nNo need for all of bootstrap since we only need to style a few elements.\n\nImplemented responsive table pattern from here:\nhttps://css-tricks.com/responsive-data-tables/\n\nRefs #16", "author_date": "2017-11-11T05:55:50Z", "committer_date": "2017-11-11T05:55:50Z", "raw_author": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "raw_committer": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "repo": {"value": 107914493, "label": "datasette"}, "author": {"value": 9599, "label": "simonw"}, "committer": {"value": 9599, "label": "simonw"}} {"sha": "b20d7119e4f6506cdb9d5d11322e28130823adfd", "message": "Implemented template inheritance and brought back errors", "author_date": "2017-10-24T02:56:27Z", "committer_date": "2017-10-24T02:56:27Z", "raw_author": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "raw_committer": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "repo": {"value": 107914493, "label": "datasette"}, "author": {"value": 9599, "label": "simonw"}, "committer": {"value": 9599, "label": "simonw"}} {"sha": "666aa032530189d585dd61d0e9851e9fe63ee598", "message": "Improved error handling\n\nInvalid SQL now shows a special error.html template, and is covered by tests.", "author_date": "2017-11-12T21:16:15Z", "committer_date": "2017-11-12T21:16:15Z", "raw_author": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "raw_committer": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "repo": {"value": 107914493, "label": "datasette"}, "author": {"value": 9599, "label": "simonw"}, "committer": {"value": 9599, "label": "simonw"}} {"sha": "7dac1c05cd40f89a5af34763e4d5614c750575c2", "message": "Improved pagination\n\nCloses #78", "author_date": "2017-11-13T20:34:56Z", "committer_date": "2017-11-13T20:34:56Z", "raw_author": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "raw_committer": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "repo": {"value": 107914493, "label": "datasette"}, "author": {"value": 9599, "label": "simonw"}, "committer": {"value": 9599, "label": "simonw"}} {"sha": "a4af532a31ece7095d710a1f5abb39ea93fe003f", "message": "Include foreign key info in inspect() output\n\nRefs #85", "author_date": "2017-11-16T01:34:32Z", "committer_date": "2017-11-16T01:34:32Z", "raw_author": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "raw_committer": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "repo": {"value": 107914493, "label": "datasette"}, "author": {"value": 9599, "label": "simonw"}, "committer": {"value": 9599, "label": "simonw"}} {"sha": "4fec50597a8684756bc96d4a69b6fab809ec6cf6", "message": "Include license/source in JSON output if provided", "author_date": "2017-11-13T18:39:25Z", "committer_date": "2017-11-13T18:39:25Z", "raw_author": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "raw_committer": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "repo": {"value": 107914493, "label": "datasette"}, "author": {"value": 9599, "label": "simonw"}, "committer": {"value": 9599, "label": "simonw"}} {"sha": "c371f06fdea413cfb00aa8f81b7a5535a7ecdbc4", "message": "Include took_ms in JSON output", "author_date": "2017-10-24T23:55:53Z", "committer_date": "2017-10-24T23:55:53Z", "raw_author": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "raw_committer": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "repo": {"value": 107914493, "label": "datasette"}, "author": {"value": 9599, "label": "simonw"}, "committer": {"value": 9599, "label": "simonw"}} {"sha": "2f34da0ab2594d917e14fd0dd90ad07872941b8d", "message": "Initial", "author_date": "2018-07-14T03:56:21Z", "committer_date": "2018-07-14T03:56:21Z", "raw_author": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "raw_committer": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "repo": {"value": 140912432, "label": "sqlite-utils"}, "author": {"value": 9599, "label": "simonw"}, "committer": {"value": 9599, "label": "simonw"}} {"sha": "ac9d66817d6a08b806f8e4bc16da02fbdb430496", "message": "Initial commit", "author_date": "2017-10-23T00:39:03Z", "committer_date": "2017-10-23T00:39:03Z", "raw_author": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "raw_committer": {"value": "cd792325681cbad9f663f2879d8b69f1edbb678f", "label": "GitHub"}, "repo": {"value": 107914493, "label": "datasette"}, "author": {"value": 9599, "label": "simonw"}, "committer": {"value": 19864447, "label": "web-flow"}} {"sha": "bd71be32abead38ec0b69695347219024efea0fe", "message": "Initial project layout + database table creation tools", "author_date": "2018-07-28T13:43:18Z", "committer_date": "2018-07-28T13:46:17Z", "raw_author": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "raw_committer": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "repo": {"value": 140912432, "label": "sqlite-utils"}, "author": {"value": 9599, "label": "simonw"}, "committer": {"value": 9599, "label": "simonw"}} {"sha": "407795b61217205625f2d4e084afbf69f1db781b", "message": "Initial unit tests against our Sanic app\n\nRefs #50\n\nI had to disable the build metadata function to get these tests to work\nsensibly. I need to completely rethink how that mechanism works.", "author_date": "2017-11-11T17:47:59Z", "committer_date": "2017-11-11T17:47:59Z", "raw_author": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "raw_committer": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "repo": {"value": 107914493, "label": "datasette"}, "author": {"value": 9599, "label": "simonw"}, "committer": {"value": 9599, "label": "simonw"}} {"sha": "de04d7a854d71003ffcf98028eab976a936c2dba", "message": "Initial working proof of concept", "author_date": "2017-10-23T00:41:19Z", "committer_date": "2017-10-23T00:41:19Z", "raw_author": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "raw_committer": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "repo": {"value": 107914493, "label": "datasette"}, "author": {"value": 9599, "label": "simonw"}, "committer": {"value": 9599, "label": "simonw"}} {"sha": "f3445e2d13e2c38bfbf75f35c2aa3e50df0040f1", "message": "Install python3-dev rothar than python-dev", "author_date": "2017-11-17T14:18:49Z", "committer_date": "2017-11-17T14:18:49Z", "raw_author": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "raw_committer": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "repo": {"value": 107914493, "label": "datasette"}, "author": {"value": 9599, "label": "simonw"}, "committer": {"value": 9599, "label": "simonw"}} {"sha": "ad8b5d3bd23a7b306b8843d7de53a7c918ddb74f", "message": "JSON version of our homepage\n\nNow available at http://localhost:8006/.json\n\nTested by tests added in 407795b61217205625f2d4e084afbf69f1db781b", "author_date": "2017-11-11T17:49:47Z", "committer_date": "2017-11-11T17:49:47Z", "raw_author": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "raw_committer": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "repo": {"value": 107914493, "label": "datasette"}, "author": {"value": 9599, "label": "simonw"}, "committer": {"value": 9599, "label": "simonw"}} {"sha": "8252e71da461c425e625e1c3e4ee0bd92ea4cbf0", "message": "Limit on max rows returned, controlled by --max_returned_rows option\n\nIf someone executes 'select * from table' against a table with a million rows\nin it, we could run into problems: just serializing that much data as JSON is\nlikely to lock up the server.\n\nSolution: we now have a hard limit on the maximum number of rows that can be\nreturned by a query. If that limit is exceeded, the server will return a\n`\"truncated\": true` field in the JSON.\n\nThis limit can be optionally controlled by the new `--max_returned_rows`\noption. Setting that option to 0 disables the limit entirely.\n\nCloses #69", "author_date": "2017-11-13T19:33:01Z", "committer_date": "2017-11-13T19:33:01Z", "raw_author": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "raw_committer": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "repo": {"value": 107914493, "label": "datasette"}, "author": {"value": 9599, "label": "simonw"}, "committer": {"value": 9599, "label": "simonw"}} {"sha": "ea0a761303d84bd73f54a1acedc45b01c38b2da0", "message": "Link to documentation from README", "author_date": "2018-04-21T00:20:56Z", "committer_date": "2018-04-21T00:20:56Z", "raw_author": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "raw_committer": {"value": "cd792325681cbad9f663f2879d8b69f1edbb678f", "label": "GitHub"}, "repo": {"value": 107914493, "label": "datasette"}, "author": {"value": 9599, "label": "simonw"}, "committer": {"value": 19864447, "label": "web-flow"}} {"sha": "b46e370ee6126aa2fa85cf789a31da38aed98496", "message": "Link to pages-per-row\n\nCloses #1", "author_date": "2017-10-24T14:10:58Z", "committer_date": "2017-10-24T14:10:58Z", "raw_author": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "raw_committer": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "repo": {"value": 107914493, "label": "datasette"}, "author": {"value": 9599, "label": "simonw"}, "committer": {"value": 9599, "label": "simonw"}} {"sha": "7f44d31782260f859af1de68ac9db29f72cc6d84", "message": "Link to register-of-members-interests tutorial", "author_date": "2018-04-25T17:40:48Z", "committer_date": "2018-04-25T17:40:48Z", "raw_author": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "raw_committer": {"value": "cd792325681cbad9f663f2879d8b69f1edbb678f", "label": "GitHub"}, "repo": {"value": 107914493, "label": "datasette"}, "author": {"value": 9599, "label": "simonw"}, "committer": {"value": 19864447, "label": "web-flow"}} {"sha": "f9c32e717f67b55e5d51bb896adc2dcec4489c2d", "message": "Linked to csvs-to-sqlite", "author_date": "2017-12-06T15:09:56Z", "committer_date": "2017-12-06T15:09:56Z", "raw_author": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "raw_committer": {"value": "cd792325681cbad9f663f2879d8b69f1edbb678f", "label": "GitHub"}, "repo": {"value": 107914493, "label": "datasette"}, "author": {"value": 9599, "label": "simonw"}, "committer": {"value": 19864447, "label": "web-flow"}} {"sha": "741e8f7fe563e18fe9a12ac1ce38157e8c903505", "message": "Make .indexes compatible with older SQLite versions (#1)\n\nOlder SQLite versions return a different set of columns from the PRAGMA we are using.", "author_date": "2018-08-02T15:17:29Z", "committer_date": "2018-08-02T15:17:29Z", "raw_author": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "raw_committer": {"value": "cd792325681cbad9f663f2879d8b69f1edbb678f", "label": "GitHub"}, "repo": {"value": 140912432, "label": "sqlite-utils"}, "author": {"value": 9599, "label": "simonw"}, "committer": {"value": 19864447, "label": "web-flow"}} {"sha": "59a616ca5c99301a254d86ab097b6ce8f7b30fb6", "message": "Move view SQL to bottom of the page\n\nNow consistent with tables", "author_date": "2017-11-12T21:25:34Z", "committer_date": "2017-11-12T21:25:34Z", "raw_author": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "raw_committer": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "repo": {"value": 107914493, "label": "datasette"}, "author": {"value": 9599, "label": "simonw"}, "committer": {"value": 9599, "label": "simonw"}} {"sha": "31b21f5c5e15fc3acab7fabb170c1da71dc3c98c", "message": "Moved all SQLite queries to threads\n\nSQLite operations are blocking, but we're running everything in Sanic, an\nasyncio web framework, so blocking operations are bad - a long-running DB\noperation could hold up the entire server.\n\nInstead, I've moved all SQLite operations into threads. These are managed by a\nconcurrent.futures ThreadPoolExecutor. This means I can run up to X queries in\nparallel, and I can continue to queue up additional incoming HTTP traffic\nwhile the threadpool is busy.\n\nEach thread is responsible for managing its own SQLite connections - one per\ndatabase. These are cached in a threadlocal.\n\nSince we are working with immutable, read-only SQLite databases it should be\nsafe to share SQLite objects across threads. On this assumption I'm using the\ncheck_same_thread=False option. Opening a database connection looks like this:\n\n conn = sqlite3.connect(\n 'file:filename.db?immutable=1',\n uri=True,\n check_same_thread=False,\n )\n\nThe following articles were helpful in figuring this out:\n\n* https://pymotw.com/3/asyncio/executors.html\n* https://marlinux.wordpress.com/2017/05/19/python-3-6-asyncio-sqlalchemy/\n\nCloses #45. Refs #38.", "author_date": "2017-11-05T02:21:44Z", "committer_date": "2017-11-05T02:21:44Z", "raw_author": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "raw_committer": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "repo": {"value": 107914493, "label": "datasette"}, "author": {"value": 9599, "label": "simonw"}, "committer": {"value": 9599, "label": "simonw"}} {"sha": "fcc38b9ff2e4dbb680a4429002767f6df855674b", "message": "Moved fixtures into conftest.py", "author_date": "2018-08-13T00:24:11Z", "committer_date": "2018-08-13T00:25:39Z", "raw_author": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "raw_committer": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "repo": {"value": 140912432, "label": "sqlite-utils"}, "author": {"value": 9599, "label": "simonw"}, "committer": {"value": 9599, "label": "simonw"}} {"sha": "c446e22f34eb56a454c57edf93824d2615b83c0e", "message": "Moved fixtures to fixtures.py, added .schema test", "author_date": "2018-07-31T15:55:24Z", "committer_date": "2018-07-31T15:55:24Z", "raw_author": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "raw_committer": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "repo": {"value": 140912432, "label": "sqlite-utils"}, "author": {"value": 9599, "label": "simonw"}, "committer": {"value": 9599, "label": "simonw"}} {"sha": "b2955d9065ea019500c7d072bcd9d49d1967f051", "message": "New --plugins-dir=plugins/ option (#212)\n\n* New --plugins-dir=plugins/ option\r\n\r\nNew option causing Datasette to load and evaluate all of the Python files in\r\nthe specified directory and register any plugins that are defined in those\r\nfiles.\r\n\r\nThis new option is available for the following commands:\r\n\r\n datasette serve mydb.db --plugins-dir=plugins/\r\n datasette publish now/heroku mydb.db --plugins-dir=plugins/\r\n datasette package mydb.db --plugins-dir=plugins/\r\n\r\n* Unit tests for --plugins-dir=plugins/\r\n\r\nCloses #211", "author_date": "2018-04-16T05:22:01Z", "committer_date": "2018-04-16T05:22:01Z", "raw_author": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "raw_committer": {"value": "cd792325681cbad9f663f2879d8b69f1edbb678f", "label": "GitHub"}, "repo": {"value": 107914493, "label": "datasette"}, "author": {"value": 9599, "label": "simonw"}, "committer": {"value": 19864447, "label": "web-flow"}} {"sha": "0abd3abacb309a2bd5913a7a2df4e9256585b1bb", "message": "New ?_shape=objects/object/lists param for JSON API (#192)\n\nNew _shape= parameter replacing old .jsono extension\r\n\r\nNow instead of this:\r\n\r\n\t/database/table.jsono\r\n\r\nWe use the _shape parameter like this:\r\n\r\n\t/database/table.json?_shape=objects\r\n\r\nAlso introduced a new _shape called 'object' which looks like this:\r\n\r\n\t/database/table.json?_shape=object\r\n\r\nReturning an object for the rows key:\r\n\r\n\t...\r\n\t\"rows\": {\r\n\t\t\"pk1\": {\r\n\t\t\t...\r\n\t\t},\r\n\t\t\"pk2\": {\r\n\t\t\t...\r\n\t\t}\r\n\t}\r\n\r\nRefs #122", "author_date": "2018-04-03T14:52:54Z", "committer_date": "2018-04-03T14:52:54Z", "raw_author": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "raw_committer": {"value": "cd792325681cbad9f663f2879d8b69f1edbb678f", "label": "GitHub"}, "repo": {"value": 107914493, "label": "datasette"}, "author": {"value": 9599, "label": "simonw"}, "committer": {"value": 19864447, "label": "web-flow"}} {"sha": "9cb69cbd45ed8fd93190c47060c19abec80bc4ef", "message": "New ?_sql_time_limit_ms=10 argument to database and table page\n\nAllows callers to opt for a lower time limit.\n\nCloses #95", "author_date": "2017-11-15T02:55:10Z", "committer_date": "2017-11-15T02:55:10Z", "raw_author": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "raw_committer": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "repo": {"value": 107914493, "label": "datasette"}, "author": {"value": 9599, "label": "simonw"}, "committer": {"value": 9599, "label": "simonw"}} {"sha": "9eacd30b1d6e3f1bd138fb330cfea4830197cb1d", "message": "New column_order= parameter for setting column order", "author_date": "2018-08-08T23:06:49Z", "committer_date": "2018-08-08T23:06:49Z", "raw_author": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "raw_committer": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "repo": {"value": 140912432, "label": "sqlite-utils"}, "author": {"value": 9599, "label": "simonw"}, "committer": {"value": 9599, "label": "simonw"}} {"sha": "4143e3b45c16cbae5e3e3419ef479a71810e7df3", "message": "New command: datasette package - packages a docker container\n\nExample usage:\n\n datasette package fivethirtyeight.db \\\n --tag fivethirtyeight \\\n --metadata=538-metadata.json\n\nThis will create a temporary directory, generate a Dockerfile, copy in the\nSQLite database and metadata file, then build that as a new docker image and\ntag that in your local Docker repository as fivethirtyeight:latest.\n\nYou can then run the image like so:\n\n docker run -p 8006:8001 fivethirtyeight\n\nThis will expose port 8001 in the container (the default) as port 8006 on your\nhost.\n\nCloses #67", "author_date": "2017-11-13T16:13:38Z", "committer_date": "2017-11-13T16:17:35Z", "raw_author": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "raw_committer": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "repo": {"value": 107914493, "label": "datasette"}, "author": {"value": 9599, "label": "simonw"}, "committer": {"value": 9599, "label": "simonw"}} {"sha": "56623e48da5412b25fb39cc26b9c743b684dd968", "message": "News: Datasette Publish", "author_date": "2018-01-17T15:50:10Z", "committer_date": "2018-01-17T15:50:10Z", "raw_author": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "raw_committer": {"value": "cd792325681cbad9f663f2879d8b69f1edbb678f", "label": "GitHub"}, "repo": {"value": 107914493, "label": "datasette"}, "author": {"value": 9599, "label": "simonw"}, "committer": {"value": 19864447, "label": "web-flow"}} {"sha": "a0bb9da17fb95ac5e3bcd3c8d800d33c25a71bbc", "message": "Now requires DB files to be passed as arguments\n\nRefs #40", "author_date": "2017-11-06T02:24:43Z", "committer_date": "2017-11-06T02:24:43Z", "raw_author": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "raw_committer": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "repo": {"value": 107914493, "label": "datasette"}, "author": {"value": 9599, "label": "simonw"}, "committer": {"value": 9599, "label": "simonw"}} {"sha": "7e0cedae3d920797f6f9411aea90a2b1d86ac9c7", "message": "Now using bootstrap 4 beta\n\nRefs #16", "author_date": "2017-11-06T02:49:07Z", "committer_date": "2017-11-06T02:49:07Z", "raw_author": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "raw_committer": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "repo": {"value": 107914493, "label": "datasette"}, "author": {"value": 9599, "label": "simonw"}, "committer": {"value": 9599, "label": "simonw"}} {"sha": "5deb65f0623bff03421f50d3c61f699b981ae18b", "message": "Now you just 'from sqlite_utils import Database'\n\nPlus fixed ad_id in the Russian ads example in the docs", "author_date": "2018-07-31T03:30:23Z", "committer_date": "2018-07-31T03:30:23Z", "raw_author": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "raw_committer": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "repo": {"value": 140912432, "label": "sqlite-utils"}, "author": {"value": 9599, "label": "simonw"}, "committer": {"value": 9599, "label": "simonw"}} {"sha": "9f47b6e4d80f0f393cf0167a6f48280de6847d1d", "message": "Pin to specific Jinja version\n\nCloses #100", "author_date": "2017-11-16T00:14:07Z", "committer_date": "2017-11-16T00:14:07Z", "raw_author": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "raw_committer": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "repo": {"value": 107914493, "label": "datasette"}, "author": {"value": 9599, "label": "simonw"}, "committer": {"value": 9599, "label": "simonw"}} {"sha": "0d63128c40aec15a958dddf181c13e0db1c7908b", "message": "Preparing v0.2, first release to PyPI", "author_date": "2018-07-29T00:42:41Z", "committer_date": "2018-07-29T00:42:41Z", "raw_author": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "raw_committer": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "repo": {"value": 140912432, "label": "sqlite-utils"}, "author": {"value": 9599, "label": "simonw"}, "committer": {"value": 9599, "label": "simonw"}} {"sha": "f1b0521810bbc467721e4dcc5a2ff1bf2a1ddbb8", "message": "Preserve .json through redirects", "author_date": "2017-10-25T15:01:22Z", "committer_date": "2017-10-25T15:01:22Z", "raw_author": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "raw_committer": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "repo": {"value": 107914493, "label": "datasette"}, "author": {"value": 9599, "label": "simonw"}, "committer": {"value": 9599, "label": "simonw"}} {"sha": "67ad77a307c7c264c68d768fa8290997e3b75e77", "message": "Re-ordered docs index page", "author_date": "2017-12-06T18:27:50Z", "committer_date": "2017-12-06T18:27:50Z", "raw_author": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "raw_committer": {"value": "cd792325681cbad9f663f2879d8b69f1edbb678f", "label": "GitHub"}, "repo": {"value": 107914493, "label": "datasette"}, "author": {"value": 9599, "label": "simonw"}, "committer": {"value": 19864447, "label": "web-flow"}} {"sha": "02b1814fcfdc61b1b69b5955f2b60252ff10cde9", "message": "Redirects now preserve query string\n\nFixes #28", "author_date": "2017-10-24T23:54:26Z", "committer_date": "2017-10-24T23:54:26Z", "raw_author": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "raw_committer": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "repo": {"value": 107914493, "label": "datasette"}, "author": {"value": 9599, "label": "simonw"}, "committer": {"value": 9599, "label": "simonw"}} {"sha": "1fc75809a6aa17860944b4cc3a4d7175cd53b1f4", "message": "Refactored everything into a factory function\n\nI now call a factory function to construct the Sanic app:\n\n app = app_factory(files)\n\nThis allows me to pass additional arguments to it, e.g. the files to serve.\n\nAlso refactored my class-based views to accept jinja as an argument, e.g:\n\n app.add_route(\n TableView.as_view(jinja),\n '//'\n )", "author_date": "2017-11-05T02:13:44Z", "committer_date": "2017-11-05T02:13:44Z", "raw_author": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "raw_committer": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "repo": {"value": 107914493, "label": "datasette"}, "author": {"value": 9599, "label": "simonw"}, "committer": {"value": 9599, "label": "simonw"}} {"sha": "e16ca1169cc49fbb5b0325564d248becad3a4b7f", "message": "Refactored table column/row display logic\n\nSimplified the template and made the way for upcoming foreign key work.\n\nRefs #85\n\nAlso fixed   bug on database page - closes #113", "author_date": "2017-11-17T15:39:36Z", "committer_date": "2017-11-17T15:39:36Z", "raw_author": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "raw_committer": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "repo": {"value": 107914493, "label": "datasette"}, "author": {"value": 9599, "label": "simonw"}, "committer": {"value": 9599, "label": "simonw"}} {"sha": "40d3b3eae68286f67e40226f18f2621b26e5e533", "message": "Refactored tests into new tests/ folder\n\nGuided by https://docs.pytest.org/en/latest/goodpractices.html", "author_date": "2017-11-10T18:48:16Z", "committer_date": "2017-11-10T18:48:16Z", "raw_author": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "raw_committer": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "repo": {"value": 107914493, "label": "datasette"}, "author": {"value": 9599, "label": "simonw"}, "committer": {"value": 9599, "label": "simonw"}} {"sha": "9d219140694551453bfa528e0624919eb065f9d6", "message": "Refactored to use class based views\n\nCloses #22", "author_date": "2017-10-24T02:25:48Z", "committer_date": "2017-10-24T02:25:48Z", "raw_author": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "raw_committer": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "repo": {"value": 107914493, "label": "datasette"}, "author": {"value": 9599, "label": "simonw"}, "committer": {"value": 9599, "label": "simonw"}} {"sha": "a8a293cd71f7529aff374be5ca01f2ebd5e71ee4", "message": "Refactored util functions into new utils module", "author_date": "2017-11-10T19:25:54Z", "committer_date": "2017-11-10T19:25:54Z", "raw_author": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "raw_committer": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "repo": {"value": 107914493, "label": "datasette"}, "author": {"value": 9599, "label": "simonw"}, "committer": {"value": 9599, "label": "simonw"}} {"sha": "f5418e13f2e435a42cd3611b28ec3c9ac02481da", "message": "Release 0.3.1 to publish updated README to PyPI", "author_date": "2018-07-31T15:39:43Z", "committer_date": "2018-07-31T15:39:43Z", "raw_author": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "raw_committer": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "repo": {"value": 140912432, "label": "sqlite-utils"}, "author": {"value": 9599, "label": "simonw"}, "committer": {"value": 9599, "label": "simonw"}} {"sha": "d75f423b6fcfc074b7c6f8f7679da8876f181edd", "message": "Release 0.9", "author_date": "2017-11-13T22:00:39Z", "committer_date": "2017-11-13T22:00:53Z", "raw_author": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "raw_committer": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "repo": {"value": 107914493, "label": "datasette"}, "author": {"value": 9599, "label": "simonw"}, "committer": {"value": 9599, "label": "simonw"}} {"sha": "0d3479ba320e5a5d15f029838744c5219a9e2987", "message": "Release notes for 0.13", "author_date": "2017-11-25T03:32:24Z", "committer_date": "2017-11-25T03:32:24Z", "raw_author": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "raw_committer": {"value": "cd792325681cbad9f663f2879d8b69f1edbb678f", "label": "GitHub"}, "repo": {"value": 107914493, "label": "datasette"}, "author": {"value": 9599, "label": "simonw"}, "committer": {"value": 19864447, "label": "web-flow"}} {"sha": "6b3b05b6db0d2a7b7cec8b8dbb4ddc5e12a376b2", "message": "Released 0.7", "author_date": "2017-11-13T18:42:30Z", "committer_date": "2017-11-13T18:42:30Z", "raw_author": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "raw_committer": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "repo": {"value": 107914493, "label": "datasette"}, "author": {"value": 9599, "label": "simonw"}, "committer": {"value": 9599, "label": "simonw"}} {"sha": "d76412668f8c12572eb7de57ccb72f1e50306177", "message": "Removed rogue middot", "author_date": "2017-11-13T20:34:39Z", "committer_date": "2017-11-13T20:34:39Z", "raw_author": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "raw_committer": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "repo": {"value": 107914493, "label": "datasette"}, "author": {"value": 9599, "label": "simonw"}, "committer": {"value": 9599, "label": "simonw"}} {"sha": "25c241fa5a0f8868e3c1bc5be4f5888caa47d864", "message": "Renamed project to immutabase", "author_date": "2017-11-06T02:32:13Z", "committer_date": "2017-11-06T02:32:13Z", "raw_author": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "raw_committer": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "repo": {"value": 107914493, "label": "datasette"}, "author": {"value": 9599, "label": "simonw"}, "committer": {"value": 9599, "label": "simonw"}} {"sha": "e7e50875d341f1d26b4dbba862f5202631f34896", "message": "Renamed to 'datasette'", "author_date": "2017-11-10T18:38:35Z", "committer_date": "2017-11-10T18:38:35Z", "raw_author": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "raw_committer": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "repo": {"value": 107914493, "label": "datasette"}, "author": {"value": 9599, "label": "simonw"}, "committer": {"value": 9599, "label": "simonw"}} {"sha": "1c57bd202fb1f82e14c47dfca63454352999732c", "message": "Replaced app_factory with new Datasette class\n\nThis should make it easier to add unit tests.", "author_date": "2017-11-10T19:05:57Z", "committer_date": "2017-11-10T19:05:57Z", "raw_author": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "raw_committer": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "repo": {"value": 107914493, "label": "datasette"}, "author": {"value": 9599, "label": "simonw"}, "committer": {"value": 9599, "label": "simonw"}} {"sha": "e9e1def4c0cc49c96ed0b0d2bbc3ae81353ed2bb", "message": "Revised JSON design a bit\n\nCloses #63", "author_date": "2017-11-11T22:20:00Z", "committer_date": "2017-11-11T22:20:00Z", "raw_author": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "raw_committer": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "repo": {"value": 107914493, "label": "datasette"}, "author": {"value": 9599, "label": "simonw"}, "committer": {"value": 9599, "label": "simonw"}} {"sha": "40a563ebac72f46a1b2dc498a25520c429bca6d6", "message": "Reworked metadata building options\n\nBuilding metadata is now optional. If you want to do it, do this:\n\n datasette build *.db --metadata=metadata.json\n\nThen when you run the server you can tell it to read from metadata:\n\n datasette serve *.db --metadata=metadata.json\n\nThe Dockerfile generated by datasette publish now uses this mechanism.\n\nCloses #60", "author_date": "2017-11-11T20:10:51Z", "committer_date": "2017-11-11T20:11:51Z", "raw_author": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "raw_committer": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "repo": {"value": 107914493, "label": "datasette"}, "author": {"value": 9599, "label": "simonw"}, "committer": {"value": 9599, "label": "simonw"}} {"sha": "6a007f632258e6cfd3c5e9e229683deb0efd87be", "message": "Row pages show incoming foreign key relationships", "author_date": "2017-11-17T18:15:44Z", "committer_date": "2017-11-18T03:15:49Z", "raw_author": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "raw_committer": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "repo": {"value": 107914493, "label": "datasette"}, "author": {"value": 9599, "label": "simonw"}, "committer": {"value": 9599, "label": "simonw"}} {"sha": "3a944d0c077c203277f13dd69387eb84b5c88d3e", "message": "Run Travis tests against Python 3.8-dev (#5)", "author_date": "2019-01-26T02:37:54Z", "committer_date": "2019-01-26T02:37:54Z", "raw_author": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "raw_committer": {"value": "cd792325681cbad9f663f2879d8b69f1edbb678f", "label": "GitHub"}, "repo": {"value": 140912432, "label": "sqlite-utils"}, "author": {"value": 9599, "label": "simonw"}, "committer": {"value": 19864447, "label": "web-flow"}} {"sha": "fa8eb0bf1b113ab17ede9cd107b7c3bd5cde39c3", "message": "Run unit tests against both Python 3.5 and 3.6", "author_date": "2017-11-22T17:43:52Z", "committer_date": "2017-11-22T17:43:52Z", "raw_author": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "raw_committer": {"value": "cd792325681cbad9f663f2879d8b69f1edbb678f", "label": "GitHub"}, "repo": {"value": 107914493, "label": "datasette"}, "author": {"value": 9599, "label": "simonw"}, "committer": {"value": 19864447, "label": "web-flow"}} {"sha": "28a52fcffb869f5e83ca2fad53738dc25eec425d", "message": "Set theme jekyll-theme-architect", "author_date": "2018-05-24T16:56:21Z", "committer_date": "2018-05-24T16:56:21Z", "raw_author": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "raw_committer": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "repo": {"value": 107914493, "label": "datasette"}, "author": {"value": 9599, "label": "simonw"}, "committer": {"value": 9599, "label": "simonw"}} {"sha": "3d9baf3c2f2f745e6949973f18480092f189116c", "message": "Set theme jekyll-theme-leap-day", "author_date": "2018-05-24T16:55:19Z", "committer_date": "2018-05-24T16:55:19Z", "raw_author": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "raw_committer": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "repo": {"value": 107914493, "label": "datasette"}, "author": {"value": 9599, "label": "simonw"}, "committer": {"value": 9599, "label": "simonw"}} {"sha": "6823b094066c5cb1dcd3581da2ed877ed72298b7", "message": "Set time limit of 1000ms on SQL queries\n\nUsing the (undocumented in the Python docs) fact that if you return 1 from a\nset_progress_handler callback, SQLite will cancel the current query.\n\nCloses #35", "author_date": "2017-10-25T01:34:54Z", "committer_date": "2017-10-25T01:34:54Z", "raw_author": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "raw_committer": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "repo": {"value": 107914493, "label": "datasette"}, "author": {"value": 9599, "label": "simonw"}, "committer": {"value": 9599, "label": "simonw"}} {"sha": "d01370f1660d0b0360248105cd43060dca31f70f", "message": "Show SQL and params if table has them applied", "author_date": "2017-11-12T23:21:39Z", "committer_date": "2017-11-12T23:21:39Z", "raw_author": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "raw_committer": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "repo": {"value": 107914493, "label": "datasette"}, "author": {"value": 9599, "label": "simonw"}, "committer": {"value": 9599, "label": "simonw"}} {"sha": "03c58fb350f6b9bb941a46907da5ac6f67bf47cf", "message": "Show databases in alphabetical order on index page", "author_date": "2017-11-10T19:04:56Z", "committer_date": "2017-11-10T19:04:56Z", "raw_author": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "raw_committer": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "repo": {"value": 107914493, "label": "datasette"}, "author": {"value": 9599, "label": "simonw"}, "committer": {"value": 9599, "label": "simonw"}} {"sha": "bd5f3b2ba1a627383d512d613b77d15501dfccc4", "message": "Show time taken at bottom of table page", "author_date": "2017-10-25T01:31:54Z", "committer_date": "2017-10-25T01:31:54Z", "raw_author": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "raw_committer": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "repo": {"value": 107914493, "label": "datasette"}, "author": {"value": 9599, "label": "simonw"}, "committer": {"value": 9599, "label": "simonw"}} {"sha": "eef213ab4d57622dfc60c8655c0c7a18afcc844f", "message": "Show total number of rows in table", "author_date": "2017-10-25T00:11:36Z", "committer_date": "2017-10-25T00:11:36Z", "raw_author": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "raw_committer": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "repo": {"value": 107914493, "label": "datasette"}, "author": {"value": 9599, "label": "simonw"}, "committer": {"value": 9599, "label": "simonw"}} {"sha": "3eb79e1a5fa4c164a224ae0adbe0ea16fde35758", "message": "Show total row count at top of table page", "author_date": "2017-10-25T01:31:43Z", "committer_date": "2017-10-25T01:31:43Z", "raw_author": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "raw_committer": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "repo": {"value": 107914493, "label": "datasette"}, "author": {"value": 9599, "label": "simonw"}, "committer": {"value": 9599, "label": "simonw"}} {"sha": "47e689a89b3f5f0969595b17d2ec59ea3caffb3b", "message": "Speed up Travis by reusing pip wheel cache across builds (#324)\n\n* Cache pip wheels between runs in Travis, refs #323\r\n* Run pytest manually - \"python setup.py test\" appeared to still download a bunch of stuff: https://travis-ci.org/simonw/datasette/jobs/395306188\r\n\r\n* Use extras_require so pip can install test dependencies: https://github.com/pypa/pip/issues/1197#issuecomment-228939212", "author_date": "2018-06-24T01:03:46Z", "committer_date": "2018-06-24T01:03:46Z", "raw_author": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "raw_committer": {"value": "cd792325681cbad9f663f2879d8b69f1edbb678f", "label": "GitHub"}, "repo": {"value": 107914493, "label": "datasette"}, "author": {"value": 9599, "label": "simonw"}, "committer": {"value": 19864447, "label": "web-flow"}} {"sha": "33c7c53ff87c25445c68088ede49d062d9c31fe8", "message": "Start of the plugin system, based on pluggy (#210)\n\nUses https://pluggy.readthedocs.io/ originally created for the py.test project\r\n\r\nWe're starting with two plugin hooks:\r\n\r\nprepare_connection(conn)\r\n\r\nThis is called when a new SQLite connection is created. It can be used to register custom SQL functions.\r\n\r\nprepare_jinja2_environment(env)\r\n\r\nThis is called with the Jinja2 environment. It can be used to register custom template tags and filters.\r\n\r\nAn example plugin which uses these two hooks can be found at https://github.com/simonw/datasette-plugin-demos or installed using `pip install datasette-plugin-demos`\r\n\r\nRefs #14", "author_date": "2018-04-16T00:56:15Z", "committer_date": "2018-04-16T00:56:15Z", "raw_author": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "raw_committer": {"value": "cd792325681cbad9f663f2879d8b69f1edbb678f", "label": "GitHub"}, "repo": {"value": 107914493, "label": "datasette"}, "author": {"value": 9599, "label": "simonw"}, "committer": {"value": 19864447, "label": "web-flow"}} {"sha": "594b25ef9f633dabdaca98b46dea9fbb82628166", "message": "Started a changelog, releasing 0.6", "author_date": "2018-08-13T00:46:22Z", "committer_date": "2018-08-13T00:46:22Z", "raw_author": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "raw_committer": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "repo": {"value": 140912432, "label": "sqlite-utils"}, "author": {"value": 9599, "label": "simonw"}, "committer": {"value": 9599, "label": "simonw"}} {"sha": "1ae8ea0f03cfb9f25b1e25f3194c456c3649789c", "message": "Started implementing ?name__contains=X filters\n\nSo far we support __contains=, __startswith=, __endswith= and __exact=\n\nRefs #23", "author_date": "2017-10-25T00:06:23Z", "committer_date": "2017-10-25T00:06:23Z", "raw_author": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "raw_committer": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "repo": {"value": 107914493, "label": "datasette"}, "author": {"value": 9599, "label": "simonw"}, "committer": {"value": 9599, "label": "simonw"}} {"sha": "29c897bb5649c35463618a32d095f72755aae8c6", "message": "Started the docs with a meaty example", "author_date": "2018-07-28T23:52:07Z", "committer_date": "2018-07-28T23:52:07Z", "raw_author": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "raw_committer": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "repo": {"value": 140912432, "label": "sqlite-utils"}, "author": {"value": 9599, "label": "simonw"}, "committer": {"value": 9599, "label": "simonw"}} {"sha": "1592fd0419f374de201926d3ba67fbf1522eed13", "message": "Started work on cli, which also meant adding setup.py\n\nI'm using click, and click recommends using a setup.py - so I've added one of\nthose. I also refactored code into a new datasite package. It's not quite\ndeploying to now properly at the moment though - I seem to have messed up the\npath handling a bit.\n\nAlso snuck in a new template for the \"Row\" view.\n\nRefs #40", "author_date": "2017-10-27T07:08:24Z", "committer_date": "2017-10-27T07:08:24Z", "raw_author": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "raw_committer": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "repo": {"value": 107914493, "label": "datasette"}, "author": {"value": 9599, "label": "simonw"}, "committer": {"value": 9599, "label": "simonw"}} {"sha": "44a199a0625b695492b2a8605030dc61191f39cb", "message": "Stop using sqlite WITH RECURSIVE in our tests\n\nThe version of Python 3 running in Travis CI doesn't support this.", "author_date": "2017-11-13T22:15:21Z", "committer_date": "2017-11-13T22:15:21Z", "raw_author": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "raw_committer": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "repo": {"value": 107914493, "label": "datasette"}, "author": {"value": 9599, "label": "simonw"}, "committer": {"value": 9599, "label": "simonw"}} {"sha": "95bce37ad3447d3c265316fa029fc09b7bbdae11", "message": "Store list/dict/tuple values as JSON strings", "author_date": "2018-07-28T22:20:29Z", "committer_date": "2018-07-28T22:20:29Z", "raw_author": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "raw_committer": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "repo": {"value": 140912432, "label": "sqlite-utils"}, "author": {"value": 9599, "label": "simonw"}, "committer": {"value": 9599, "label": "simonw"}} {"sha": "fc3660cfad7668dbce6ead12766e048fc1f78b11", "message": "Streaming mode for downloading all rows as a CSV (#315)\n\n* table.csv?_stream=1 to download all rows - refs #266\r\n\r\nThis option causes Datasette to serve ALL rows in the table, by internally\r\nfollowing the _next= pagination links and serving everything out as a stream.\r\n\r\nAlso added new config option, allow_csv_stream, which can be used to disable\r\nthis feature.\r\n\r\n* New config option max_csv_mb limiting size of CSV export", "author_date": "2018-06-18T03:21:02Z", "committer_date": "2018-06-18T03:21:02Z", "raw_author": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "raw_committer": {"value": "cd792325681cbad9f663f2879d8b69f1edbb678f", "label": "GitHub"}, "repo": {"value": 107914493, "label": "datasette"}, "author": {"value": 9599, "label": "simonw"}, "committer": {"value": 19864447, "label": "web-flow"}} {"sha": "2bbe9ca34a701191e3bf4e97943b7503a50ab548", "message": "Support OPTIONS requests for CORS", "author_date": "2017-11-13T02:11:52Z", "committer_date": "2017-11-13T02:11:52Z", "raw_author": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "raw_committer": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "repo": {"value": 107914493, "label": "datasette"}, "author": {"value": 9599, "label": "simonw"}, "committer": {"value": 9599, "label": "simonw"}} {"sha": "e615d22c5564ea1f32abb086088b2700110be10a", "message": "Support for numpy types, closes #11 (#12)", "author_date": "2019-02-24T04:02:19Z", "committer_date": "2019-02-24T04:02:19Z", "raw_author": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "raw_committer": {"value": "cd792325681cbad9f663f2879d8b69f1edbb678f", "label": "GitHub"}, "repo": {"value": 140912432, "label": "sqlite-utils"}, "author": {"value": 9599, "label": "simonw"}, "committer": {"value": 19864447, "label": "web-flow"}} {"sha": "72644b6e3fc78ecf55b386854943ec3ad39f97bd", "message": "Support method chaining, added .last_id for accessing lastrowid\n\nAlso shipping as 0.5", "author_date": "2018-08-06T01:42:43Z", "committer_date": "2018-08-06T01:42:43Z", "raw_author": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "raw_committer": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "repo": {"value": 140912432, "label": "sqlite-utils"}, "author": {"value": 9599, "label": "simonw"}, "committer": {"value": 9599, "label": "simonw"}} {"sha": "186c513a61a091b9f83d788e25b08f41a84ed9a3", "message": "Support parameterized SQL and block potentially harmful queries\n\nYou can now call arbitrary SQL like this:\n\n /flights?sql=select%20*%20from%20airports%20where%20country%20like%20:c&c=iceland\n\nUnescaped, those querystring params look like this:\n\n sql = select * from airports where country like :c\n c = iceland\n\nSo SQL can be constructed with named parameters embedded in it, which will\nthen be read from the querystring and correctly escaped.\n\nThis means we can aggressively filter the SQL parameter for potentially\ndangerous syntax. For the moment we enforce that it starts with a SELECT\nstatement and we ban the sequence \"pragma\" from it entirely.\n\nIf you need to use pragma in a query, you can use the new named parameter\nmechanism.\n\nFixes #39", "author_date": "2017-11-05T02:49:18Z", "committer_date": "2017-11-05T02:49:18Z", "raw_author": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "raw_committer": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "repo": {"value": 107914493, "label": "datasette"}, "author": {"value": 9599, "label": "simonw"}, "committer": {"value": 9599, "label": "simonw"}} {"sha": "084350b0f1343d988928cae63cfedbeb6205e25e", "message": "Switched to gather_request=False for Sanic tests\n\nGets rid of those ugly _, response = lines.", "author_date": "2017-11-17T14:53:37Z", "committer_date": "2017-11-17T14:53:37Z", "raw_author": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "raw_committer": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "repo": {"value": 107914493, "label": "datasette"}, "author": {"value": 9599, "label": "simonw"}, "committer": {"value": 9599, "label": "simonw"}} {"sha": "22851ed9f0541904f5c3fca7ddbd7add10a75d39", "message": "Table page now shows CREATE TABLE at bottom\n\nCloses #66", "author_date": "2017-11-12T21:16:59Z", "committer_date": "2017-11-12T21:16:59Z", "raw_author": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "raw_committer": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "repo": {"value": 107914493, "label": "datasette"}, "author": {"value": 9599, "label": "simonw"}, "committer": {"value": 9599, "label": "simonw"}} {"sha": "1b04662585ea1539014bfbd616a8112b650d5699", "message": "Table views now show expanded foreign key references, if possible\n\nIf a table has foreign key columns, and those foreign key tables have\nlabel_columns, the TableView will now query those other tables for the\ncorresponding values and display those values as links in the corresponding\ntable cells.\n\nlabel_columns are currently detected by the inspect() function, which looks\nfor any table that has just two columns - an ID column and one other - and\nsets the label_column to be that second non-ID column.", "author_date": "2017-11-18T03:09:32Z", "committer_date": "2017-11-18T03:15:49Z", "raw_author": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "raw_committer": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "repo": {"value": 107914493, "label": "datasette"}, "author": {"value": 9599, "label": "simonw"}, "committer": {"value": 9599, "label": "simonw"}} {"sha": "0b8c1b0a6da9cb8ac0d28cc90dd783de87554036", "message": "Test for sql_time_limit_ms + sqlite_functions mechanism\n\nAdded a unit test for the sql_time_limit_ms option.\n\nTo test this, I needed to add a custom SQLite sleep() function. I've added a\nsimple mechanism to the Datasette class for registering custom functions.\n\nI also had to modify the sqlite_timelimit() function. It makes use of a magic\nvalue, N, which is the number of SQLite virtual machine instructions that\nshould execute in between calls to my termination decision function.\n\nThe value of N was not finely grained enough for my test to work - so I've\nadded logic that says that if the time limit is less than 50ms, N is set to 1.\nThis got the tests working.\n\nRefs #95", "author_date": "2017-11-15T02:41:03Z", "committer_date": "2017-11-15T02:43:34Z", "raw_author": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "raw_committer": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "repo": {"value": 107914493, "label": "datasette"}, "author": {"value": 9599, "label": "simonw"}, "committer": {"value": 9599, "label": "simonw"}} {"sha": "8acdc2fd14c0f7251e1e3fd592c53b3152f5256c", "message": "Test for table with space in name\n\nTests code in b51836f8463ef65bc947f0a7b6e60167cb7154cf", "author_date": "2017-11-12T20:08:32Z", "committer_date": "2017-11-12T20:08:32Z", "raw_author": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "raw_committer": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "repo": {"value": 107914493, "label": "datasette"}, "author": {"value": 9599, "label": "simonw"}, "committer": {"value": 9599, "label": "simonw"}} {"sha": "0e5f51adfeff24a120bbdf0e5ac5669b18124400", "message": "Three more news items", "author_date": "2018-03-30T07:03:45Z", "committer_date": "2018-03-30T07:03:45Z", "raw_author": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "raw_committer": {"value": "cd792325681cbad9f663f2879d8b69f1edbb678f", "label": "GitHub"}, "repo": {"value": 107914493, "label": "datasette"}, "author": {"value": 9599, "label": "simonw"}, "committer": {"value": 19864447, "label": "web-flow"}} {"sha": "82261a638bd35c9d69a9582a898cf4dab374f76c", "message": "Turn on auto-escaping in Jinja\n\nWe had XSS holes! Since we don't do cookies or authentication\nthey shouldn't cause any actual harm, but still really not good.\n\nhttps://github.com/pallets/jinja/issues/528", "author_date": "2017-11-16T01:59:42Z", "committer_date": "2017-11-16T01:59:42Z", "raw_author": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "raw_committer": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "repo": {"value": 107914493, "label": "datasette"}, "author": {"value": 9599, "label": "simonw"}, "committer": {"value": 9599, "label": "simonw"}} {"sha": "70e1f831a00ec97b724187025e35338becd2309a", "message": "Typo", "author_date": "2018-08-01T01:32:03Z", "committer_date": "2018-08-01T01:32:03Z", "raw_author": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "raw_committer": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "repo": {"value": 140912432, "label": "sqlite-utils"}, "author": {"value": 9599, "label": "simonw"}, "committer": {"value": 9599, "label": "simonw"}} {"sha": "6f6d0ff2b41f1cacaf42287b1b230b646bcba9ee", "message": "URL hashing is now off by default - closes #418\n\nPrior to this commit Datasette would calculate the content hash of every\r\ndatabase and redirect to a URL containing that hash, like so:\r\n\r\n https://v0-27.datasette.io/fixtures => https://v0-27.datasette.io/fixtures-dd88475\r\n\r\nThis assumed that all databases were opened in immutable mode and were not\r\nexpected to change.\r\n\r\nThis will be changing as a result of #419 - so this commit takes the first step\r\nin implementing that change by changing this default behaviour. Datasette will\r\nnow only redirect hash-free URLs under two circumstances:\r\n\r\n* The new `hash_urls` config option is set to true (it defaults to false).\r\n* The user passes `?_hash=1` in the URL", "author_date": "2019-03-17T22:55:04Z", "committer_date": "2019-03-17T22:55:04Z", "raw_author": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "raw_committer": {"value": "cd792325681cbad9f663f2879d8b69f1edbb678f", "label": "GitHub"}, "repo": {"value": 107914493, "label": "datasette"}, "author": {"value": 9599, "label": "simonw"}, "committer": {"value": 19864447, "label": "web-flow"}} {"sha": "3cce63b59851495b6d9d38936356e21ea8fbad3a", "message": "URL to allow direct database download\n\nIt's just the database URL with .db on the end, e.g. /flights.db\n\nCloses #19", "author_date": "2017-10-25T15:19:32Z", "committer_date": "2017-10-25T15:19:32Z", "raw_author": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "raw_committer": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "repo": {"value": 107914493, "label": "datasette"}, "author": {"value": 9599, "label": "simonw"}, "committer": {"value": 9599, "label": "simonw"}} {"sha": "3c50a3600d0975b84d98c93bb2336a790afc6aca", "message": "Unit test for black-approved coding style", "author_date": "2018-07-28T14:29:20Z", "committer_date": "2018-07-28T14:29:20Z", "raw_author": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "raw_committer": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "repo": {"value": 140912432, "label": "sqlite-utils"}, "author": {"value": 9599, "label": "simonw"}, "committer": {"value": 9599, "label": "simonw"}} {"sha": "dd4491dd8112d70d96d73f8f1d12b58cb42fe1bd", "message": "Update number of expected tables", "author_date": "2018-04-14T15:03:41Z", "committer_date": "2018-04-14T15:16:54Z", "raw_author": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "raw_committer": {"value": "13ae486343ea6454a93114c6f558ffea2f2c6874", "label": "Simon Willison"}, "repo": {"value": 107914493, "label": "datasette"}, "author": {"value": 9599, "label": "simonw"}, "committer": {"value": 9599, "label": "simonw"}} {"sha": "bf5ec2d61148f9852441934dd206b3b1c07a512f", "message": "Updated PyPI link to pypi.org", "author_date": "2018-04-17T02:24:36Z", "committer_date": "2018-04-17T02:24:36Z", "raw_author": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "raw_committer": {"value": "cd792325681cbad9f663f2879d8b69f1edbb678f", "label": "GitHub"}, "repo": {"value": 107914493, "label": "datasette"}, "author": {"value": 9599, "label": "simonw"}, "committer": {"value": 19864447, "label": "web-flow"}} {"sha": "4f08fc092f59b434c11f77b6fb2d29b3255227e5", "message": "Updated news", "author_date": "2017-12-12T16:52:19Z", "committer_date": "2017-12-12T16:52:19Z", "raw_author": {"value": "2946d096d0cdefdc017559e6b57e87658736e843", "label": "Simon Willison"}, "raw_committer": {"value": "cd792325681cbad9f663f2879d8b69f1edbb678f", "label": "GitHub"}, "repo": {"value": 107914493, "label": "datasette"}, "author": {"value": 9599, "label": "simonw"}, "committer": {"value": 19864447, "label": "web-flow"}}