{"html_url": "https://github.com/simonw/datasette/issues/2057#issuecomment-1730363182", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/2057", "id": 1730363182, "node_id": "IC_kwDOBm6k_c5nIz8u", "user": {"value": 9599, "label": "simonw"}, "created_at": "2023-09-21T22:09:10Z", "updated_at": "2023-09-21T22:09:10Z", "author_association": "OWNER", "body": "Tests all pass now.", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1662951875, "label": "DeprecationWarning: pkg_resources is deprecated as an API"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/2057#issuecomment-1730356422", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/2057", "id": 1730356422, "node_id": "IC_kwDOBm6k_c5nIyTG", "user": {"value": 9599, "label": "simonw"}, "created_at": "2023-09-21T22:01:00Z", "updated_at": "2023-09-21T22:01:00Z", "author_association": "OWNER", "body": "Tested that locally with Python 3.9 from `pyenv` and it worked.", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1662951875, "label": "DeprecationWarning: pkg_resources is deprecated as an API"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/2057#issuecomment-1730353462", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/2057", "id": 1730353462, "node_id": "IC_kwDOBm6k_c5nIxk2", "user": {"value": 9599, "label": "simonw"}, "created_at": "2023-09-21T21:57:17Z", "updated_at": "2023-09-21T21:57:17Z", "author_association": "OWNER", "body": "Still fails in Python 3.9: https://github.com/simonw/datasette/actions/runs/6266752548/job/17018363302\r\n```\r\n plugin_info[\"name\"] = distinfo.name or distinfo.project_name\r\nAttributeError: 'PathDistribution' object has no attribute 'name'\r\nTest failed: datasette-json-html should not have been loaded\r\n```", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1662951875, "label": "DeprecationWarning: pkg_resources is deprecated as an API"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/2057#issuecomment-1730250337", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/2057", "id": 1730250337, "node_id": "IC_kwDOBm6k_c5nIYZh", "user": {"value": 9599, "label": "simonw"}, "created_at": "2023-09-21T20:26:12Z", "updated_at": "2023-09-21T20:26:12Z", "author_association": "OWNER", "body": "That does seem to fix the problem! ", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1662951875, "label": "DeprecationWarning: pkg_resources is deprecated as an API"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/2057#issuecomment-1730247545", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/2057", "id": 1730247545, "node_id": "IC_kwDOBm6k_c5nIXt5", "user": {"value": 9599, "label": "simonw"}, "created_at": "2023-09-21T20:23:47Z", "updated_at": "2023-09-21T20:23:47Z", "author_association": "OWNER", "body": "Hunch: https://pypi.org/project/importlib-metadata/ may help here.", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1662951875, "label": "DeprecationWarning: pkg_resources is deprecated as an API"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/2057#issuecomment-1730226107", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/2057", "id": 1730226107, "node_id": "IC_kwDOBm6k_c5nISe7", "user": {"value": 9599, "label": "simonw"}, "created_at": "2023-09-21T20:06:19Z", "updated_at": "2023-09-21T20:06:19Z", "author_association": "OWNER", "body": "No that's not it actually, it's something else.\r\n\r\nGot to this point:\r\n```bash\r\nDATASETTE_LOAD_PLUGINS=datasette-init python -i $(which datasette) plugins\r\n```\r\nThat fails and drops me into a debugger:\r\n\r\n```\r\n File \"/Users/simon/Dropbox/Development/datasette/datasette/cli.py\", line 186, in plugins\r\n app = Datasette([], plugins_dir=plugins_dir)\r\n File \"/Users/simon/Dropbox/Development/datasette/datasette/app.py\", line 405, in __init__\r\n for plugin in get_plugins()\r\n File \"/Users/simon/Dropbox/Development/datasette/datasette/plugins.py\", line 89, in get_plugins\r\n plugin_info[\"name\"] = distinfo.name or distinfo.project_name\r\nAttributeError: 'PathDistribution' object has no attribute 'name'\r\n```", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1662951875, "label": "DeprecationWarning: pkg_resources is deprecated as an API"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/2057#issuecomment-1730219703", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/2057", "id": 1730219703, "node_id": "IC_kwDOBm6k_c5nIQ63", "user": {"value": 9599, "label": "simonw"}, "created_at": "2023-09-21T20:01:54Z", "updated_at": "2023-09-21T20:01:54Z", "author_association": "OWNER", "body": "The problem is here:\r\n```\r\n 86 \t distinfo = plugin_to_distinfo.get(plugin)\r\n 87 \t if distinfo is None:\r\n 88 \t breakpoint()\r\n 89 ->\t assert False\r\n 90 \t if distinfo.name is None:\r\n 91 \t breakpoint()\r\n 92 \t assert False\r\n 93 \t if distinfo:\r\n 94 \t plugin_info[\"version\"] = distinfo.version\r\n(Pdb) distinfo\r\n(Pdb) plugin\r\n\r\n```\r\nThat `plugin_to_distinfo` is missing some stuff.", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1662951875, "label": "DeprecationWarning: pkg_resources is deprecated as an API"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/2057#issuecomment-1730214654", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/2057", "id": 1730214654, "node_id": "IC_kwDOBm6k_c5nIPr-", "user": {"value": 9599, "label": "simonw"}, "created_at": "2023-09-21T19:59:51Z", "updated_at": "2023-09-21T19:59:51Z", "author_association": "OWNER", "body": "So the problem is the `get_plugins()` function returning plugins with `None` for their name:\r\n\r\nhttps://github.com/simonw/datasette/blob/80a9cd9620fddf2695d12d8386a91e7c6b145ef2/datasette/plugins.py#L61-L91", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1662951875, "label": "DeprecationWarning: pkg_resources is deprecated as an API"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/2057#issuecomment-1730212597", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/2057", "id": 1730212597, "node_id": "IC_kwDOBm6k_c5nIPL1", "user": {"value": 9599, "label": "simonw"}, "created_at": "2023-09-21T19:58:38Z", "updated_at": "2023-09-21T19:58:38Z", "author_association": "OWNER", "body": "Relevant code: https://github.com/simonw/datasette/blob/80a9cd9620fddf2695d12d8386a91e7c6b145ef2/datasette/app.py#L1127-L1146", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1662951875, "label": "DeprecationWarning: pkg_resources is deprecated as an API"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/2057#issuecomment-1730211445", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/2057", "id": 1730211445, "node_id": "IC_kwDOBm6k_c5nIO51", "user": {"value": 9599, "label": "simonw"}, "created_at": "2023-09-21T19:57:44Z", "updated_at": "2023-09-21T19:57:44Z", "author_association": "OWNER", "body": "In the debugger:\r\n```\r\n>>> import pdb\r\n>>> pdb.pm()\r\n> /Users/simon/Dropbox/Development/datasette/datasette/app.py(1136)_plugins()\r\n-> ps.sort(key=lambda p: p[\"name\"])\r\n(Pdb) ps\r\n[{'name': None, 'static_path': None, 'templates_path': None, 'hooks': ['prepare_connection', 'render_cell'], 'version': '1.0.1'}, {'name': None, 'static_path': None, 'templates_path': None, 'hooks': ['startup'], 'version': '0.2'}]\r\n```", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1662951875, "label": "DeprecationWarning: pkg_resources is deprecated as an API"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/2057#issuecomment-1730210728", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/2057", "id": 1730210728, "node_id": "IC_kwDOBm6k_c5nIOuo", "user": {"value": 9599, "label": "simonw"}, "created_at": "2023-09-21T19:57:08Z", "updated_at": "2023-09-21T19:57:08Z", "author_association": "OWNER", "body": "In my Python 3.8 environment I ran:\r\n```bash\r\ndatasette install datasette-init datasette-json-html\r\n```\r\nAnd now `datasette plugins` produces this error:\r\n```\r\n File \"/Users/simon/Dropbox/Development/datasette/datasette/cli.py\", line 192, in plugins\r\n click.echo(json.dumps(app._plugins(all=all), indent=4))\r\n File \"/Users/simon/Dropbox/Development/datasette/datasette/app.py\", line 1136, in _plugins\r\n ps.sort(key=lambda p: p[\"name\"])\r\nTypeError: '<' not supported between instances of 'NoneType' and 'NoneType'\r\n```", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1662951875, "label": "DeprecationWarning: pkg_resources is deprecated as an API"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/2057#issuecomment-1730201226", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/2057", "id": 1730201226, "node_id": "IC_kwDOBm6k_c5nIMaK", "user": {"value": 9599, "label": "simonw"}, "created_at": "2023-09-21T19:49:20Z", "updated_at": "2023-09-21T19:49:20Z", "author_association": "OWNER", "body": "That passed on 3.8 but should have failed: https://github.com/simonw/datasette/actions/runs/6266341481/job/17017099801 - the \"Test DATASETTE_LOAD_PLUGINS\" test shows errors but did not fail the CI run.", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1662951875, "label": "DeprecationWarning: pkg_resources is deprecated as an API"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/2057#issuecomment-1730188367", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/2057", "id": 1730188367, "node_id": "IC_kwDOBm6k_c5nIJRP", "user": {"value": 9599, "label": "simonw"}, "created_at": "2023-09-21T19:38:28Z", "updated_at": "2023-09-21T19:40:38Z", "author_association": "OWNER", "body": "I'll imitate `certbot`:\r\n\r\nhttps://github.com/certbot/certbot/blob/694c758db7fcd8410b5dadcd136c61b3eb028fdc/certbot-ci/setup.py#L9\r\n\r\n```python\r\n 'importlib_resources>=1.3.1; python_version < \"3.9\"',\r\n```\r\nLooks like `1.3` is the minimum version needed for compatibility with the 3.9 standard library, according to https://github.com/python/importlib_resources/blob/main/README.rst#compatibility\r\n\r\nhttps://github.com/certbot/certbot/blob/694c758db7fcd8410b5dadcd136c61b3eb028fdc/certbot/certbot/_internal/constants.py#L13C29-L16\r\n\r\n```python\r\nif sys.version_info >= (3, 9): # pragma: no cover\r\n import importlib.resources as importlib_resources\r\nelse: # pragma: no cover\r\n import importlib_resources\r\n```", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1662951875, "label": "DeprecationWarning: pkg_resources is deprecated as an API"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/2057#issuecomment-1730185322", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/2057", "id": 1730185322, "node_id": "IC_kwDOBm6k_c5nIIhq", "user": {"value": 9599, "label": "simonw"}, "created_at": "2023-09-21T19:35:49Z", "updated_at": "2023-09-21T19:35:49Z", "author_association": "OWNER", "body": "I think I can fix this using https://importlib-resources.readthedocs.io/en/latest/using.html - maybe as a dependency only installed if the Python version is less than 3.9.", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1662951875, "label": "DeprecationWarning: pkg_resources is deprecated as an API"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/2057#issuecomment-1730183405", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/2057", "id": 1730183405, "node_id": "IC_kwDOBm6k_c5nIIDt", "user": {"value": 9599, "label": "simonw"}, "created_at": "2023-09-21T19:34:09Z", "updated_at": "2023-09-21T19:34:09Z", "author_association": "OWNER", "body": "Confirmed: https://docs.python.org/3/library/importlib.resources.html#importlib.resources.files\r\n\r\n> `importlib.resources.files(package)`\r\n> [...]\r\n> New in version 3.9.", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1662951875, "label": "DeprecationWarning: pkg_resources is deprecated as an API"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/2057#issuecomment-1730171241", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/2057", "id": 1730171241, "node_id": "IC_kwDOBm6k_c5nIFFp", "user": {"value": 9599, "label": "simonw"}, "created_at": "2023-09-21T19:27:25Z", "updated_at": "2023-09-21T19:27:25Z", "author_association": "OWNER", "body": "This broke in Python 3.8:\r\n\r\n```\r\nif plugin.__name__ not in DEFAULT_PLUGINS:\r\n try:\r\n if (importlib.resources.files(plugin.__name__) / \"static\").is_dir():\r\nE AttributeError: module 'importlib.resources' has no attribute '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": 1662951875, "label": "DeprecationWarning: pkg_resources is deprecated as an API"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/2057#issuecomment-1722323967", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/2057", "id": 1722323967, "node_id": "IC_kwDOBm6k_c5mqJP_", "user": {"value": 9599, "label": "simonw"}, "created_at": "2023-09-16T21:54:33Z", "updated_at": "2023-09-16T21:54:33Z", "author_association": "OWNER", "body": "Just found this migration guide: https://importlib-metadata.readthedocs.io/en/latest/migration.html", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1662951875, "label": "DeprecationWarning: pkg_resources is deprecated as an API"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/2057#issuecomment-1722266942", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/2057", "id": 1722266942, "node_id": "IC_kwDOBm6k_c5mp7U-", "user": {"value": 9599, "label": "simonw"}, "created_at": "2023-09-16T16:38:27Z", "updated_at": "2023-09-16T16:38:27Z", "author_association": "OWNER", "body": "The `importlib.metadata.entry_points()` function is pretty interesting:\r\n```pycon\r\n>>> import importlib.metadata\r\n>>> from pprint import pprint\r\n>>> pprint(importlib.metadata.entry_points())\r\n{'babel.checkers': [EntryPoint(name='num_plurals', value='babel.messages.checkers:num_plurals', group='babel.checkers'),\r\n EntryPoint(name='python_format', value='babel.messages.checkers:python_format', group='babel.checkers')],\r\n 'babel.extractors': [EntryPoint(name='jinja2', value='jinja2.ext:babel_extract[i18n]', group='babel.extractors'),\r\n EntryPoint(name='ignore', value='babel.messages.extract:extract_nothing', group='babel.extractors'),\r\n EntryPoint(name='javascript', value='babel.messages.extract:extract_javascript', group='babel.extractors'),\r\n EntryPoint(name='python', value='babel.messages.extract:extract_python', group='babel.extractors')],\r\n 'console_scripts': [EntryPoint(name='datasette', value='datasette.cli:cli', group='console_scripts'),\r\n EntryPoint(name='normalizer', value='charset_normalizer.cli.normalizer:cli_detect', group='console_scripts'),\r\n EntryPoint(name='pypprint', value='pprintpp:console', group='console_scripts'),\r\n EntryPoint(name='cog', value='cogapp:main', group='console_scripts'),\r\n EntryPoint(name='icdiff', value='icdiff:start', group='console_scripts'),\r\n EntryPoint(name='pycodestyle', value='pycodestyle:_main', group='console_scripts'),\r\n EntryPoint(name='sphinx-autobuild', value='sphinx_autobuild.__main__:main', group='console_scripts'),\r\n EntryPoint(name='sphinx-apidoc', value='sphinx.ext.apidoc:main', group='console_scripts'),\r\n EntryPoint(name='sphinx-autogen', value='sphinx.ext.autosummary.generate:main', group='console_scripts'),\r\n EntryPoint(name='sphinx-build', value='sphinx.cmd.build:main', group='console_scripts'),\r\n EntryPoint(name='sphinx-quickstart', value='sphinx.cmd.quickstart:main', group='console_scripts'),\r\n EntryPoint(name='sphinx-to-sqlite', value='sphinx_to_sqlite.cli:cli', group='console_scripts'),\r\n EntryPoint(name='pybabel', value='babel.messages.frontend:main', group='console_scripts'),\r\n EntryPoint(name='docutils', value='docutils.__main__:main', group='console_scripts'),\r\n EntryPoint(name='isort', value='isort.main:main', group='console_scripts'),\r\n EntryPoint(name='isort-identify-imports', value='isort.main:identify_imports_main', group='console_scripts'),\r\n EntryPoint(name='hupper', value='hupper.cli:main', group='console_scripts'),\r\n EntryPoint(name='sqlite-utils', value='sqlite_utils.cli:cli', group='console_scripts'),\r\n EntryPoint(name='py.test', value='pytest:console_main', group='console_scripts'),\r\n EntryPoint(name='pytest', value='pytest:console_main', group='console_scripts'),\r\n EntryPoint(name='pyflakes', value='pyflakes.api:main', group='console_scripts'),\r\n EntryPoint(name='livereload', value='livereload.cli:main', group='console_scripts'),\r\n EntryPoint(name='uvicorn', value='uvicorn.main:main', group='console_scripts'),\r\n EntryPoint(name='httpx', value='httpx:main', group='console_scripts'),\r\n EntryPoint(name='flake8', value='flake8.main.cli:main', group='console_scripts'),\r\n EntryPoint(name='blacken-docs', value='blacken_docs:main', group='console_scripts'),\r\n EntryPoint(name='pip', value='pip._internal.cli.main:main', group='console_scripts'),\r\n EntryPoint(name='pip3', value='pip._internal.cli.main:main', group='console_scripts'),\r\n EntryPoint(name='pip3.10', value='pip._internal.cli.main:main', group='console_scripts'),\r\n EntryPoint(name='wheel', value='wheel.cli:main', group='console_scripts'),\r\n EntryPoint(name='pygmentize', value='pygments.cmdline:main', group='console_scripts'),\r\n EntryPoint(name='black', value='black:patched_main', group='console_scripts'),\r\n EntryPoint(name='blackd', value='blackd:patched_main [d]', group='console_scripts'),\r\n EntryPoint(name='codespell', value='codespell_lib:_script_main', group='console_scripts'),\r\n EntryPoint(name='tabulate', value='tabulate:_main', group='console_scripts')],\r\n 'datasette': [EntryPoint(name='debug_permissions', value='datasette_debug_permissions', group='datasette'),\r\n EntryPoint(name='codespaces', value='datasette_codespaces', group='datasette'),\r\n EntryPoint(name='vega', value='datasette_vega', group='datasette'),\r\n EntryPoint(name='x_forwarded_host', value='datasette_x_forwarded_host', group='datasette'),\r\n EntryPoint(name='json_html', value='datasette_json_html', group='datasette'),\r\n EntryPoint(name='datasette_write_ui', value='datasette_write_ui', group='datasette'),\r\n EntryPoint(name='pretty_json', value='datasette_pretty_json', group='datasette'),\r\n EntryPoint(name='graphql', value='datasette_graphql', group='datasette')],\r\n 'distutils.commands': [EntryPoint(name='compile_catalog', value='babel.messages.frontend:compile_catalog', group='distutils.commands'),\r\n EntryPoint(name='extract_messages', value='babel.messages.frontend:extract_messages', group='distutils.commands'),\r\n EntryPoint(name='init_catalog', value='babel.messages.frontend:init_catalog', group='distutils.commands'),\r\n EntryPoint(name='update_catalog', value='babel.messages.frontend:update_catalog', group='distutils.commands'),\r\n EntryPoint(name='isort', value='isort.setuptools_commands:ISortCommand', group='distutils.commands'),\r\n EntryPoint(name='alias', value='setuptools.command.alias:alias', group='distutils.commands'),\r\n EntryPoint(name='bdist_egg', value='setuptools.command.bdist_egg:bdist_egg', group='distutils.commands'),\r\n EntryPoint(name='bdist_rpm', value='setuptools.command.bdist_rpm:bdist_rpm', group='distutils.commands'),\r\n EntryPoint(name='build', value='setuptools.command.build:build', group='distutils.commands'),\r\n EntryPoint(name='build_clib', value='setuptools.command.build_clib:build_clib', group='distutils.commands'),\r\n EntryPoint(name='build_ext', value='setuptools.command.build_ext:build_ext', group='distutils.commands'),\r\n EntryPoint(name='build_py', value='setuptools.command.build_py:build_py', group='distutils.commands'),\r\n EntryPoint(name='develop', value='setuptools.command.develop:develop', group='distutils.commands'),\r\n EntryPoint(name='dist_info', value='setuptools.command.dist_info:dist_info', group='distutils.commands'),\r\n EntryPoint(name='easy_install', value='setuptools.command.easy_install:easy_install', group='distutils.commands'),\r\n EntryPoint(name='editable_wheel', value='setuptools.command.editable_wheel:editable_wheel', group='distutils.commands'),\r\n EntryPoint(name='egg_info', value='setuptools.command.egg_info:egg_info', group='distutils.commands'),\r\n EntryPoint(name='install', value='setuptools.command.install:install', group='distutils.commands'),\r\n EntryPoint(name='install_egg_info', value='setuptools.command.install_egg_info:install_egg_info', group='distutils.commands'),\r\n EntryPoint(name='install_lib', value='setuptools.command.install_lib:install_lib', group='distutils.commands'),\r\n EntryPoint(name='install_scripts', value='setuptools.command.install_scripts:install_scripts', group='distutils.commands'),\r\n EntryPoint(name='rotate', value='setuptools.command.rotate:rotate', group='distutils.commands'),\r\n EntryPoint(name='saveopts', value='setuptools.command.saveopts:saveopts', group='distutils.commands'),\r\n EntryPoint(name='sdist', value='setuptools.command.sdist:sdist', group='distutils.commands'),\r\n EntryPoint(name='setopt', value='setuptools.command.setopt:setopt', group='distutils.commands'),\r\n EntryPoint(name='test', value='setuptools.command.test:test', group='distutils.commands'),\r\n EntryPoint(name='upload_docs', value='setuptools.command.upload_docs:upload_docs', group='distutils.commands'),\r\n EntryPoint(name='bdist_wheel', value='wheel.bdist_wheel:bdist_wheel', group='distutils.commands')],\r\n 'distutils.setup_keywords': [EntryPoint(name='message_extractors', value='babel.messages.frontend:check_message_extractors', group='distutils.setup_keywords'),\r\n EntryPoint(name='cffi_modules', value='cffi.setuptools_ext:cffi_modules', group='distutils.setup_keywords'),\r\n EntryPoint(name='dependency_links', value='setuptools.dist:assert_string_list', group='distutils.setup_keywords'),\r\n EntryPoint(name='eager_resources', value='setuptools.dist:assert_string_list', group='distutils.setup_keywords'),\r\n EntryPoint(name='entry_points', value='setuptools.dist:check_entry_points', group='distutils.setup_keywords'),\r\n EntryPoint(name='exclude_package_data', value='setuptools.dist:check_package_data', group='distutils.setup_keywords'),\r\n EntryPoint(name='extras_require', value='setuptools.dist:check_extras', group='distutils.setup_keywords'),\r\n EntryPoint(name='include_package_data', value='setuptools.dist:assert_bool', group='distutils.setup_keywords'),\r\n EntryPoint(name='install_requires', value='setuptools.dist:check_requirements', group='distutils.setup_keywords'),\r\n EntryPoint(name='namespace_packages', value='setuptools.dist:check_nsp', group='distutils.setup_keywords'),\r\n EntryPoint(name='package_data', value='setuptools.dist:check_package_data', group='distutils.setup_keywords'),\r\n EntryPoint(name='packages', value='setuptools.dist:check_packages', group='distutils.setup_keywords'),\r\n EntryPoint(name='python_requires', value='setuptools.dist:check_specifier', group='distutils.setup_keywords'),\r\n EntryPoint(name='setup_requires', value='setuptools.dist:check_requirements', group='distutils.setup_keywords'),\r\n EntryPoint(name='test_loader', value='setuptools.dist:check_importable', group='distutils.setup_keywords'),\r\n EntryPoint(name='test_runner', value='setuptools.dist:check_importable', group='distutils.setup_keywords'),\r\n EntryPoint(name='test_suite', value='setuptools.dist:check_test_suite', group='distutils.setup_keywords'),\r\n EntryPoint(name='tests_require', value='setuptools.dist:check_requirements', group='distutils.setup_keywords'),\r\n EntryPoint(name='use_2to3', value='setuptools.dist:invalid_unless_false', group='distutils.setup_keywords'),\r\n EntryPoint(name='zip_safe', value='setuptools.dist:assert_bool', group='distutils.setup_keywords')],\r\n 'egg_info.writers': [EntryPoint(name='PKG-INFO', value='setuptools.command.egg_info:write_pkg_info', group='egg_info.writers'),\r\n EntryPoint(name='dependency_links.txt', value='setuptools.command.egg_info:overwrite_arg', group='egg_info.writers'),\r\n EntryPoint(name='depends.txt', value='setuptools.command.egg_info:warn_depends_obsolete', group='egg_info.writers'),\r\n EntryPoint(name='eager_resources.txt', value='setuptools.command.egg_info:overwrite_arg', group='egg_info.writers'),\r\n EntryPoint(name='entry_points.txt', value='setuptools.command.egg_info:write_entries', group='egg_info.writers'),\r\n EntryPoint(name='namespace_packages.txt', value='setuptools.command.egg_info:overwrite_arg', group='egg_info.writers'),\r\n EntryPoint(name='requires.txt', value='setuptools.command.egg_info:write_requirements', group='egg_info.writers'),\r\n EntryPoint(name='top_level.txt', value='setuptools.command.egg_info:write_toplevel_names', group='egg_info.writers')],\r\n 'flake8.extension': [EntryPoint(name='C90', value='mccabe:McCabeChecker', group='flake8.extension'),\r\n EntryPoint(name='E', value='flake8.plugins.pycodestyle:pycodestyle_logical', group='flake8.extension'),\r\n EntryPoint(name='F', value='flake8.plugins.pyflakes:FlakesChecker', group='flake8.extension'),\r\n EntryPoint(name='W', value='flake8.plugins.pycodestyle:pycodestyle_physical', group='flake8.extension')],\r\n 'flake8.report': [EntryPoint(name='default', value='flake8.formatting.default:Default', group='flake8.report'),\r\n EntryPoint(name='pylint', value='flake8.formatting.default:Pylint', group='flake8.report'),\r\n EntryPoint(name='quiet-filename', value='flake8.formatting.default:FilenameOnly', group='flake8.report'),\r\n EntryPoint(name='quiet-nothing', value='flake8.formatting.default:Nothing', group='flake8.report')],\r\n 'pylama.linter': [EntryPoint(name='isort', value='isort.pylama_isort:Linter', group='pylama.linter')],\r\n 'pytest11': [EntryPoint(name='icdiff', value='pytest_icdiff', group='pytest11'),\r\n EntryPoint(name='asyncio', value='pytest_asyncio.plugin', group='pytest11'),\r\n EntryPoint(name='xdist', value='xdist.plugin', group='pytest11'),\r\n EntryPoint(name='xdist.looponfail', value='xdist.looponfail', group='pytest11'),\r\n EntryPoint(name='timeout', value='pytest_timeout', group='pytest11'),\r\n EntryPoint(name='anyio', value='anyio.pytest_plugin', group='pytest11')],\r\n 'setuptools.finalize_distribution_options': [EntryPoint(name='keywords', value='setuptools.dist:Distribution._finalize_setup_keywords', group='setuptools.finalize_distribution_options'),\r\n EntryPoint(name='parent_finalize', value='setuptools.dist:_Distribution.finalize_options', group='setuptools.finalize_distribution_options')],\r\n 'sphinx.html_themes': [EntryPoint(name='alabaster', value='alabaster', group='sphinx.html_themes'),\r\n EntryPoint(name='basic-ng', value='sphinx_basic_ng', group='sphinx.html_themes'),\r\n EntryPoint(name='furo', value='furo', group='sphinx.html_themes')],\r\n 'sqlite_utils': [EntryPoint(name='hello_world', value='sqlite_utils_hello_world', group='sqlite_utils')]}\r\n```", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1662951875, "label": "DeprecationWarning: pkg_resources is deprecated as an API"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/2057#issuecomment-1722266513", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/2057", "id": 1722266513, "node_id": "IC_kwDOBm6k_c5mp7OR", "user": {"value": 9599, "label": "simonw"}, "created_at": "2023-09-16T16:36:09Z", "updated_at": "2023-09-16T16:36:09Z", "author_association": "OWNER", "body": "Now I need to switch out `pkg_resources` in `plugins.py`:\r\n\r\nhttps://github.com/simonw/datasette/blob/852f5014853943fa27f43ddaa2d442545b3259fb/datasette/plugins.py#L33-L74", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1662951875, "label": "DeprecationWarning: pkg_resources is deprecated as an API"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/2057#issuecomment-1722265848", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/2057", "id": 1722265848, "node_id": "IC_kwDOBm6k_c5mp7D4", "user": {"value": 9599, "label": "simonw"}, "created_at": "2023-09-16T16:32:42Z", "updated_at": "2023-09-16T16:32:42Z", "author_association": "OWNER", "body": "Here's the exception it uses:\r\n```pycon\r\n>>> importlib.metadata.version(\"datasette\")\r\n'1.0a6'\r\n>>> importlib.metadata.version(\"datasette2\")\r\nTraceback (most recent call last):\r\n File \"\", line 1, in \r\n File \"/opt/homebrew/Caskroom/miniconda/base/lib/python3.10/importlib/metadata/__init__.py\", line 996, in version\r\n return distribution(distribution_name).version\r\n File \"/opt/homebrew/Caskroom/miniconda/base/lib/python3.10/importlib/metadata/__init__.py\", line 969, in distribution\r\n return Distribution.from_name(distribution_name)\r\n File \"/opt/homebrew/Caskroom/miniconda/base/lib/python3.10/importlib/metadata/__init__.py\", line 548, in from_name\r\n raise PackageNotFoundError(name)\r\nimportlib.metadata.PackageNotFoundError: No package metadata was found for datasette2\r\n```", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1662951875, "label": "DeprecationWarning: pkg_resources is deprecated as an API"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/2057#issuecomment-1722258980", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/2057", "id": 1722258980, "node_id": "IC_kwDOBm6k_c5mp5Yk", "user": {"value": 9599, "label": "simonw"}, "created_at": "2023-09-16T15:56:45Z", "updated_at": "2023-09-16T15:56:45Z", "author_association": "OWNER", "body": "Weird, I still can't get the warning to show even with this:\r\n```python\r\n@pytest.mark.asyncio\r\nasync def test_plugin_is_installed():\r\n datasette = Datasette(memory=True)\r\n\r\n class DummyPlugin:\r\n __name__ = \"DummyPlugin\"\r\n\r\n @hookimpl\r\n def actors_from_ids(self, datasette, actor_ids):\r\n return {}\r\n\r\n try:\r\n pm.register(DummyPlugin(), name=\"DummyPlugin\")\r\n response = await datasette.client.get(\"/-/plugins.json\")\r\n assert response.status_code == 200\r\n installed_plugins = {p[\"name\"] for p in response.json()}\r\n assert \"DummyPlugin\" in installed_plugins\r\n\r\n finally:\r\n pm.unregister(name=\"ReturnNothingPlugin\")\r\n```", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1662951875, "label": "DeprecationWarning: pkg_resources is deprecated as an API"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/2057#issuecomment-1722257328", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/2057", "id": 1722257328, "node_id": "IC_kwDOBm6k_c5mp4-w", "user": {"value": 9599, "label": "simonw"}, "created_at": "2023-09-16T15:47:32Z", "updated_at": "2023-09-16T15:47:32Z", "author_association": "OWNER", "body": "Frustrating that this warning doesn't show up in the Datasette test suite itself. It shows up in plugin test suites that run this test:\r\n```python\r\n@pytest.mark.asyncio\r\nasync def test_plugin_is_installed():\r\n datasette = Datasette(memory=True)\r\n response = await datasette.client.get(\"/-/plugins.json\")\r\n assert response.status_code == 200\r\n installed_plugins = {p[\"name\"] for p in response.json()}\r\n assert \"datasette-chronicle\" in installed_plugins\r\n```\r\nIf you run that test inside Datasette core `installed_plugins` is an empty set, which presumably is why the warning doesn't get triggered there.", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1662951875, "label": "DeprecationWarning: pkg_resources is deprecated as an API"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/2057#issuecomment-1503838640", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/2057", "id": 1503838640, "node_id": "IC_kwDOBm6k_c5ZosGw", "user": {"value": 9599, "label": "simonw"}, "created_at": "2023-04-11T17:48:23Z", "updated_at": "2023-04-11T17:48:23Z", "author_association": "OWNER", "body": "> This looks wrong to me - I would expect something like `is_directory()` not `is_file()` for telling if `static/` is a directory.\r\n\r\nI was right about that:\r\n\r\n```pycon\r\n>>> importlib.resources.files('datasette_graphql')\r\nPosixPath('/Users/simon/.local/share/virtualenvs/datasette-big-local-6Yn-280V/lib/python3.11/site-packages/datasette_graphql')\r\n>>> importlib.resources.files('datasette_graphql').joinpath(\"static\")\r\nPosixPath('/Users/simon/.local/share/virtualenvs/datasette-big-local-6Yn-280V/lib/python3.11/site-packages/datasette_graphql/static')\r\n>>> p = importlib.resources.files('datasette_graphql').joinpath(\"static\")\r\n>>> p\r\nPosixPath('/Users/simon/.local/share/virtualenvs/datasette-big-local-6Yn-280V/lib/python3.11/site-packages/datasette_graphql/static')\r\n>>> p.is_\r\np.is_absolute() p.is_char_device() p.is_fifo() p.is_mount() p.is_reserved() p.is_symlink() \r\np.is_block_device() p.is_dir() p.is_file() p.is_relative_to( p.is_socket() \r\n>>> p.is_dir()\r\nTrue\r\n>>> p.is_file()\r\nFalse\r\n```", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1662951875, "label": "DeprecationWarning: pkg_resources is deprecated as an API"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/2057#issuecomment-1503832422", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/2057", "id": 1503832422, "node_id": "IC_kwDOBm6k_c5Zoqlm", "user": {"value": 9599, "label": "simonw"}, "created_at": "2023-04-11T17:42:57Z", "updated_at": "2023-04-11T17:46:42Z", "author_association": "OWNER", "body": "I ran this prompt against ChatGPT with the Browsing alpha:\r\n\r\n> ```python\r\n> if pkg_resources.resource_isdir(plugin.__name__, \"static\"):\r\n> static_path = pkg_resources.resource_filename(\r\n> plugin.__name__, \"static\"\r\n> )\r\n> if pkg_resources.resource_isdir(plugin.__name__, \"templates\"):\r\n> templates_path = pkg_resources.resource_filename(\r\n> plugin.__name__, \"templates\"\r\n> )\r\n> ```\r\n> This code gives a deprecation warning in Python 3.11 - fix it\r\n\r\nIt looked up the fix for me:\r\n\r\n\"image\"\r\n\r\nAnd suggested:\r\n\r\n```python\r\nimport importlib.resources\r\n\r\n# Replace pkg_resources.resource_isdir with importlib.resources.files().is_file()\r\nif importlib.resources.files(plugin.__name__).joinpath(\"static\").is_file():\r\n static_path = importlib.resources.as_file(\r\n importlib.resources.files(plugin.__name__).joinpath(\"static\")\r\n )\r\nif importlib.resources.files(plugin.__name__).joinpath(\"templates\").is_file():\r\n templates_path = importlib.resources.as_file(\r\n importlib.resources.files(plugin.__name__).joinpath(\"templates\")\r\n )\r\n```\r\nThis looks wrong to me - I would expect something like `is_directory()` not `is_file()` for telling if `static/` is a directory.", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1662951875, "label": "DeprecationWarning: pkg_resources is deprecated as an API"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/2057#issuecomment-1503833906", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/2057", "id": 1503833906, "node_id": "IC_kwDOBm6k_c5Zoq8y", "user": {"value": 9599, "label": "simonw"}, "created_at": "2023-04-11T17:44:16Z", "updated_at": "2023-04-11T17:45:45Z", "author_association": "OWNER", "body": "Another prompt:\r\n\r\n> How to fix this:\r\n>\r\n> `pkg_resources.get_distribution(package).version`\r\n\r\nResponse:\r\n\r\n\"image\"\r\n\r\n```python\r\nimport importlib.metadata\r\n\r\n# Get the version number of the specified package\r\npackage_version = importlib.metadata.version(package)\r\n```\r\n\r\nThat seems to work:\r\n\r\n```pycon\r\n>>> import importlib.metadata\r\n>>> importlib.metadata.version(\"datasette\")\r\n'0.64.2'\r\n>>> importlib.metadata.version(\"pluggy\")\r\n'1.0.0'\r\n>>> importlib.metadata.version(\"not-a-package\")\r\n...\r\nimportlib.metadata.PackageNotFoundError: No package metadata was found for not-a-package\r\n```\r\n", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 1662951875, "label": "DeprecationWarning: pkg_resources is deprecated as an API"}, "performed_via_github_app": null}