autopypath ========== .. Badges .. image:: https://github.com/JerilynFranz/python-autopypath/actions/workflows/build.yml/badge.svg :target: https://github.com/JerilynFranz/python-autopypath/actions/workflows/build.yml :alt: Build Status .. image:: https://coveralls.io/repos/github/JerilynFranz/python-autopypath/badge.svg :target: https://coveralls.io/github/JerilynFranz/python-autopypath :alt: Coverage Status .. image:: https://readthedocs.org/projects/python-autopypath/badge/?version=latest :target: https://python-autopypath.readthedocs.io/en/latest/?badge=latest :alt: Documentation Status .. image:: https://img.shields.io/pypi/v/autopypath :target: https://pypi.org/project/autopypath/ :alt: PyPI Version .. image:: https://img.shields.io/pypi/pyversions/autopypath :target: https://pypi.org/project/autopypath/ :alt: Python Versions .. image:: https://img.shields.io/badge/License-Apache_2.0-green.svg :target: https://opensource.org/licenses/Apache-2.0 :alt: License .. image:: https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json :target: https://github.com/astral-sh/ruff :alt: Ruff Table of Contents ----------------- .. toctree:: :name: contents :maxdepth: 1 :caption: Table of Contents installation usage configuration public_api contributing code_of_conduct What is autopypath? ------------------- **autopypath** is a library that simplifies the management of the Python module search path (:data:`sys.path`) for testing and development environments. It automatically detects your project root (via `.git `_, `pyproject.toml `_, etc.) and intelligently adds source directories to :data:`sys.path` at runtime. It *does not* read ``.env`` files to derive `PYTHONPATH `_ because the semantics cannot be consistently interpreted across different operating systems. For example, consider ``PYTHONPATH=src:test;lib``: * On POSIX, ``PYTHONPATH`` is separated by ``:`` → ``["src", "test;lib"]`` * On Windows, ``PYTHONPATH`` is separated by ``;`` → ``["src:test", "lib"]`` * And the intent may have been ``["src", "test", "lib"]`` All of those interpretations are "reasonable", so autopypath avoids guessing what was meant and instead uses ``pyproject.toml`` or ``autopypath.toml`` for configuration. The Problem it Solves ~~~~~~~~~~~~~~~~~~~~~ In active development, **builds are often broken.** Standard test runners (like `pytest `_ or `tox `_) often refuse to start if they cannot import the entire package, or if the package hasn't been re-installed into the virtual environment after a structural change. **autopypath allows you to run individual tests or scripts in isolation, even if:** - The project build is currently broken. - The package is not installed in the current environment. - Other parts of the test suite are failing due to ongoing refactoring. It is not a replacement for `virtual environments `_, but a resilience tool. It mitigates path-related :class:`ModuleNotFoundError` errors, allowing you to debug a specific file without needing the entire project ecosystem to be in a perfect, deployable state. Installation ------------ Installing from PyPI ~~~~~~~~~~~~~~~~~~~~ .. code-block:: shell pip install autopypath Installing from Source ~~~~~~~~~~~~~~~~~~~~~~ .. code-block:: shell git clone https://github.com/JerilynFranz/python-autopypath.git cd python-autopypath pip install . Development Installation ~~~~~~~~~~~~~~~~~~~~~~~~ For development purposes, you can install ``autopypath`` in editable mode. To make this easier, a ``bootstrap.py`` script is provided. .. code-block:: shell git clone https://github.com/JerilynFranz/python-autopypath.git cd python-autopypath python3 bootstrap.py source .venv/bin/activate # On Windows use .venv\Scripts\activate This script will: 1. Set up the development environment (``uv sync --all-groups``). 2. Install ``autopypath`` in editable mode. 3. Install Git hooks for pre-commit checks. 4. Install development tools like `tox `_, `sphinx `_, and `ruff `_. Usage ----- Simply import ``autopypath`` at the top of your test script. It will automatically detect the project root and adjust :data:`sys.path` accordingly (by default adding ``src``, ``lib``, ``src/tests``, and ``tests`` directories if they exist). It does not add ``.`` to :data:`sys.path` by default to avoid conflicts with subdirectories that are NOT intended to be packages, but if you want to include the repo root directory, you can configure it via `pyproject.toml `_ or ``autopypath.toml``. Here is an example: .. code-block:: python :caption: tests/my_test_script.py import autopypath # <--- This line adjusts the sys.path import pytest # Now these imports work without installing the package import mypackage.my_module if __name__ == '__main__': pytest.main([__file__]) You can now run this file directly: .. code-block:: shell python tests/my_test_script.py Configuration ------------- autopypath automatically detects `pyproject.toml `_. You can configure it by adding a ``[tool.autopypath]`` section. **Example `pyproject.toml`:** .. code-block:: toml :caption: pyproject.toml [tool.autopypath] paths = ["lib", "src/tests", ".", "src"] If you do not use ``pyproject.toml``, you can create an ``autopypath.toml`` file either in your root directory or in subdirectories such as ``src`` or ``tests`` and it will be detected automatically. This can be useful for monorepos or multi-package repositories and allows customization of :data:`sys.path` per sub-project or for detection of the project root in non-standard layouts. **Example `autopypath.toml`:** .. code-block:: toml :caption: autopypath.toml [tool.autopypath] paths = ["src", "src/lib", "tests"] repo_markers = {".git" = "dir"} This file can be placed in the root of your project or in any directory that is a parent of your test scripts (but still inside the repo).