{"html_url": "https://github.com/simonw/datasette/issues/841#issuecomment-643576372", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/841", "id": 643576372, "node_id": "MDEyOklzc3VlQ29tbWVudDY0MzU3NjM3Mg==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2020-06-13T06:08:34Z", "updated_at": "2020-06-13T06:08:34Z", "author_association": "OWNER", "body": "Starlette achieves this. https://github.com/encode/starlette", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 638104520, "label": "Research feasibility of 100% test coverage"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/834#issuecomment-643648359", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/834", "id": 643648359, "node_id": "MDEyOklzc3VlQ29tbWVudDY0MzY0ODM1OQ==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2020-06-13T16:47:29Z", "updated_at": "2020-06-13T16:47:29Z", "author_association": "OWNER", "body": "Implementing this is proving surprisingly tricky, because of the need to be able to optionally `await` the returned value. It's a bit of a fiddle to get this to work within unit tests because they run in non-async functions - due to this cunning `async_to_sync` usage in the test client:\r\n\r\nhttps://github.com/simonw/datasette/blob/b906030235efbdff536405d66078f4868ce0d3bd/tests/fixtures.py#L115-L133\r\n\r\nI could switch to using `async def test_*` functions decorated with `@pytest.mark.asyncio` but I'd rather not re-engineer the entire test suite just for this one feature, so I'll try to find another way.", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 637342551, "label": "startup() plugin hook"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/841#issuecomment-643655108", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/841", "id": 643655108, "node_id": "MDEyOklzc3VlQ29tbWVudDY0MzY1NTEwOA==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2020-06-13T17:43:15Z", "updated_at": "2020-06-13T17:43:15Z", "author_association": "OWNER", "body": "Using https://pypi.org/project/pytest-cov/ and running `pytest --cov=datasette`:\r\n```\r\n---------- coverage: platform darwin, python 3.7.7-final-0 -----------\r\nName Stmts Miss Cover\r\n--------------------------------------------------------\r\ndatasette/__init__.py 3 0 100%\r\ndatasette/__main__.py 3 3 0%\r\ndatasette/_version.py 277 152 45%\r\ndatasette/actor_auth_cookie.py 19 3 84%\r\ndatasette/app.py 499 27 95%\r\ndatasette/cli.py 157 45 71%\r\ndatasette/database.py 233 17 93%\r\ndatasette/default_permissions.py 39 0 100%\r\ndatasette/facets.py 209 24 89%\r\ndatasette/filters.py 122 7 94%\r\ndatasette/hookspecs.py 19 0 100%\r\ndatasette/inspect.py 37 23 38%\r\ndatasette/plugins.py 34 6 82%\r\ndatasette/publish/__init__.py 0 0 100%\r\ndatasette/publish/cloudrun.py 55 2 96%\r\ndatasette/publish/common.py 19 1 95%\r\ndatasette/publish/heroku.py 95 13 86%\r\ndatasette/renderer.py 63 4 94%\r\ndatasette/sql_functions.py 4 0 100%\r\ndatasette/tracer.py 85 16 81%\r\ndatasette/utils/__init__.py 503 31 94%\r\ndatasette/utils/asgi.py 253 25 90%\r\ndatasette/utils/shutil_backport.py 44 40 9%\r\ndatasette/version.py 4 0 100%\r\ndatasette/views/__init__.py 0 0 100%\r\ndatasette/views/base.py 288 19 93%\r\ndatasette/views/database.py 120 2 98%\r\ndatasette/views/index.py 57 2 96%\r\ndatasette/views/special.py 72 16 78%\r\ndatasette/views/table.py 418 18 96%\r\n--------------------------------------------------------\r\nTOTAL 3731 496 87%\r\n```", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 638104520, "label": "Research feasibility of 100% test coverage"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/841#issuecomment-643656053", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/841", "id": 643656053, "node_id": "MDEyOklzc3VlQ29tbWVudDY0MzY1NjA1Mw==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2020-06-13T17:50:34Z", "updated_at": "2020-06-13T17:50:34Z", "author_association": "OWNER", "body": "Added a `.coveragerc` file:\r\n```\r\n[run]\r\nomit = datasette/_version.py, datasette/utils/shutil_backport.py\r\n```\r\nAnd ran again: `pytest --cov=datasette --cov-config=.coveragerc`\r\n```\r\nName Stmts Miss Cover\r\n------------------------------------------------------\r\ndatasette/__init__.py 3 0 100%\r\ndatasette/__main__.py 3 3 0%\r\ndatasette/actor_auth_cookie.py 19 3 84%\r\ndatasette/app.py 499 27 95%\r\ndatasette/cli.py 157 45 71%\r\ndatasette/database.py 233 17 93%\r\ndatasette/default_permissions.py 39 0 100%\r\ndatasette/facets.py 209 24 89%\r\ndatasette/filters.py 122 7 94%\r\ndatasette/hookspecs.py 19 0 100%\r\ndatasette/inspect.py 37 23 38%\r\ndatasette/plugins.py 34 6 82%\r\ndatasette/publish/__init__.py 0 0 100%\r\ndatasette/publish/cloudrun.py 55 2 96%\r\ndatasette/publish/common.py 19 1 95%\r\ndatasette/publish/heroku.py 95 13 86%\r\ndatasette/renderer.py 63 4 94%\r\ndatasette/sql_functions.py 4 0 100%\r\ndatasette/tracer.py 85 16 81%\r\ndatasette/utils/__init__.py 503 31 94%\r\ndatasette/utils/asgi.py 253 25 90%\r\ndatasette/version.py 4 0 100%\r\ndatasette/views/__init__.py 0 0 100%\r\ndatasette/views/base.py 288 19 93%\r\ndatasette/views/database.py 120 2 98%\r\ndatasette/views/index.py 57 2 96%\r\ndatasette/views/special.py 72 16 78%\r\ndatasette/views/table.py 418 18 96%\r\n------------------------------------------------------\r\nTOTAL 3410 304 91%\r\n```", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 638104520, "label": "Research feasibility of 100% test coverage"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/841#issuecomment-643657287", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/841", "id": 643657287, "node_id": "MDEyOklzc3VlQ29tbWVudDY0MzY1NzI4Nw==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2020-06-13T18:01:39Z", "updated_at": "2020-06-13T18:01:39Z", "author_association": "OWNER", "body": "Added `--cov-report html` and got this report: https://static.simonwillison.net/static/2020/htmlcov-issue-841/index.html", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 638104520, "label": "Research feasibility of 100% test coverage"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/841#issuecomment-643658036", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/841", "id": 643658036, "node_id": "MDEyOklzc3VlQ29tbWVudDY0MzY1ODAzNg==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2020-06-13T18:08:13Z", "updated_at": "2020-06-13T18:08:13Z", "author_association": "OWNER", "body": "From digging through that report it looks like the majority stuff that isn't fully covered is corner-cases... which are the kind of things I really do want the tests to catch.\r\n\r\nI'm not entirely ready to commit to 100%, but I'm going to start digging through and seeing how close I can get. If I can get to 98% (I'm on 91% already) I may as well push all the way to 100.", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 638104520, "label": "Research feasibility of 100% test coverage"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/841#issuecomment-643660427", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/841", "id": 643660427, "node_id": "MDEyOklzc3VlQ29tbWVudDY0MzY2MDQyNw==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2020-06-13T18:29:30Z", "updated_at": "2020-06-13T18:29:36Z", "author_association": "OWNER", "body": "This one looks easy enough to fix:\r\n\r\n\"Coverage_for_datasette_actor_auth_cookie_py__84_\"", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 638104520, "label": "Research feasibility of 100% test coverage"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/841#issuecomment-643660757", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/841", "id": 643660757, "node_id": "MDEyOklzc3VlQ29tbWVudDY0MzY2MDc1Nw==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2020-06-13T18:32:20Z", "updated_at": "2020-06-13T18:32:20Z", "author_association": "OWNER", "body": "Looking at options for publishing coverage reports:\r\n\r\n* https://github.com/codecov/codecov-action\r\n* https://github.com/coveralls-clients/coveralls-python\r\n\r\nI'm going to try https://codecov.io/", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 638104520, "label": "Research feasibility of 100% test coverage"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/841#issuecomment-643661125", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/841", "id": 643661125, "node_id": "MDEyOklzc3VlQ29tbWVudDY0MzY2MTEyNQ==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2020-06-13T18:35:30Z", "updated_at": "2020-06-13T18:36:50Z", "author_association": "OWNER", "body": "I ran export CODECOV_TOKEN=\"f7935cad...\", then ran this:\r\n```\r\ndatasette $ bash <(curl -s https://codecov.io/bash) \r\n _____ _\r\n / ____| | |\r\n| | ___ __| | ___ ___ _____ __\r\n| | / _ \\ / _` |/ _ \\/ __/ _ \\ \\ / /\r\n| |___| (_) | (_| | __/ (_| (_) \\ V /\r\n \\_____\\___/ \\__,_|\\___|\\___\\___/ \\_/\r\n Bash-20200602-f809a24\r\n\r\n\r\nx> No CI provider detected.\r\n Testing inside Docker? http://docs.codecov.io/docs/testing-with-docker\r\n Testing with Tox? https://docs.codecov.io/docs/python#section-testing-with-tox\r\n project root: .\r\n--> token set from env\r\n Yaml not found, that's ok! Learn more at http://docs.codecov.io/docs/codecov-yaml\r\n==> Running gcov in . (disable via -X gcov)\r\n==> Searching for coverage reports in:\r\n + .\r\n -> Found 1 reports\r\n==> Detecting git/mercurial file structure\r\n==> Reading reports\r\n + ./coverage.xml bytes=139174\r\n==> Appending adjustments\r\n https://docs.codecov.io/docs/fixing-reports\r\n -> No adjustments found\r\n==> Gzipping contents\r\n==> Uploading reports\r\n url: https://codecov.io\r\n query: branch=master&commit=0e49842e227a0f1f69d48108c87d17fe0379e548&build=&build_url=&name=&tag=&slug=simonw%2Fdatasette&service=&flags=&pr=&job=\r\n -> Pinging Codecov\r\nhttps://codecov.io/upload/v4?package=bash-20200602-f809a24&token=secret&branch=master&commit=0e49842e227a0f1f69d48108c87d17fe0379e548&build=&build_url=&name=&tag=&slug=simonw%2Fdatasette&service=&flags=&pr=&job=\r\n -> Uploading\r\n -> View reports at https://codecov.io/github/simonw/datasette/commit/0e49842e227a0f1f69d48108c87d17fe0379e548\r\n```\r\nBut https://codecov.io/github/simonw/datasette/commit/0e49842e227a0f1f69d48108c87d17fe0379e548 is a 404, so it doesn't seem to have worked?\r\n\r\nUPDATE: It works now, took about 30 seconds before the report showed up at that URL.", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 638104520, "label": "Research feasibility of 100% test coverage"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/842#issuecomment-643663005", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/842", "id": 643663005, "node_id": "MDEyOklzc3VlQ29tbWVudDY0MzY2MzAwNQ==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2020-06-13T18:51:57Z", "updated_at": "2020-06-13T18:51:57Z", "author_association": "OWNER", "body": "Two potential designs:\r\n\r\n- `_actor_id`, `_request_ip`, `_now_timestamp` - so special reserved parameters\r\n- a SQL function: `update blah set up = special('ip')`\r\n\r\nI fee the first would be easier to implement.", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 638212085, "label": "Magic parameters for canned queries"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/843#issuecomment-643676069", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/843", "id": 643676069, "node_id": "MDEyOklzc3VlQ29tbWVudDY0MzY3NjA2OQ==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2020-06-13T20:45:29Z", "updated_at": "2020-06-13T20:45:29Z", "author_association": "OWNER", "body": "I set up https://codecov.io/gh/simonw/datasette/settings and added a `CODECOV_TOKEN` to the GitHub Actions secrets for this repo.", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 638229448, "label": "Configure codecov.io"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/843#issuecomment-643676314", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/843", "id": 643676314, "node_id": "MDEyOklzc3VlQ29tbWVudDY0MzY3NjMxNA==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2020-06-13T20:47:37Z", "updated_at": "2020-06-13T20:47:37Z", "author_association": "OWNER", "body": "I can use this action: https://github.com/codecov/codecov-action", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 638229448, "label": "Configure codecov.io"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/pull/844#issuecomment-643681517", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/844", "id": 643681517, "node_id": "MDEyOklzc3VlQ29tbWVudDY0MzY4MTUxNw==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2020-06-13T21:36:15Z", "updated_at": "2020-06-13T21:36:15Z", "author_association": "OWNER", "body": "OK, this works now: https://codecov.io/gh/simonw/datasette/tree/1210d9f41841bdca450f85a2342cdb0ff339c1b4", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 638230433, "label": "Action to run tests and upload coverage report"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/841#issuecomment-643681747", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/841", "id": 643681747, "node_id": "MDEyOklzc3VlQ29tbWVudDY0MzY4MTc0Nw==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2020-06-13T21:38:46Z", "updated_at": "2020-06-13T21:38:46Z", "author_association": "OWNER", "body": "Closing this because I've researched feasibility. I may start a milestone in the future to help me get to 100%.", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 638104520, "label": "Research feasibility of 100% test coverage"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/846#issuecomment-643685207", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/846", "id": 643685207, "node_id": "MDEyOklzc3VlQ29tbWVudDY0MzY4NTIwNw==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2020-06-13T22:18:01Z", "updated_at": "2020-06-13T22:18:01Z", "author_association": "OWNER", "body": "This shows currently open files (after `pip install psutil`):\r\n```\r\nimport psutil\r\npsutil.Process().open_files()\r\n```\r\n\r\nI ran it inside `pytest -x --pdb` and got this:\r\n```\r\n> /Users/simon/.local/share/virtualenvs/datasette-AWNrQs95/lib/python3.7/site-packages/jinja2/utils.py(154)open_if_exists()\r\n-> return open(filename, mode)\r\n(Pdb) import psutil\r\n(Pdb) psutil.Process().open_files()\r\npopenfile(path='/private/var/folders/wr/hn3206rs1yzgq3r49bz8nvnh0000gn/T/tmp9uhx5d8x/fixtures.db', fd=10),\r\npopenfile(path='/private/var/folders/wr/hn3206rs1yzgq3r49bz8nvnh0000gn/T/tmpyfw44ica/fixtures.dot.db', fd=11),\r\npopenfile(path='/private/var/folders/wr/hn3206rs1yzgq3r49bz8nvnh0000gn/T/tmpyrg6g48b/fixtures.db', fd=12),\r\npopenfile(path='/private/var/folders/wr/hn3206rs1yzgq3r49bz8nvnh0000gn/T/tmp33kkg62s/fixtures.db', fd=13),\r\npopenfile(path='/private/var/folders/wr/hn3206rs1yzgq3r49bz8nvnh0000gn/T/tmp33kkg62s/fixtures.db', fd=14),\r\npopenfile(path='/private/var/folders/wr/hn3206rs1yzgq3r49bz8nvnh0000gn/T/tmp33kkg62s/fixtures.db', fd=15),\r\npopenfile(path='/private/var/folders/wr/hn3206rs1yzgq3r49bz8nvnh0000gn/T/tmp33kkg62s/fixtures.db', fd=16),\r\npopenfile(path='/private/var/folders/wr/hn3206rs1yzgq3r49bz8nvnh0000gn/T/tmp33kkg62s/fixtures.db', fd=17),\r\npopenfile(path='/private/var/folders/wr/hn3206rs1yzgq3r49bz8nvnh0000gn/T/tmp33kkg62s/fixtures.db', fd=18),\r\npopenfile(path='/private/var/folders/wr/hn3206rs1yzgq3r49bz8nvnh0000gn/T/tmp33kkg62s/fixtures.db', fd=19),\r\npopenfile(path='/private/var/folders/wr/hn3206rs1yzgq3r49bz8nvnh0000gn/T/tmpng4lg84_/fixtures.db', fd=20),\r\npopenfile(path='/private/var/folders/wr/hn3206rs1yzgq3r49bz8nvnh0000gn/T/tmp9uhx5d8x/fixtures.db', fd=21),\r\npopenfile(path='/private/var/folders/wr/hn3206rs1yzgq3r49bz8nvnh0000gn/T/tmp9uhx5d8x/fixtures.db', fd=22),\r\npopenfile(path='/private/var/folders/wr/hn3206rs1yzgq3r49bz8nvnh0000gn/T/tmp9uhx5d8x/fixtures.db', fd=23),\r\npopenfile(path='/private/var/folders/wr/hn3206rs1yzgq3r49bz8nvnh0000gn/T/tmph11oalw_/fixtures.db', fd=24),\r\npopenfile(path='/private/var/folders/wr/hn3206rs1yzgq3r49bz8nvnh0000gn/T/tmpyfw44ica/fixtures.dot.db', fd=25),\r\npopenfile(path='/private/var/folders/wr/hn3206rs1yzgq3r49bz8nvnh0000gn/T/tmpyfw44ica/fixtures.dot.db', fd=26),\r\npopenfile(path='/private/var/folders/wr/hn3206rs1yzgq3r49bz8nvnh0000gn/T/tmpyfw44ica/fixtures.dot.db', fd=27),\r\npopenfile(path='/private/var/folders/wr/hn3206rs1yzgq3r49bz8nvnh0000gn/T/tmpiorb2bo9/fixtures.db', fd=28),\r\npopenfile(path='/private/var/folders/wr/hn3206rs1yzgq3r49bz8nvnh0000gn/T/tmpyrg6g48b/fixtures.db', fd=29),\r\npopenfile(path='/private/var/folders/wr/hn3206rs1yzgq3r49bz8nvnh0000gn/T/tmpyrg6g48b/fixtures.db', fd=30),\r\npopenfile(path='/private/var/folders/wr/hn3206rs1yzgq3r49bz8nvnh0000gn/T/tmpyrg6g48b/fixtures.db', fd=31),\r\npopenfile(path='/private/var/folders/wr/hn3206rs1yzgq3r49bz8nvnh0000gn/T/tmprvyj5udv/fixtures.db', fd=32),\r\npopenfile(path='/private/var/folders/wr/hn3206rs1yzgq3r49bz8nvnh0000gn/T/tmpng4lg84_/fixtures.db', fd=33),\r\npopenfile(path='/private/var/folders/wr/hn3206rs1yzgq3r49bz8nvnh0000gn/T/tmpng4lg84_/fixtures.db', fd=34),\r\npopenfile(path='/private/var/folders/wr/hn3206rs1yzgq3r49bz8nvnh0000gn/T/tmpng4lg84_/fixtures.db', fd=35),\r\npopenfile(path='/private/var/folders/wr/hn3206rs1yzgq3r49bz8nvnh0000gn/T/tmpb_l6gmq0/fixtures.db', fd=36),\r\npopenfile(path='/private/var/folders/wr/hn3206rs1yzgq3r49bz8nvnh0000gn/T/tmph11oalw_/extra database.db', fd=40),\r\npopenfile(path='/private/var/folders/wr/hn3206rs1yzgq3r49bz8nvnh0000gn/T/tmpf0py4thp/fixtures.db', fd=41),\r\npopenfile(path='/private/var/folders/wr/hn3206rs1yzgq3r49bz8nvnh0000gn/T/tmpiorb2bo9/fixtures.db', fd=42),\r\npopenfile(path='/private/var/folders/wr/hn3206rs1yzgq3r49bz8nvnh0000gn/T/tmpiorb2bo9/fixtures.db', fd=43),\r\npopenfile(path='/private/var/folders/wr/hn3206rs1yzgq3r49bz8nvnh0000gn/T/tmpiorb2bo9/fixtures.db', fd=44),\r\npopenfile(path='/private/var/folders/wr/hn3206rs1yzgq3r49bz8nvnh0000gn/T/tmph11oalw_/fixtures.db', fd=45),\r\npopenfile(path='/private/var/folders/wr/hn3206rs1yzgq3r49bz8nvnh0000gn/T/tmph11oalw_/fixtures.db', fd=52),\r\npopenfile(path='/private/var/folders/wr/hn3206rs1yzgq3r49bz8nvnh0000gn/T/tmpwgcnmg4b/fixtures.db', fd=53),\r\npopenfile(path='/private/var/folders/wr/hn3206rs1yzgq3r49bz8nvnh0000gn/T/tmprvyj5udv/fixtures.db', fd=54),\r\npopenfile(path='/private/var/folders/wr/hn3206rs1yzgq3r49bz8nvnh0000gn/T/tmprvyj5udv/fixtures.db', fd=55),\r\npopenfile(path='/private/var/folders/wr/hn3206rs1yzgq3r49bz8nvnh0000gn/T/tmprvyj5udv/fixtures.db', fd=56),\r\npopenfile(path='/private/var/folders/wr/hn3206rs1yzgq3r49bz8nvnh0000gn/T/tmpoveuwqn6/fixtures.db', fd=57),\r\npopenfile(path='/private/var/folders/wr/hn3206rs1yzgq3r49bz8nvnh0000gn/T/tmpb_l6gmq0/fixtures.db', fd=61),\r\npopenfile(path='/private/var/folders/wr/hn3206rs1yzgq3r49bz8nvnh0000gn/T/tmpb_l6gmq0/fixtures.db', fd=62),\r\npopenfile(path='/private/var/folders/wr/hn3206rs1yzgq3r49bz8nvnh0000gn/T/tmpb_l6gmq0/fixtures.db', fd=63),\r\npopenfile(path='/private/var/folders/wr/hn3206rs1yzgq3r49bz8nvnh0000gn/T/tmp_j4h9mrn/fixtures.db', fd=64),\r\npopenfile(path='/private/var/folders/wr/hn3206rs1yzgq3r49bz8nvnh0000gn/T/tmpf0py4thp/fixtures.db', fd=65),\r\npopenfile(path='/private/var/folders/wr/hn3206rs1yzgq3r49bz8nvnh0000gn/T/tmpf0py4thp/fixtures.db', fd=66),\r\npopenfile(path='/private/var/folders/wr/hn3206rs1yzgq3r49bz8nvnh0000gn/T/tmpf0py4thp/extra database.db', fd=67),\r\npopenfile(path='/private/var/folders/wr/hn3206rs1yzgq3r49bz8nvnh0000gn/T/tmpf0py4thp/extra database.db', fd=68),\r\npopenfile(path='/private/var/folders/wr/hn3206rs1yzgq3r49bz8nvnh0000gn/T/tmpf0py4thp/fixtures.db', fd=69),\r\npopenfile(path='/private/var/folders/wr/hn3206rs1yzgq3r49bz8nvnh0000gn/T/tmpf0py4thp/extra database.db', fd=70)\r\n popenfile(path='/private/var/folders/wr/hn3206rs1yzgq3r49bz8nvnh0000gn/T/tmpub3eodj1/fixtures.db', fd=71)\r\n popenfile(path='/private/var/folders/wr/hn3206rs1yzgq3r49bz8nvnh0000gn/T/tmpwgcnmg4b/fixtures.db', fd=72)\r\n popenfile(path='/private/var/folders/wr/hn3206rs1yzgq3r49bz8nvnh0000gn/T/tmpwgcnmg4b/foo.db', fd=73)\r\n popenfile(path='/private/var/folders/wr/hn3206rs1yzgq3r49bz8nvnh0000gn/T/tmpwgcnmg4b/foo.db', fd=74)\r\n popenfile(path='/private/var/folders/wr/hn3206rs1yzgq3r49bz8nvnh0000gn/T/tmpwgcnmg4b/fixtures.db', fd=75)\r\n popenfile(path='/private/var/folders/wr/hn3206rs1yzgq3r49bz8nvnh0000gn/T/tmpwgcnmg4b/fixtures.db', fd=76)\r\n popenfile(path='/private/var/folders/wr/hn3206rs1yzgq3r49bz8nvnh0000gn/T/tmpwgcnmg4b/foo.db', fd=77)\r\n popenfile(path='/private/var/folders/wr/hn3206rs1yzgq3r49bz8nvnh0000gn/T/tmpwgcnmg4b/foo-bar.db', fd=78)\r\n popenfile(path='/private/var/folders/wr/hn3206rs1yzgq3r49bz8nvnh0000gn/T/tmpwgcnmg4b/foo-bar.db', fd=79)\r\n popenfile(path='/private/var/folders/wr/hn3206rs1yzgq3r49bz8nvnh0000gn/T/tmpwgcnmg4b/foo-bar.db', fd=80)\r\n popenfile(path='/private/var/folders/wr/hn3206rs1yzgq3r49bz8nvnh0000gn/T/pytest-of-simon/pytest-4/config-dir0/immutable.db', fd=81),\r\npopenfile(path='/private/var/folders/wr/hn3206rs1yzgq3r49bz8nvnh0000gn/T/tmpoveuwqn6/fixtures.db', fd=82),\r\npopenfile(path='/private/var/folders/wr/hn3206rs1yzgq3r49bz8nvnh0000gn/T/tmpoveuwqn6/fixtures.db', fd=83),\r\npopenfile(path='/private/var/folders/wr/hn3206rs1yzgq3r49bz8nvnh0000gn/T/tmpoveuwqn6/fixtures.db', fd=84),\r\npopenfile(path='/private/var/folders/wr/hn3206rs1yzgq3r49bz8nvnh0000gn/T/tmp44w5d5wo/fixtures.db', fd=85),\r\npopenfile(path='/private/var/folders/wr/hn3206rs1yzgq3r49bz8nvnh0000gn/T/tmp_j4h9mrn/fixtures.db', fd=86),\r\npopenfile(path='/private/var/folders/wr/hn3206rs1yzgq3r49bz8nvnh0000gn/T/tmp_j4h9mrn/fixtures.db', fd=87),\r\npopenfile(path='/private/var/folders/wr/hn3206rs1yzgq3r49bz8nvnh0000gn/T/tmp_j4h9mrn/fixtures.db', fd=88),\r\npopenfile(path='/private/var/folders/wr/hn3206rs1yzgq3r49bz8nvnh0000gn/T/tmpvu7h14uy/fixtures.db', fd=89),\r\npopenfile(path='/private/var/folders/wr/hn3206rs1yzgq3r49bz8nvnh0000gn/T/pytest-of-simon/pytest-4/config-dir0/demo.db', fd=119),\r\npopenfile(path='/private/var/folders/wr/hn3206rs1yzgq3r49bz8nvnh0000gn/T/pytest-of-simon/pytest-4/config-dir0/demo.db', fd=120),\r\npopenfile(path='/private/var/folders/wr/hn3206rs1yzgq3r49bz8nvnh0000gn/T/pytest-of-simon/pytest-4/config-dir0/demo.db', fd=121),\r\npopenfile(path='/private/var/folders/wr/hn3206rs1yzgq3r49bz8nvnh0000gn/T/tmp0xcnrjag/fixtures.db', fd=122),\r\npopenfile(path='/private/var/folders/wr/hn3206rs1yzgq3r49bz8nvnh0000gn/T/tmpub3eodj1/fixtures.db', fd=123),\r\npopenfile(path='/private/var/folders/wr/hn3206rs1yzgq3r49bz8nvnh0000gn/T/tmpub3eodj1/fixtures.db', fd=124),\r\npopenfile(path='/private/var/folders/wr/hn3206rs1yzgq3r49bz8nvnh0000gn/T/tmpub3eodj1/fixtures.db', fd=125),\r\npopenfile(path='/private/var/folders/wr/hn3206rs1yzgq3r49bz8nvnh0000gn/T/tmpfz8go8rk/fixtures.db', fd=126),\r\npopenfile(path='/private/var/folders/wr/hn3206rs1yzgq3r49bz8nvnh0000gn/T/tmp44w5d5wo/fixtures.db', fd=127),\r\npopenfile(path='/private/var/folders/wr/hn3206rs1yzgq3r49bz8nvnh0000gn/T/tmp44w5d5wo/fixtures.db', fd=128),\r\npopenfile(path='/private/var/folders/wr/hn3206rs1yzgq3r49bz8nvnh0000gn/T/tmp44w5d5wo/fixtures.db', fd=129),\r\npopenfile(path='/private/var/folders/wr/hn3206rs1yzgq3r49bz8nvnh0000gn/T/tmp5j3k1ep_/fixtures.db', fd=130)\r\n popenfile(path='/private/var/folders/wr/hn3206rs1yzgq3r49bz8nvnh0000gn/T/tmpvu7h14uy/fixtures.db', fd=131),\r\npopenfile(path='/private/var/folders/wr/hn3206rs1yzgq3r49bz8nvnh0000gn/T/tmpvu7h14uy/fixtures.db', fd=132),\r\npopenfile(path='/private/var/folders/wr/hn3206rs1yzgq3r49bz8nvnh0000gn/T/tmpvo3cobk9/fixtures.db', fd=133),\r\npopenfile(path='/private/var/folders/wr/hn3206rs1yzgq3r49bz8nvnh0000gn/T/tmp2t9txyir/fixtures.db', fd=134),\r\npopenfile(path='/private/var/folders/wr/hn3206rs1yzgq3r49bz8nvnh0000gn/T/tmpfz8go8rk/fixtures.db', fd=135),\r\npopenfile(path='/private/var/folders/wr/hn3206rs1yzgq3r49bz8nvnh0000gn/T/tmpfz8go8rk/fixtures.db', fd=136),\r\npopenfile(path='/private/var/folders/wr/hn3206rs1yzgq3r49bz8nvnh0000gn/T/tmp7h3skv8b/fixtures.db', fd=137),\r\npopenfile(path='/private/var/folders/wr/hn3206rs1yzgq3r49bz8nvnh0000gn/T/tmp5j3k1ep_/fixtures.db', fd=138),\r\npopenfile(path='/private/var/folders/wr/hn3206rs1yzgq3r49bz8nvnh0000gn/T/tmp5j3k1ep_/fixtures.db', fd=139),\r\npopenfile(path='/private/var/folders/wr/hn3206rs1yzgq3r49bz8nvnh0000gn/T/tmp5j3k1ep_/fixtures.db', fd=140),\r\npopenfile(path='/private/var/folders/wr/hn3206rs1yzgq3r49bz8nvnh0000gn/T/tmp5j3k1ep_/extra database.db', fd=141),\r\n```\r\nSo yeah, that's too many open files!\r\n", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 638241779, "label": "\"Too many open files\" error running tests"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/846#issuecomment-643685333", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/846", "id": 643685333, "node_id": "MDEyOklzc3VlQ29tbWVudDY0MzY4NTMzMw==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2020-06-13T22:19:38Z", "updated_at": "2020-06-13T22:19:38Z", "author_association": "OWNER", "body": "That's 91 open files but only 29 unique filenames.", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 638241779, "label": "\"Too many open files\" error running tests"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/846#issuecomment-643685669", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/846", "id": 643685669, "node_id": "MDEyOklzc3VlQ29tbWVudDY0MzY4NTY2OQ==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2020-06-13T22:24:22Z", "updated_at": "2020-06-13T22:24:22Z", "author_association": "OWNER", "body": "I tried this experiment:\r\n```python\r\nimport sqlite3, psutil\r\ndef show_things():\r\n conn = sqlite3.connect(\"fixtures.db\")\r\n tables = [r[0] for r in conn.execute(\"select * from sqlite_master\").fetchall()]\r\n return tables\r\nprint(psutil.Process().open_files())\r\nprint(show_things())\r\nprint(psutil.Process().open_files())\r\n```\r\nTo see if the connection would be automatically released when the `conn` variable was garbage collected at the end of the function... and it was correctly released - the two calls to `open_files()` showed that the file did not remain open.\r\n\r\nLikewise:\r\n```\r\nIn [11]: conn = sqlite3.connect(\"fixtures.db\") \r\n\r\nIn [12]: psutil.Process().open_files() \r\nOut[12]: \r\n[popenfile(path='/Users/simon/.ipython/profile_default/history.sqlite', fd=4),\r\n popenfile(path='/Users/simon/.ipython/profile_default/history.sqlite', fd=5),\r\n popenfile(path='/Users/simon/Dropbox/Development/datasette/fixtures.db', fd=12)]\r\n\r\nIn [13]: del conn \r\n\r\nIn [14]: psutil.Process().open_files() \r\nOut[14]: \r\n[popenfile(path='/Users/simon/.ipython/profile_default/history.sqlite', fd=4),\r\n popenfile(path='/Users/simon/.ipython/profile_default/history.sqlite', fd=5)]\r\n```\r\nSo presumably there's something about the way my pytest fixtures work that's causing the many different `Datasette()` instances and their underlying SQLite connections that I create not to be cleaned up later.", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 638241779, "label": "\"Too many open files\" error running tests"}, "performed_via_github_app": null}