From 7024c7d2936adf8728bf755f0a3aedf6abf0498f Mon Sep 17 00:00:00 2001 From: Theodore Turocy Date: Sat, 29 Aug 2026 16:30:14 +0100 Subject: [PATCH] Adjust dependency on/relationship with `gtdraw`. This removes the overall `pygambit` package dependency on `gtdraw`. The package itself does not depend on `gtdraw`; only the tutorials and catalog (documentation) do. * Tutorials have been adjusted to fall back gracefully when `gtdraw` is not installed. * The CI scripts now install `gtdraw` from its `main` branch on GitHub to pick up the latest version. * Updates the developer documentation to note the developer needs to install `gtdraw`, for example, to work with extending the catalog. --- .github/workflows/python.yml | 8 ++++---- .readthedocs.yml | 2 +- ChangeLog | 8 ++++++++ doc/developer.build.rst | 5 ++++- doc/developer.catalog.rst | 1 + doc/tutorials/02_extensive_form.ipynb | 12 +++++++++-- doc/tutorials/03_stripped_down_poker.ipynb | 20 +++++++++++++------ .../agent_versus_non_agent_regret.ipynb | 17 +++++++++++++++- .../openspiel.ipynb | 10 +++++++++- doc/tutorials/running_locally.rst | 5 +++++ pyproject.toml | 1 - 11 files changed, 72 insertions(+), 17 deletions(-) diff --git a/.github/workflows/python.yml b/.github/workflows/python.yml index a10db93319..a3b36eac14 100644 --- a/.github/workflows/python.yml +++ b/.github/workflows/python.yml @@ -30,7 +30,7 @@ jobs: cd dist sdist=$(ls pygambit-*.tar.gz) pip install -v "${sdist}[test,doc]" - pip install "draw-tree @ git+https://github.com/gambitproject/draw_tree.git@v0.9.1" + pip install "gtdraw @ git+https://github.com/gambitproject/gtdraw.git@main" - name: Run tests run: pytest --run-tutorials @@ -53,7 +53,7 @@ jobs: - name: Build extension run: | python -m pip install -v .[test,doc] - pip install "draw-tree @ git+https://github.com/gambitproject/draw_tree.git@v0.9.1" + pip install "gtdraw @ git+https://github.com/gambitproject/gtdraw.git@main" - name: Run tests run: pytest --run-tutorials @@ -76,7 +76,7 @@ jobs: - name: Build extension run: | python -m pip install -v .[test,doc] - pip install "draw-tree @ git+https://github.com/gambitproject/draw_tree.git@v0.9.1" + pip install "gtdraw @ git+https://github.com/gambitproject/gtdraw.git@main" - name: Run tests run: pytest --run-tutorials @@ -100,6 +100,6 @@ jobs: shell: bash run: | python -m pip install -v .[test,doc] - pip install "draw-tree @ git+https://github.com/gambitproject/draw_tree.git@v0.9.1" + pip install "gtdraw @ git+https://github.com/gambitproject/gtdraw.git@main" - name: Run tests run: pytest --run-tutorials diff --git a/.readthedocs.yml b/.readthedocs.yml index d06f69e2b6..13359f0490 100644 --- a/.readthedocs.yml +++ b/.readthedocs.yml @@ -17,7 +17,7 @@ build: - pdf2svg jobs: post_install: - - pip install "draw-tree @ git+https://github.com/gambitproject/draw_tree.git@v0.9.1" + - pip install "gtdraw @ git+https://github.com/gambitproject/gtdraw.git@main" # Create RST for catalog table in docs - $READTHEDOCS_VIRTUALENV_PATH/bin/python build_support/catalog/update.py diff --git a/ChangeLog b/ChangeLog index cf2523b455..a7fe1bc2cc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -25,6 +25,14 @@ - `Game.new_table` no longer creates an outcome for every contingency; a new strategic game has no outcomes, and every contingency is initially null. Outcomes are created as they are needed; games built by `Game.from_arrays` and `Game.from_dict` are unaffected. (#1061) +- Tutorial notebooks that use `gtdraw` to draw game trees now degrade gracefully if it isn't + installed: the drawing cells print a short note instead of raising `ImportError`, so the rest + of the tutorial (which doesn't otherwise depend on `gtdraw`) still runs. `gtdraw` depends on a + LaTeX installation, so this lets the tutorials be run without that heavier local setup. + +### Removed +- `gtdraw` is no longer part of the `doc` optional-dependency group. Install it separately + (`pip install gtdraw`) to run tutorials locally or build the documentation. ## [17.0.0-alpha.2] - 2026-08-21 diff --git a/doc/developer.build.rst b/doc/developer.build.rst index 5f4b86c6d3..98717f736e 100644 --- a/doc/developer.build.rst +++ b/doc/developer.build.rst @@ -189,10 +189,13 @@ Use `pip` to install from the **root directory of the source tree**: python -m venv venv source venv/bin/activate python -m pip install ".[test,doc]" + pip install gtdraw .. tip:: - The "test" and "doc" optional dependencies are useful for developers wishing to run the test suite or build this documentation locally. + The "test" and "doc" optional dependencies are useful for developers wishing to run the test suite or build this documentation locally. `gtdraw `_, used to + draw game trees in the tutorials and the games catalog, is installed separately rather than as + part of the "doc" extra, since it is not needed by the installed `pygambit` package itself. Once installed, simply ``import pygambit`` in your Python shell or diff --git a/doc/developer.catalog.rst b/doc/developer.catalog.rst index 5f6a67a5b6..b69c2a519f 100644 --- a/doc/developer.catalog.rst +++ b/doc/developer.catalog.rst @@ -22,6 +22,7 @@ Currently supported representations are: .. code-block:: bash pip install -e ".[doc]" + pip install gtdraw 1. **Create or edit a game file:** diff --git a/doc/tutorials/02_extensive_form.ipynb b/doc/tutorials/02_extensive_form.ipynb index bba579e9f6..599924774e 100644 --- a/doc/tutorials/02_extensive_form.ipynb +++ b/doc/tutorials/02_extensive_form.ipynb @@ -25,7 +25,8 @@ "- If the Seller chooses **Abuse**, the Buyer receives a payoff of `-1` and the Seller receives a payoff of `2`.\n", "\n", "In addition to `pygambit`, this tutorial introduces the `gtdraw` package, which can be used to draw extensive form games in Python.\n", - "If you're running this tutorial on your local machine, you'll need to install the requirements for [gtdraw](https://www.gambit-project.org/gtdraw/), which include LaTeX, in order to run the `gtdraw` cells.\n", + "`gtdraw` is optional here; if it isn't available, the drawing cells below print a short note.\n", + "To install `gtdraw`, see [gtdraw](https://www.gambit-project.org/gtdraw/).\n", "Another option for visualising extensive form games is to install the Gambit GUI and use it to load the EFG file generated at the end of this tutorial." ] }, @@ -36,7 +37,14 @@ "metadata": {}, "outputs": [], "source": [ - "from gtdraw import draw\n", + "try:\n", + " from gtdraw import draw\n", + "except ImportError:\n", + " def draw(*args, **kwargs):\n", + " print(\n", + " \"gtdraw is not installed, so the game tree cannot be drawn here; \"\n", + " \"see https://www.gambit-project.org/gtdraw/ to install it.\"\n", + " )\n", "\n", "import pygambit as gbt" ] diff --git a/doc/tutorials/03_stripped_down_poker.ipynb b/doc/tutorials/03_stripped_down_poker.ipynb index 113330199e..2925af1e2e 100644 --- a/doc/tutorials/03_stripped_down_poker.ipynb +++ b/doc/tutorials/03_stripped_down_poker.ipynb @@ -32,8 +32,9 @@ " - If she has a King, then she wins the pot.\n", " - If she has a Queen, then Bob wins the pot.\n", "\n", - "In addition to `pygambit`, this tutorial uses the `gtdraw` package, which can be used to draw extensive form games in Python.\n", - "If you're running this tutorial on your local machine, you'll need to install the requirements for [gtdraw](https://www.gambit-project.org/gtdraw/), which include LaTeX, in order to run the `gtdraw` cells.\n", + "In addition to `pygambit`, this tutorial introduces the `gtdraw` package, which can be used to draw extensive form games in Python.\n", + "`gtdraw` is optional here; if it isn't available, the drawing cells below print a short note.\n", + "To install `gtdraw`, see [gtdraw](https://www.gambit-project.org/gtdraw/).\n", "Another option for visualising extensive form games is to install the Gambit GUI and use it to load a saved EFG file." ] }, @@ -44,7 +45,14 @@ "metadata": {}, "outputs": [], "source": [ - "from gtdraw import draw\n", + "try:\n", + " from gtdraw import draw\n", + "except ImportError:\n", + " def draw(*args, **kwargs):\n", + " print(\n", + " \"gtdraw is not installed, so the game tree cannot be drawn here; \"\n", + " \"see https://www.gambit-project.org/gtdraw/ to install it.\"\n", + " )\n", "\n", "import pygambit as gbt" ] @@ -160,7 +168,7 @@ "source": [ "The loop above causes each of the newly-appended moves to be in new information sets, reflecting the fact that Alice's decision depends on the knowledge of which card she holds.\n", "\n", - "In contrast, Bob does not know Alice\u2019s card, and therefore cannot distinguish between the two nodes at which he has to make his decision:\n", + "In contrast, Bob does not know Alice’s card, and therefore cannot distinguish between the two nodes at which he has to make his decision:\n", "\n", " - Chance player chooses King, then Alice Bets: `g.root.children[\"King\"].children[\"Bet\"]`\n", " - Chance player chooses Queen, then Alice Bets: `g.root.children[\"Queen\"].children[\"Bet\"]`\n", @@ -396,7 +404,7 @@ "id": "1f121d48", "metadata": {}, "source": [ - "Now let's look at Bob\u2019s strategy:" + "Now let's look at Bob’s strategy:" ] }, { @@ -414,7 +422,7 @@ "id": "e906c4c4", "metadata": {}, "source": [ - "Bob Calls Alice\u2019s Bet two-thirds of the time.\n", + "Bob Calls Alice’s Bet two-thirds of the time.\n", "\n", "Since Bob has just one information set, we can get its representative node and index\n", "the profile directly by it to read off a single action's probability:" diff --git a/doc/tutorials/advanced_tutorials/agent_versus_non_agent_regret.ipynb b/doc/tutorials/advanced_tutorials/agent_versus_non_agent_regret.ipynb index e6bb5857db..5ac1957ab8 100644 --- a/doc/tutorials/advanced_tutorials/agent_versus_non_agent_regret.ipynb +++ b/doc/tutorials/advanced_tutorials/agent_versus_non_agent_regret.ipynb @@ -32,7 +32,22 @@ "id": "5142d6ba-da13-4500-bca6-e68b608bfae9", "metadata": {}, "outputs": [], - "source": "from gtdraw import draw\n\nimport pygambit as gbt\n\ng = gbt.catalog.load(\"books/myerson1991/fig4_2\")\ndraw(g)" + "source": [ + "# gtdraw is optional: it depends on a LaTeX installation; without it, draw() prints a note.\n", + "try:\n", + " from gtdraw import draw\n", + "except ImportError:\n", + " def draw(*args, **kwargs):\n", + " print(\n", + " \"gtdraw is not installed, so the game tree cannot be drawn here; \"\n", + " \"see https://www.gambit-project.org/gtdraw/ to install it.\"\n", + " )\n", + "\n", + "import pygambit as gbt\n", + "\n", + "g = gbt.catalog.load(\"books/myerson1991/fig4_2\")\n", + "draw(g)" + ] }, { "cell_type": "markdown", diff --git a/doc/tutorials/interoperability_tutorials/openspiel.ipynb b/doc/tutorials/interoperability_tutorials/openspiel.ipynb index 1e3f35df84..60005abeb2 100644 --- a/doc/tutorials/interoperability_tutorials/openspiel.ipynb +++ b/doc/tutorials/interoperability_tutorials/openspiel.ipynb @@ -459,7 +459,15 @@ "metadata": {}, "outputs": [], "source": [ - "from gtdraw import draw\n", + "# gtdraw is optional: it depends on a LaTeX installation; without it, draw() prints a note.\n", + "try:\n", + " from gtdraw import draw\n", + "except ImportError:\n", + " def draw(*args, **kwargs):\n", + " print(\n", + " \"gtdraw is not installed, so the game tree cannot be drawn here; \"\n", + " \"see https://www.gambit-project.org/gtdraw/ to install it.\"\n", + " )\n", "\n", "draw(\n", " gbt_hanabi_game,\n", diff --git a/doc/tutorials/running_locally.rst b/doc/tutorials/running_locally.rst index 5407afec15..abe55ca8b5 100644 --- a/doc/tutorials/running_locally.rst +++ b/doc/tutorials/running_locally.rst @@ -22,6 +22,11 @@ The tutorials are available as Jupyter notebooks and can be run interactively us pip install .[doc] + Several tutorials also use `gtdraw `_ to draw game + trees. `gtdraw` is installed separately:: + + pip install gtdraw + .. warning:: Windows users wishing to run the "Using Gambit with OpenSpiel" tutorial will need to install OpenSpiel manually; see the `OpenSpiel installation instructions `_ for details. diff --git a/pyproject.toml b/pyproject.toml index 9f5ebbff88..9dd6042676 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -63,7 +63,6 @@ doc = [ "pyyaml", "sphinxcontrib-bibtex", "myst-parser", - "gtdraw", ] [project.urls]