Skip to main content

toxology

Read tox configuration (deps, extras, dependency groups, commands, setenv, changedir) using the tox Python API without requiring tox as a runtime dependency.

Toxology vendors tox and provides lightweight stubs for its dependencies, making it suitable for use in Fedora/RHEL RPM builds where tox and virtualenv are not available.

⚠️ Project Status: Proof of Concept

This is an experimental proof of concept project created with extensive AI assistance to explore whether this vendoring approach is viable.

  • ⚠️ API is unstable - The API may change at any time without notice
  • ⚠️ Not production-ready - This is for experimentation only
  • ⚠️ Uncertain future - It is not yet determined whether this will be used in Fedora RPM macros or continue development

Do not use this project for anything beyond experimentation and evaluation.

Features

  • ✅ No tox runtime dependency - tox is vendored, only packaging>=26 and pluggy required
  • ✅ Comprehensive config extraction - deps, extras, dependency_groups, commands, setenv, changedir
  • ✅ All tox config formats - tox.ini, pyproject.toml, setup.cfg
  • ✅ Full tox features - factor expansion, placeholders, conditional deps, markers
  • ✅ 95.3% success rate on real-world Fedora packages (205/215) - the rest appear to be broken configs anyway
  • ✅ Python 3.12+ support

Installation

pip install toxology

Runtime dependencies: Only packaging>=26 and pluggy (both available in Fedora ELN).

API Reference

read_tox_config(env: str, path: Path | None = None) -> ToxEnvConfig

Read tox configuration for a given environment.

Parameters:

  • env (str): Environment name (e.g., "py312", "lint")
  • path (Path | None): Project root or config file location. Defaults to current directory.

Returns: ToxEnvConfig with the following attributes:

  • name (str): Environment name
  • deps (tuple[str, ...]): Dependency specifiers as tox would pass to pip
  • extras (frozenset[str]): Extras to install for the target package
  • dependency_groups (frozenset[str]): Dependency groups to install
  • commands (tuple[Command, ...]): Test commands with .args, .ignore_exit_code, .invert_exit_code
  • setenv (dict[str, str]): Environment variables to set when running commands
  • changedir (Path | None): Working directory for commands

Convenience properties:

  • deps_list → list[str]
  • extras_set → set[str]
  • dependency_groups_set → set[str]
  • commands_list → list[Command]

Example usage

Given a tox configuration like this:

[project]
name = "my-project"
version = "0.1.0"
requires-python = ">=3.12"

[tool.tox]
env_list = ["py312", "lint"]

[tool.tox.env.py312]
deps = ["pytest>=8"]
extras = ["dev"]
dependency_groups = ["test"]
commands = [["pytest", "tests"], ["coverage", "report"]]

[tool.tox.env.lint]
deps = ["ruff"]
commands = [["ruff", "check", "."]]

This is what the library returns:

from toxology import read_tox_config

config = read_tox_config("py312")  # path= defaults to current directory
assert config.name == "py312"
assert config.deps == ("pytest>=8",)
assert config.extras == frozenset({"dev"})
assert config.dependency_groups == frozenset({"test"})
assert tuple(config.commands[0].args) == ("pytest", "tests")
assert tuple(config.commands[1].args) == ("coverage", "report")

configs = {env: read_tox_config(env) for env in ["py312", "lint"]}
assert configs["lint"].name == "lint"
assert tuple(configs["lint"].commands[0].args) == ("ruff", "check", ".")

Supported tox Features

Toxology correctly handles:

  • Factor expansion: py{38,39,310} → py38, py39, py310
  • Placeholders: {envpython}, {envtmpdir}, {toxinidir} resolved to sys.prefix paths
  • Conditional dependencies: mock; python_version < "3.3"
  • PEP 508 markers: pytest>=8; sys_platform == "linux"
  • Substitutions: {toxinidir}/data, {env:HOME}
  • Complex setenv: Multi-line, markers, file references
  • All config formats: tox.ini, pyproject.toml, setup.cfg

Vendoring Approach

Toxology uses a unique vendoring strategy to eliminate tox as a runtime dependency:

What's Vendored

  • tox only (~150 files, ~80KB)

What's Stubbed (Not Vendored)

Instead of vendoring tox's dependencies, we provide lightweight stubs:

  • virtualenv, distlib, python-discovery - Not needed for config reading
  • cachetools, filelock - Only used in package building
  • platformdirs - Only for user config (we use project config)
  • pyproject-api, tomli-w, colorama - Not needed for our use case

Runtime Dependencies

Only 2 packages from Fedora ELN:

  • packaging>=26 - Essential for parsing deps/requirements/markers
  • pluggy - Plugin system infrastructure

See VENDORING.md for details on how to update vendored tox.

Real-World Validation

Tested on 215 real Fedora packages:

  • ✅ 205/215 succeeded (95.3%)
  • ✅ All 10 failures were legitimate package issues (missing tox configs or broken tox.ini files)
  • ✅ Successfully extracts config from pytest, OpenStack, Fedora tooling packages

Use Cases

Fedora/RHEL RPM Builds

Primary use case: Replace tox-current-env in the %tox RPM macro to run tests without requiring tox/virtualenv in RHEL.

CI/CD Systems

Extract tox configuration to generate test matrices or validate tox configs without installing tox.

Build Tools

Read tox deps/extras to populate other build system configurations.

Development

Run all checks (tests, type checking, lint) with tox:

tox

Run a single environment, e.g. tests on one Python version or just lint:

tox run -e py312
tox run -e lint
tox run -e typing

Compatibility

  • Tox version: 4 (vendored, for exact version see src/toxology/_vendored/vendor.txt)
  • Python versions: 3.12, 3.13, 3.14+
  • Config formats: tox.ini, pyproject.toml, setup.cfg
  • Tox features: Factor expansion, placeholders, conditional deps, markers, setenv, changedir

Limitations

Toxology is designed for config reading only. It does not:

  • ❌ Create or manage virtual environments
  • ❌ Install packages
  • ❌ Run test commands
  • ❌ Build wheels or sdists

These limitations are intentional - toxology extracts configuration so other tools (like RPM macros) can use it.

License

MIT License - see LICENSE file for details.

Vendored tox is distributed under its original MIT license.

Metadata

Release files for toxology 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for toxology 0.1.0
File Size Uploaded Provenance Actions
toxology-0.1.0.tar.gz 170.5 kB With provenance Details for toxology-0.1.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for toxology 0.1.0
File Interpreter ABI Platform Actions
toxology-0.1.0-py3-none-any.whl Python 3 none any Details for toxology-0.1.0-py3-none-any.whl

Total release size: 394.5 kB

Release files / toxology-0.1.0.tar.gz

Download URL toxology-0.1.0.tar.gz
Size 170.5 kB
Tags Source
SHA-256 checksum
How to use checksums
cb16bf7f7a3ffa67cead223164f4bce0da9421b9e5ebc7aeae0e212de3b62ce4
BLAKE2b-256 checksum
How to use checksums
7e43186e9b82bce145636a70e0692faf364617b402ee9b910d0fd24e34420b0d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Mar 31, 2026.

Transparency log

Release files / toxology-0.1.0-py3-none-any.whl

Download URL toxology-0.1.0-py3-none-any.whl
Size 224.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
304290daa7263d8e323cc07f82bbe5ee12a8934f535671063ab8501bd485a82b
BLAKE2b-256 checksum
How to use checksums
12d0988e79b16b83da5ca9788e39f207dab9af2de36a63210988c18f23e9c6ab
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Mar 31, 2026.

Transparency log

Security for toxology 0.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

Both files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for toxology-0.1.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Mar 31, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files Full provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page