Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 17 additions & 12 deletions doc/developer.catalog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,6 @@ To do so, you will need to have the `gambit` GitHub repo cloned and be able to s
you may wish to first review the :ref:`contributor guidelines <contributing>`.
You'll also need to have a developer install of `pygambit` available in your Python environment, see :ref:`build-python`.

The catalog module
------------------

Although the ``catalog`` directory is located at the project root outside of ``src/pygambit/``, it is installed and bundled as the ``pygambit.catalog`` subpackage.

This is handled by the package build configuration in ``pyproject.toml`` under ``[tool.setuptools]``:

- The ``package-dir`` mapping instructs ``setuptools`` to source the ``pygambit.catalog`` subpackage from the physical ``catalog`` directory.
- The ``package-data`` configuration ensures all non-Python data files (like ``.efg`` and ``.nfg`` files) inside the catalog are correctly bundled during installation.

As a developer, this means you will need to reinstall the package (e.g., passing ``pip install .``) for any new game files or internal catalog changes to be reflected in the ``pygambit`` module.

Add new game files
------------------

Expand Down Expand Up @@ -58,3 +46,20 @@ Currently supported representations are:
.. warning::

Make sure you commit all changed files e.g. run ``git add --all`` before committing and pushing.


Access from pygambit
--------------------

We keep the ``catalog`` directory at the top level of the repository because it is in principle independent
of the Python and C++ code. However, in order to include these games with the Python package, there is a bit
of extra infrastructure.

In ``setup.py`` we have a custom build command which first copies the contents of ``catalog/`` into the build
directory for the Python package. These are then exposed as data in the ``catalog_data`` directory (changing
the name to avoid confusion or clashes with ``catalog.py``, which is responsible for accessing the catalog).

The main implication is that if you are working via the Python package and you add new games to the catalog,
you will need to rebuild and reinstall the Python extension in order to access the new games. That is, changing
the contents of the catalog is no different than changing any other source code in the Python package; you'll
need to execute ``pip install .`` after the addition or change.
6 changes: 3 additions & 3 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -114,11 +114,11 @@ markers = [
]

[tool.setuptools]
packages = ["pygambit", "pygambit.catalog"]
package-dir = { "pygambit" = "src/pygambit", "pygambit.catalog" = "catalog" }
packages = ["pygambit"]
package-dir = { "pygambit" = "src/pygambit" }

[tool.setuptools.package-data]
"pygambit.catalog" = ["*"]
pygambit = ["catalog_data/**/*"]

[tool.setuptools.dynamic]
version = {file = "build_support/GAMBIT_VERSION"}
18 changes: 17 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,12 @@
#

import glob
import pathlib
import platform
import shutil

import Cython.Build
import setuptools
import setuptools.command.build_py

cppgambit_include_dirs = ["src"]
cppgambit_cflags = (
Expand Down Expand Up @@ -78,6 +80,19 @@ def solver_library_config(library_name: str, paths: list) -> tuple:
)


class GambitBuildPy(setuptools.command.build_py.build_py):
"""Extend `build_py` to copy the catalog games data into the build library."""
def run(self) -> None:
super().run()

catalog_source = pathlib.Path("catalog")
catalog_target = pathlib.Path(self.build_lib) / "pygambit/catalog_data"
if catalog_target.exists():
shutil.rmtree(catalog_target)
catalog_target.mkdir(exist_ok=True, parents=True)
shutil.copytree(catalog_source, catalog_target, dirs_exist_ok=True)


cppgambit_bimatrix = solver_library_config("cppgambit_bimatrix",
["linalg", "lp", "lcp", "enummixed"])
cppgambit_liap = solver_library_config("cppgambit_liap", ["liap"])
Expand All @@ -100,6 +115,7 @@ def solver_library_config(library_name: str, paths: list) -> tuple:
)

setuptools.setup(
cmdclass={"build_py": GambitBuildPy},
libraries=[cppgambit_bimatrix, cppgambit_liap, cppgambit_logit, cppgambit_simpdiv,
cppgambit_gtracer, cppgambit_enumpoly,
cppgambit_games, cppgambit_core],
Expand Down
4 changes: 2 additions & 2 deletions catalog/__init__.py → src/pygambit/catalog.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@

import pygambit as gbt

# Use the full string path to the virtual package we created
_CATALOG_RESOURCE = files(__name__)
# Use the full string path to where the catalog data are placed in the package
_CATALOG_RESOURCE = files("pygambit")/"catalog_data"

READERS = {
".nfg": gbt.read_nfg,
Expand Down
Loading