Python Single-Source Versioning Library
The `single-source` library provides a unified way to access a Python project's version directly from code, aligning with PEP 621-style projects. It aims to establish a single source of truth for version information, preventing inconsistencies that arise from manual updates across multiple files. The library supports Python 3.8 and newer versions and is actively maintained.
Common errors
-
single_source.VersionNotFoundError: Version not found in pyproject.toml
cause The `get_version()` function was called with `raise_exc=True`, but it could not find the project version in the expected `pyproject.toml` file (or other configured source) at the specified path.fixVerify that `pyproject.toml` exists in the `path_to_pyproject_dir` you provided to `get_version()`. Ensure the `[project].version` key is correctly defined in `pyproject.toml`, or if using a dynamic version, that your build system is configured to generate it. -
ModuleNotFoundError: No module named 'single_source'
cause The `single-source` library is not installed in the current Python environment, or the Python interpreter cannot find it in its `sys.path`.fixInstall the library using `pip install single-source`. If using a virtual environment, ensure it is activated before installation. -
TypeError: get_version() missing 1 required positional argument: 'path_to_pyproject_dir'
cause The `get_version` function requires at least one argument, a `pathlib.Path` object pointing to the root directory of your project where the version information is located.fixProvide the necessary `pathlib.Path` argument to `get_version()`. For example: `get_version(Path(__file__).parent.parent)` to look two directories up from the current script.
Warnings
- gotcha By default, `get_version()` returns an empty string (`""`) if it cannot locate the project version from `pyproject.toml`, `setup.py`, or `__init__.py`. This can lead to silent failures if an empty string is not an expected valid version.
- gotcha The `path_to_pyproject_dir` argument for `get_version()` must accurately point to the directory containing your project's version source (e.g., `pyproject.toml`). An incorrect path will cause the library to fail in finding the version.
- breaking The `single-source` library explicitly requires Python 3.8 or newer. Attempting to use it with older Python versions (e.g., Python 2.x or Python 3.7 and below) will result in `SyntaxError` or `ModuleNotFoundError` due to incompatible language features and module structures.
Install
-
pip install single-source
Imports
- get_version
from single_source import get_version
- VersionNotFoundError
from single_source import VersionNotFoundError
Quickstart
from pathlib import Path
from single_source import get_version, VersionNotFoundError
# For demonstration, assume a pyproject.toml exists in the parent directory.
# In a real project, this path would point to your project root.
try:
# Adjust path_to_pyproject_dir to point to your project's root.
# For an executable script, .parent.parent might work if pyproject.toml is two levels up.
# For a library in a package, it might be Path(__file__).parent.parent.parent
project_root = Path(__file__).resolve().parent
# In a typical project, if your script is in `src/my_package/my_module.py` and pyproject.toml is at project root:
# project_root = Path(__file__).resolve().parents[3] # Adjust as needed
# Example of a simplified path for a quick demonstration setup:
# Create a dummy pyproject.toml for this example to be runnable
dummy_project_dir = Path('./dummy_project_for_single_source_test')
dummy_project_dir.mkdir(exist_ok=True)
pyproject_content = '[project]\nname = "my_test_package"\nversion = "1.2.3"\n'
(dummy_project_dir / 'pyproject.toml').write_text(pyproject_content)
# Now get the version from the dummy project
version = get_version(dummy_project_dir)
print(f"Project version (from dummy_project): {version}")
# Example with explicit error raising
# Clean up dummy project
(dummy_project_dir / 'pyproject.toml').unlink()
dummy_project_dir.rmdir()
# Attempt to get version from a non-existent path to demonstrate VersionNotFoundError
non_existent_path = Path('./non_existent_project')
print(f"\nAttempting to get version from non-existent path '{non_existent_path}' with error raising...")
try:
get_version(non_existent_path, raise_exc=True)
except VersionNotFoundError as e:
print(f"Caught expected error: {e}")
except Exception as e:
print(f"An error occurred: {e}")
finally:
# Ensure cleanup even if errors occur before the explicit unlink/rmdir
dummy_project_dir = Path('./dummy_project_for_single_source_test')
if dummy_project_dir.exists():
if (dummy_project_dir / 'pyproject.toml').exists():
(dummy_project_dir / 'pyproject.toml').unlink()
if dummy_project_dir.is_dir():
dummy_project_dir.rmdir()