{"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": "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": "f571b19d8a5fd3a19fdf679421fd55a8edbf5295", "message": "sqlerrors() decorator catching and returning useful errors\n\nCloses #8", "author_date": "2017-10-23T15:28:00Z", "committer_date": "2017-10-23T15:28: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": "6a0c5de6154893eb4269dc7b1f160726ec6395f2", "message": "ensure_build_metadata() function for metadata\n\nThis will be run at compile time - the goal is to generate a build-\nmetadata.json file with a bunch of useful facts about the databases that could\nbe expensive to generate at run-time.\n\nExample metadata:\n\n {\n \"flights\": {\n \"file\": \"flights.db\",\n \"tables\": {\n \"airlines\": 6048,\n \"airports\": 8107,\n \"routes\": 67663\n },\n \"hash\": \"07d1283e07786b1235bb7041ea445ae103d1571565580a29eab0203c555725fd\"\n }\n\nSo far we have a sha256 hash of the database file itself, plus a row count for\neach table.\n\nFixes #11", "author_date": "2017-10-23T16:02:40Z", "committer_date": "2017-10-23T16:02:40Z", "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": "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": "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": "255e2611e5c3cfdda76c9da7abdbe5af976044ac", "message": "CORS headers for JSON responses\n\nAccess-Control-Allow-Origin: *", "author_date": "2017-10-24T02:48:06Z", "committer_date": "2017-10-24T02:48:06Z", "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": "0fa177269767e5e55c863382333fde627d2b7074", "message": "Allow ?sql= argument against database\n\ne.g. /database-234324?sql=select * from table limit 1", "author_date": "2017-10-24T02:48:56Z", "committer_date": "2017-10-24T02:48: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": "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": "606ff9e35e007ae58a491d417f47779034bacabc", "message": "python app.py --build to generate build-metadata.json\n\nThis is now run by the Dockerfile to build this at compile time.", "author_date": "2017-10-24T05:53:13Z", "committer_date": "2017-10-24T05:53: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": "6a9fdcc0718aea2cbc01ae4d60b9a1fba3601a66", "message": "Added addressable page per row\n\nRefs #1 - only exists for tables with introspectable primary keys.\n\nStill need to link to this page.\n\nAlso added first unit tests - refs #9", "author_date": "2017-10-24T05:54:58Z", "committer_date": "2017-10-24T05:54: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": "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": "f643f7aee1b3d29df82b93a6560887a35b7a2f13", "message": "base64 encode bytestrings from DB in JSON\n\nFixes #29", "author_date": "2017-10-24T14:58:41Z", "committer_date": "2017-10-24T14:58:41Z", "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": "bc9379aabcedce7fbc661ac15008d8801199a045", "message": "Added .jsono extension\n\nReturns JSON key/value objects for each row instead of lists of values.\n\nCloses #6", "author_date": "2017-10-24T15:07:52Z", "committer_date": "2017-10-24T15:07: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": "5f806880c9766daf09fc9535171637ebb8224cab", "message": "Correctly JSON serialize sqlite3.Cursor", "author_date": "2017-10-24T23:53:21Z", "committer_date": "2017-10-24T23:53: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": "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": "2a09d3708777116daedc548078a662086552523f", "message": "Allow views to be browsed as well as tables", "author_date": "2017-10-24T23:55:08Z", "committer_date": "2017-10-24T23:55:08Z", "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": "4c7379a898df426af0c31159e5cb06d672189301", "message": "Don't crash on weird character encodings\n\nExpecting SQLite columns to all be valid utf8 doesn't work, because we are\ndeailing with all kinds of databases. Instead, we now use the 'replace'\nencoding mode to replace any non-UTF8 characters with a [X] character.", "author_date": "2017-10-25T00:01:34Z", "committer_date": "2017-10-25T00:01: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": "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": "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": "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": "2fe94641b0b2dc291d1fce3dad0fbf96294b3a32", "message": "Don't try to show row counts for views\n\nAlso handle tables/views with spaces in their name in the URL.", "author_date": "2017-10-25T01:33:12Z", "committer_date": "2017-10-25T01:33:12Z", "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": "630b40038ef31b351abc2e39c3a0c7b3648814f8", "message": "Added support for gt, gte, lt, lte lookups\n\nRefs #23", "author_date": "2017-10-25T01:46:49Z", "committer_date": "2017-10-25T01:46: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": "1c5977961f596dae5aaa18c8b2d7a10e9f42a543", "message": "Added glob and like lookups - refs #23", "author_date": "2017-10-25T01:53:01Z", "committer_date": "2017-10-25T01:53: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": "e55bc3b2fa6e1e8be7b7c1f5b6cb3764713b6faa", "message": "th align left for all tables", "author_date": "2017-10-25T14:46:38Z", "committer_date": "2017-10-25T14:46:38Z", "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": "d94d4465d7e72e668122f81206397f4f20cf555b", "message": "Double quote around column names\n\nThis means filters still work even with column names that contain spaces", "author_date": "2017-10-25T14:47:20Z", "committer_date": "2017-10-25T14:47:20Z", "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": "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": "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": "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": "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": "2c625e31ed018f929223918240603bf2a80e665c", "message": "Fixed bug on Row page with tables containing spaces\n\nWe were attempting to run this SQL:\n\n select * from \"Order%20Details\" where ...\n\nOn this page:\n\n http://0.0.0.0:8877/northwind-40d049b/Order%20Details/10250,41", "author_date": "2017-10-27T07:16:18Z", "committer_date": "2017-10-27T07:16: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": "be768f26d09fa060b1ca71785ff546dd572f3fbc", "message": "python setup.py test now runs the tests", "author_date": "2017-11-04T23:40:27Z", "committer_date": "2017-11-04T23:40: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": "edaa10587e60946e0c1935333f6b79553db33798", "message": "Configured Travis CI", "author_date": "2017-11-04T23:47:46Z", "committer_date": "2017-11-04T23:47:46Z", "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": "0ac8bbce2e73c0759ec48661a7b740d2c368b2a2", "message": "Default subcommand is now serve\n\nUsing click-default-group: https://github.com/click-contrib/click-default-group\n\nAlso removed requirements.txt in favour of setup.py", "author_date": "2017-11-04T23:53:50Z", "committer_date": "2017-11-04T23:53: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": "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": "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": "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": "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": "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": "9e9e9613907b6a2a8a051fdda93c0d26344ee110", "message": "Fixed error in RowView", "author_date": "2017-11-06T02:38:06Z", "committer_date": "2017-11-06T02:38:06Z", "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": "8af7bc100c681975894f49f4ffd6d26a06e93f60", "message": "Added a MANIFEST.in\n\nNow python setup.py bdist_wheel creates a .whl that includes the CSS.", "author_date": "2017-11-09T02:39:42Z", "committer_date": "2017-11-09T02:39: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": "abb591d83264bbf11a5eb9daf03011d051e8f833", "message": "Added --reload argument to 'immutabase serve' command\n\nUses hupper to restart the server when the code changes. Useful for development.\n\nDepends on https://pypi.python.org/pypi/hupper", "author_date": "2017-11-09T13:46:16Z", "committer_date": "2017-11-09T14:14: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": "b2dee11fcd989d9e2a7bf4de1e23dbc320c05013", "message": "Databases now get distinct colours\n\nA left border based on their content hash.\n\nCloses #31", "author_date": "2017-11-09T14:12:42Z", "committer_date": "2017-11-09T14:14:40Z", "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": "d9fa2bf7ba2f9d3dcb2beb303f772c86344b4bcf", "message": "Use rowid if no primary key available\n\nAllows us to link to individual records even for tables that do not have a primary key.\n\nRefs #5", "author_date": "2017-11-09T14:39:50Z", "committer_date": "2017-11-09T14:39: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": "bc9871c93583f3cdcca191b7fa05b255be7275c8", "message": "gt/lt/gte/lte now treat numeric arguments as numeric\n\nThis now works:\n\n https://immutabase-dlmggyoepw.now.sh/northwind-40d049b/Products?UnitsInStock__gt=100\n\nPreviously the input value of 100 would be treated as a string.\n\nAlso fixed a bug where filter arguments had stopped working entirely.\n\nRefs #23", "author_date": "2017-11-09T16:09:55Z", "committer_date": "2017-11-09T16:09: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": "292f140a4f391f646ec0be85ec9f22dde30f9de2", "message": "Explicitly order by pk (or by rowid)\n\nRefs #5", "author_date": "2017-11-09T16:11:14Z", "committer_date": "2017-11-09T16:11: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": "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": "e06b0117711ca7c9d6d6865d2bff8525aa11ebf0", "message": "Updated tests\n\nRefs #23", "author_date": "2017-11-10T18:43:54Z", "committer_date": "2017-11-10T18:43: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": "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": "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": "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": "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": "e9fce441956642bef3548e3181d72a88317efa65", "message": "Don't serve cache headers in debug or refresh modes", "author_date": "2017-11-10T20:26:37Z", "committer_date": "2017-11-10T20:26: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": "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": "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": "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": "3863a30b5d18204b4c77518f1880a1f705e929db", "message": "publish command checks 'now' is installed\n\nCloses #58", "author_date": "2017-11-11T16:00:00Z", "committer_date": "2017-11-11T16:00: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": "3280972c891633c6015fa55bbfd094420b4f0233", "message": "Fixed tests I broke earlier\n\nBroke these tests in 21c9c04310dffcdb8cf6fee0f74fc9e7ac1ecf19", "author_date": "2017-11-11T16:52:17Z", "committer_date": "2017-11-11T16:52: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": "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": "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": "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": "e4bf66d9b075190bf96c1f85eaccd7464915f249", "message": "Added header with breadcrumbs and footer\n\nAlso cleaned up titles on various pages.\n\nCloses #61", "author_date": "2017-11-11T20:36:20Z", "committer_date": "2017-11-11T20:36:20Z", "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": "fa42a56c6a0fa62529eabf2d363bd3008ce23094", "message": "Bulked out table test a bit\n\nI'm closing #50 - more tests will be added in the future, but the framework\nis neatly in place for them now.", "author_date": "2017-11-11T22:22:47Z", "committer_date": "2017-11-11T22:22: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": "2366a016f252f2220eb777938a9da4b0de179063", "message": "Added links to .json and .jsono representations\n\nCloses #62", "author_date": "2017-11-11T22:40:44Z", "committer_date": "2017-11-11T22:40: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": "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": "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": "b51836f8463ef65bc947f0a7b6e60167cb7154cf", "message": "Fixed bug with tables with spaces in their name\n\nThe new database index page was erroring.", "author_date": "2017-11-12T20:02:45Z", "committer_date": "2017-11-12T20:02:45Z", "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": "f4794df07032083fbd3d4829e17b3fd2a54b779a", "message": "Added border-right to table cells", "author_date": "2017-11-12T20:19:18Z", "committer_date": "2017-11-12T20:19: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": "ff2ab9dc7d82f70daae10f5b0cde87d74704f910", "message": "Views now show their SQL, are handled a bit better\n\nRefs #66", "author_date": "2017-11-12T20:31:46Z", "committer_date": "2017-11-12T20:32: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": "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": "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": "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": "db3fa4abfac366184e97fb313b36d3429e5b937a", "message": "Views no longer attempt to link to records\n\nCloses #54", "author_date": "2017-11-12T21:29:26Z", "committer_date": "2017-11-12T21:29: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": "efecae5a11617eb576d475192384339fcdb03189", "message": "Full path to database now works\n\ne.g. datasette /tmp/blah.db\n\nPreviously this failed because it did not open with full path.", "author_date": "2017-11-12T22:23:41Z", "committer_date": "2017-11-12T23:01:29Z", "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": "4c66097d581c3970a23530598c4fe98b09f422ee", "message": "datasette publish now works with full paths\n\ne.g. datasette publish /tmp/blah/database.db now does the right thing", "author_date": "2017-11-12T23:16:24Z", "committer_date": "2017-11-12T23:16: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": "26370b14d862a5d2dc32b858bdf627f2a5ec3209", "message": "Handle table names with slashes in them\n\ne.g. https://datasette-wdlexdiaoz.now.sh/fivethirtyeight-75d605c/bob-ross%2Felements-by-episode.csv?CABIN=1&BUSHES=1&CLOUDS=1", "author_date": "2017-11-12T23:17:00Z", "committer_date": "2017-11-12T23:17: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": "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": "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": "ff2fb573cd8773206a6df83229620928056e2ee2", "message": "datasette publish --name=now-accepts-name\n\nFixes #72", "author_date": "2017-11-13T02:12:21Z", "committer_date": "2017-11-13T02:12: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": "3ef35ca8b4369af6a8bcdd9e5cfbb5f3a7d17cf8", "message": "serve and publish commands now take a --metadata option\n\nIf provided, the --metadata option is the path to a JSON file containing\nmetadata that should be displayed alongside the dataset.\n\n datasette /tmp/fivethirtyeight.db --metadata /tmp/metadata.json\n\nCurrently that metadata format looks like this:\n\n {\n \"title\": \"Five Thirty Eight\",\n \"license\": \"CC Attribution 4.0 License\",\n \"license_url\": \"http://creativecommons.org/licenses/by/4.0/\",\n \"source\": \"fivethirtyeight/data on GitHub\",\n \"source_url\": \"https://github.com/fivethirtyeight/data\"\n }\n\nIf provided, this will be used by the index template and to populate the\ncommon footer.\n\nThe publish command also accepts this argument, and will package any provided\nmetadata up and include it with the resulting Docker container.\n\n datasette publish --metadata /tmp/metadata.json /tmp/fivethirtyeight.db\n\nCloses #68", "author_date": "2017-11-13T15:20:02Z", "committer_date": "2017-11-13T15:20:02Z", "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": "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": "495407acefe1e6976316aef88ae0e4c1d48ab421", "message": "Force initial .inspect() before starting server\n\nOtherwise there is a long pause on the first request made.", "author_date": "2017-11-13T18:03:52Z", "committer_date": "2017-11-13T18:03: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": "97c4bf4271495f8f711926ec44d8def3f2941379", "message": "Added --cors argument to enable CORS\n\nCloses #75", "author_date": "2017-11-13T18:17:42Z", "committer_date": "2017-11-13T18:17: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": "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": "20d41c8e8e84ab3e8bdb5cca9bd9799da09794ad", "message": "publish now takes a required publisher argument - only current option is 'now'\n\nCloses #76", "author_date": "2017-11-13T18:40:51Z", "committer_date": "2017-11-13T18:40: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": "e838bd743d31358b362875854a0ac5e78047727f", "message": "Added README and improved help for 'datasette serve'", "author_date": "2017-11-13T18:41:53Z", "committer_date": "2017-11-13T18:41: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": "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": "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": "79216bac12668eb90ccad65086d4f129476a3969", "message": "Added some breathing room to the footer", "author_date": "2017-11-13T19:38:20Z", "committer_date": "2017-11-13T19:38:20Z", "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": "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": "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": "fe279ab7b4ae99dab295d5cf4d39ad06d782997e", "message": "v0.8 - added PyPI metadata, ready to ship", "author_date": "2017-11-13T21:17:34Z", "committer_date": "2017-11-13T21:17: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"}}