Skip to main content

Dependency Checker

cyber_modules/dependency_checker.py provides a lightweight bootstrapper that verifies required Python packages are installed before the game starts and automatically installs any that are missing via pip.
This module is intentionally simple and classroom-safe. It only installs the exact packages passed to it by the caller — no hidden package lists or network calls beyond what pip install performs.

ensure_dependencies(packages)

The public entry point. Checks each package by name, installs missing ones, and raises RuntimeError if any installation fails.
def ensure_dependencies(packages: Iterable[str]) -> None:
    missing = [p for p in packages if not _is_installed(p)]
    if not missing:
        return

    print("[Dependency Checker] Missing packages:", ", ".join(missing))
    for pkg in missing:
        print(f"[Dependency Checker] Installing {pkg}...")
        ok = _install_package(pkg)
        if not ok:
            raise RuntimeError(
                f"Failed to install {pkg}. "
                f"Please run: {sys.executable} -m pip install {pkg}"
            )
packages
Iterable[str]
required
An iterable of package/module name strings to verify. In the game this is called with ["pygame"]:
ensure_dependencies(["pygame"])
Package names must be importable module names (e.g. "pygame", "PIL", "requests"), not PyPI distribution names, since _is_installed uses importlib.import_module.
return
None
Returns None if all packages are present or successfully installed. Raises RuntimeError if any installation fails.
If _install_package fails, ensure_dependencies raises RuntimeError with a human-readable message that includes the exact pip install command to run manually. The caller in main() catches this and exits with code 1.

Behaviour

1

Filter missing packages

Builds a list of packages for which _is_installed() returns False. If the list is empty the function returns immediately with no output.
2

Log and install

Prints each missing package name to stdout, then calls _install_package() for each one.
3

Raise on failure

If _install_package() returns False for any package, RuntimeError is raised immediately. Remaining packages in the missing list are not attempted.

_is_installed(module_name)

Attempts to import a module and returns whether it succeeded.
def _is_installed(module_name: str) -> bool:
    try:
        importlib.import_module(module_name)
        return True
    except Exception:
        return False
module_name
str
required
The importable module name to probe, e.g. "pygame". This must match the name used in import statements, not necessarily the PyPI package name.
return
bool
True if importlib.import_module(module_name) succeeds without raising any exception. False for any exception, including ModuleNotFoundError, ImportError, or errors raised during module initialisation.
The broad except Exception clause is intentional — some partially-installed packages raise non-ImportError exceptions on import (e.g. missing native libraries). Catching all exceptions ensures these cases are treated as “not installed”.

_install_package(package)

Installs a package using the current Python interpreter’s pip.
def _install_package(package: str) -> bool:
    try:
        subprocess.check_call(
            [sys.executable, "-m", "pip", "install", package]
        )
        return True
    except Exception:
        return False
package
str
required
PyPI package name to install, e.g. "pygame". This is passed directly to pip install.
return
bool
True if pip install exits with code 0. False if subprocess.check_call raises any exception (non-zero exit code, binary not found, permission denied, etc.).
The command executed is equivalent to:
python -m pip install <package>
Using sys.executable ensures the package is installed into the same Python environment that is running the game, avoiding issues with multiple Python installations or virtual environments.
Because subprocess.check_call blocks, package installation is synchronous. For pygame, installation typically takes a few seconds on a fresh environment. The game will not proceed until ensure_dependencies returns.

Build docs developers (and LLMs) love