From 4cbdfcc07d36c36ac77243d586836b91f90be67c Mon Sep 17 00:00:00 2001 From: Simon Willison Date: Thu, 11 Dec 2025 17:32:58 -0800 Subject: [PATCH] dependency-groups and uv (#2611) * dependency-groups and uv, closes #2610 * New .readthedocs config for --group dev --- .github/workflows/deploy-latest.yml | 3 +- .github/workflows/publish.yml | 4 +- .github/workflows/spellcheck.yml | 2 +- .github/workflows/test-coverage.yml | 2 +- .github/workflows/test-sqlite-support.yml | 2 +- .github/workflows/test.yml | 5 +- .readthedocs.yaml | 25 ++++----- Justfile | 8 +-- docs/contributing.rst | 65 ++++++++++------------- pyproject.toml | 28 +++++----- 10 files changed, 67 insertions(+), 77 deletions(-) diff --git a/.github/workflows/deploy-latest.yml b/.github/workflows/deploy-latest.yml index 9f53b01e..7349a1ab 100644 --- a/.github/workflows/deploy-latest.yml +++ b/.github/workflows/deploy-latest.yml @@ -24,8 +24,7 @@ jobs: - name: Install Python dependencies run: | python -m pip install --upgrade pip - python -m pip install -e .[test] - python -m pip install -e .[docs] + python -m pip install . --group dev python -m pip install sphinx-to-sqlite==0.1a1 - name: Run tests if: ${{ github.ref == 'refs/heads/main' }} diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index e94d0bdd..2e8cea9c 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -23,7 +23,7 @@ jobs: cache-dependency-path: pyproject.toml - name: Install dependencies run: | - pip install -e '.[test]' + pip install . --group dev - name: Run tests run: | pytest @@ -65,7 +65,7 @@ jobs: cache-dependency-path: pyproject.toml - name: Install dependencies run: | - python -m pip install -e .[docs] + python -m pip install . --group dev python -m pip install sphinx-to-sqlite==0.1a1 - name: Build docs.db run: |- diff --git a/.github/workflows/spellcheck.yml b/.github/workflows/spellcheck.yml index 7c5370ce..d42ae96b 100644 --- a/.github/workflows/spellcheck.yml +++ b/.github/workflows/spellcheck.yml @@ -18,7 +18,7 @@ jobs: cache-dependency-path: '**/pyproject.toml' - name: Install dependencies run: | - pip install -e '.[docs]' + pip install . --group dev - name: Check spelling run: | codespell README.md --ignore-words docs/codespell-ignore-words.txt diff --git a/.github/workflows/test-coverage.yml b/.github/workflows/test-coverage.yml index 8d73b64d..1b3d2f2c 100644 --- a/.github/workflows/test-coverage.yml +++ b/.github/workflows/test-coverage.yml @@ -25,7 +25,7 @@ jobs: - name: Install Python dependencies run: | python -m pip install --upgrade pip - python -m pip install -e .[test] + python -m pip install . --group dev python -m pip install pytest-cov - name: Run tests run: |- diff --git a/.github/workflows/test-sqlite-support.yml b/.github/workflows/test-sqlite-support.yml index 76ea138a..c81a3c0b 100644 --- a/.github/workflows/test-sqlite-support.yml +++ b/.github/workflows/test-sqlite-support.yml @@ -45,7 +45,7 @@ jobs: (cd tests && gcc ext.c -fPIC -shared -o ext.so) - name: Install dependencies run: | - pip install -e '.[test]' + pip install . --group dev pip freeze - name: Run tests run: | diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 1e5e03d2..3790c788 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -25,7 +25,7 @@ jobs: (cd tests && gcc ext.c -fPIC -shared -o ext.so) - name: Install dependencies run: | - pip install -e '.[test]' + pip install . --group dev pip freeze - name: Run tests run: | @@ -33,9 +33,6 @@ jobs: pytest -m "serial" # And the test that exceeds a localhost HTTPS server tests/test_datasette_https_server.sh - - name: Install docs dependencies - run: | - pip install -e '.[docs]' - name: Black run: black --check . - name: Check if cog needs to be run diff --git a/.readthedocs.yaml b/.readthedocs.yaml index 5b30e75a..8b3e54aa 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -1,16 +1,17 @@ version: 2 -build: - os: ubuntu-20.04 - tools: - python: "3.11" - sphinx: - configuration: docs/conf.py + configuration: docs/conf.py -python: - install: - - method: pip - path: . - extra_requirements: - - docs +build: + os: ubuntu-24.04 + tools: + python: "3.13" + jobs: + install: + - pip install --upgrade pip + - pip install . --group dev + +formats: +- pdf +- epub diff --git a/Justfile b/Justfile index a47662c3..8c50e5ca 100644 --- a/Justfile +++ b/Justfile @@ -5,7 +5,7 @@ export DATASETTE_SECRET := "not_a_secret" # Setup project @init: - uv sync --extra test --extra docs + uv sync # Run pytest with supplied options @test *options: init @@ -21,15 +21,15 @@ export DATASETTE_SECRET := "not_a_secret" @lint: codespell uv run black . --check uv run flake8 - uv run --extra test cog --check README.md docs/*.rst + uv run cog --check README.md docs/*.rst # Rebuild docs with cog @cog: - uv run --extra test cog -r README.md docs/*.rst + uv run cog -r README.md docs/*.rst # Serve live docs on localhost:8000 @docs: cog blacken-docs - uv run --extra docs make -C docs livehtml + uv run make -C docs livehtml # Build docs as static HTML @docs-build: cog blacken-docs diff --git a/docs/contributing.rst b/docs/contributing.rst index 6be0247c..3d41a125 100644 --- a/docs/contributing.rst +++ b/docs/contributing.rst @@ -32,17 +32,18 @@ If you want to get started without creating your own fork, you can do this inste git clone git@github.com:simonw/datasette -The next step is to create a virtual environment for your project and use it to install Datasette's dependencies:: +The quickest way to set up a development environment is to use `uv `__. From the repository root you can run the tests directly:: cd datasette - # Create a virtual environment in ./venv - python3 -m venv ./venv - # Now activate the virtual environment, so pip can install into it - source venv/bin/activate - # Install Datasette and its testing dependencies - python3 -m pip install -e '.[test]' + uv run pytest -That last line does most of the work: ``pip install -e`` means "install this package in a way that allows me to edit the source code in place". The ``.[test]`` option means "install the optional testing dependencies as well". +This will create a local ``.venv/`` and install Datasette plus its development dependencies. + +If you prefer to manage your own virtual environment with pip, create and activate one and then install the development dependency group:: + + python3 -m venv ./venv + source venv/bin/activate + python3 -m pip install -e . --group dev .. _contributing_running_tests: @@ -51,15 +52,15 @@ Running the tests Once you have done this, you can run the Datasette unit tests from inside your ``datasette/`` directory using `pytest `__ like so:: - pytest + uv run pytest You can run the tests faster using multiple CPU cores with `pytest-xdist `__ like this:: - pytest -n auto -m "not serial" + uv run pytest -n auto -m "not serial" ``-n auto`` detects the number of available cores automatically. The ``-m "not serial"`` skips tests that don't work well in a parallel test environment. You can run those tests separately like so:: - pytest -m "serial" + uv run pytest -m "serial" .. _contributing_using_fixtures: @@ -72,11 +73,11 @@ You're going to need at least one SQLite database. A quick way to get started is You can create a copy of that database by running this command:: - python tests/fixtures.py fixtures.db + uv run python tests/fixtures.py fixtures.db Now you can run Datasette against the new fixtures database like so:: - datasette fixtures.db + uv run datasette fixtures.db This will start a server at ``http://127.0.0.1:8001/``. @@ -84,15 +85,14 @@ Any changes you make in the ``datasette/templates`` or ``datasette/static`` fold If you want to change Datasette's Python code you can use the ``--reload`` option to cause Datasette to automatically reload any time the underlying code changes:: - datasette --reload fixtures.db + uv run datasette --reload fixtures.db You can also use the ``fixtures.py`` script to recreate the testing version of ``metadata.json`` used by the unit tests. To do that:: - python tests/fixtures.py fixtures.db fixtures-metadata.json - + uv run python tests/fixtures.py fixtures.db fixtures-metadata.json Or to output the plugins used by the tests, run this:: - python tests/fixtures.py fixtures.db fixtures-metadata.json fixtures-plugins + uv run python tests/fixtures.py fixtures.db fixtures-metadata.json fixtures-plugins Test tables written to fixtures.db - metadata written to fixtures-metadata.json Wrote plugin: fixtures-plugins/register_output_renderer.py @@ -103,7 +103,7 @@ Or to output the plugins used by the tests, run this:: Then run Datasette like this:: - datasette fixtures.db -m fixtures-metadata.json --plugins-dir=fixtures-plugins/ + uv run datasette fixtures.db -m fixtures-metadata.json --plugins-dir=fixtures-plugins/ .. _contributing_debugging: @@ -114,11 +114,11 @@ Any errors that occur while Datasette is running while display a stack trace on You can tell Datasette to open an interactive ``pdb`` (or ``ipdb``, if present) debugger session if an error occurs using the ``--pdb`` option:: - datasette --pdb fixtures.db + uv run datasette --pdb fixtures.db For `ipdb `__, first run this:: - datasette install ipdb + uv run datasette install ipdb .. _contributing_formatting: @@ -145,9 +145,9 @@ Or run both at the same time:: Running Black ~~~~~~~~~~~~~ -Black will be installed when you run ``pip install -e '.[test]'``. To test that your code complies with Black, run the following in your root ``datasette`` repository checkout:: +Black is installed as part of the development dependency group. To test that your code complies with Black, run the following in your root ``datasette`` repository checkout:: - black . --check + uv run black . --check :: @@ -156,7 +156,7 @@ Black will be installed when you run ``pip install -e '.[test]'``. To test that If any of your code does not conform to Black you can run this to automatically fix those problems:: - black . + uv run black . :: @@ -171,7 +171,7 @@ blacken-docs The `blacken-docs `__ command applies Black formatting rules to code examples in the documentation. Run it like this:: - blacken-docs -l 60 docs/*.rst + uv run blacken-docs -l 60 docs/*.rst .. _contributing_formatting_prettier: @@ -208,17 +208,10 @@ Datasette's documentation lives in the ``docs/`` directory and is deployed autom The documentation is written using reStructuredText. You may find this article on `The subset of reStructuredText worth committing to memory `__ useful. -You can build it locally by installing ``sphinx`` and ``sphinx_rtd_theme`` in your Datasette development environment and then running ``make html`` directly in the ``docs/`` directory:: +You can build it locally once you have installed the development dependency group (which includes Sphinx and related tools) and then running ``make html`` directly in the ``docs/`` directory:: - # You may first need to activate your virtual environment: - source venv/bin/activate - - # Install the dependencies needed to build the docs - pip install -e .[docs] - - # Now build the docs cd docs/ - make html + uv run make html This will create the HTML version of the documentation in ``docs/_build/html``. You can open it in your browser like so:: @@ -228,9 +221,9 @@ Any time you make changes to a ``.rst`` file you can re-run ``make html`` to upd For added productivity, you can use use `sphinx-autobuild `__ to run Sphinx in auto-build mode. This will run a local webserver serving the docs that automatically rebuilds them and refreshes the page any time you hit save in your editor. -``sphinx-autobuild`` will have been installed when you ran ``pip install -e .[docs]``. In your ``docs/`` directory you can start the server by running the following:: +``sphinx-autobuild`` is included in the development dependency group. In your ``docs/`` directory you can start the server by running the following:: - make livehtml + uv run make livehtml Now browse to ``http://localhost:8000/`` to view the documentation. Any edits you make should be instantly reflected in your browser. @@ -243,7 +236,7 @@ Some pages of documentation (in particular the :ref:`cli_reference`) are automat To update these pages, run the following command:: - cog -r docs/*.rst + uv run cog -r docs/*.rst .. _contributing_continuous_deployment: diff --git a/pyproject.toml b/pyproject.toml index f3053447..87884341 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -55,20 +55,8 @@ CI = "https://github.com/simonw/datasette/actions?query=workflow%3ATest" [project.scripts] datasette = "datasette.cli:cli" -[project.optional-dependencies] -docs = [ - "Sphinx==7.4.7", - "furo==2025.9.25", - "sphinx-autobuild", - "codespell>=2.2.5", - "blacken-docs", - "sphinx-copybutton", - "sphinx-inline-tabs", - "myst-parser", - "sphinx-markdown-builder", - "ruamel.yaml", -] -test = [ +[dependency-groups] +dev = [ "pytest>=9", "pytest-xdist>=2.2.1", "pytest-asyncio>=1.2.0", @@ -78,7 +66,19 @@ test = [ "pytest-timeout>=1.4.2", "trustme>=0.7", "cogapp>=3.3.0", + # docs + "Sphinx==7.4.7", + "furo==2025.9.25", + "sphinx-autobuild", + "codespell>=2.2.5", + "sphinx-copybutton", + "sphinx-inline-tabs", + "myst-parser", + "sphinx-markdown-builder", + "ruamel.yaml", ] + +[project.optional-dependencies] rich = ["rich"] [build-system]