FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

Add support for native TOML configuration by bluetech · Pull Request #13846 · pytest-dev/pytest · GitHub

Add support for native TOML configuration - #13846

Merged
bluetech merged 5 commits into
pytest-dev:mainfrom
bluetech:native-toml
Oct 27, 2025
Merged

Add support for native TOML configuration#13846
bluetech merged 5 commits into
pytest-dev:mainfrom
bluetech:native-toml

Conversation

bluetech commented Oct 25, 2025
edited
Loading

Copy link
Copy Markdown
Member

Fixes #13743.

Add support for using native TOML configuration, while maintaining full backwards compatibility with the existing INI-based configuration system.

In pyproject.toml, the native configuration is under [pytest.tool]. Also add support for pytest.toml/.pytest.toml files, under [pytest] table (similar to pytest.ini).

--override-ini always uses "ini" mode for compatibility.

nicoddemus commented Oct 25, 2025
edited
Loading

Copy link
Copy Markdown
Member

Gave it a first pass, this is looking great! The ability of using [tool.pytest] or a pytest.toml file is definitely appealing from the user's perspective.

However, it seems the only difference between ini_options and the native TOML support is the type checking versus string coercion:

# pyproject.toml
[tool.pytest]
test_int_validation = 5
test_paths = ["src", "lib"]

#[tool.pytest.ini_options]
#test_int_validation = "5"
#test_paths = ["src", "lib"]
# conftest
def pytest_addoption(parser):
    parser.addini("test_int_validation", "Test int validation", type="int", default=0)
    parser.addini("test_paths", "Test paths config", type="paths")
# test_foo.py
def test(request):
    val = request.config.getini("test_int_validation")
    print(f"{val} ({type(val)})")
    val2 = request.config.getini("test_paths")
    print(f"{val2} ({type(val2)})")

From plugin author's POV, both [tool.pytest] and [tool.pytest.ini_options] yield exactly the same configuration values (as they should):

5 (<class 'int'>)
[WindowsPath('e:/projects/pytest/.tmp/toml-config/src'), WindowsPath('e:/projects/pytest/.tmp/toml-config/lib')] (<class 'list'>)

The type-coercion for ini options means that test_int_validation in ini_options can be either "5" or 5.

Unless I'm missing something, [tool.pytest.ini_options] and [tool.pytest] are identical, except the latter does type validation instead of coercion.

To be clear, this is all good and definitely we want to introduce this in pytest.

I'm just wondering why we just not did this in the first place, rather than introducing pytest.ini_options. I was under the impression that @RonnyPfannschmidt had other plans regarding TOML configuration -- perhaps letting plugins define their options in their own tables or something like that. That said, I believe this implementation is more grounded and probably what we should have done from the start, so thanks a lot @bluetech for tackling this.

Copy link
Copy Markdown
Member

I hope to have cot.config.ingest a reasonable wip by the end of the year

psf-chronographer Bot added the bot:chronographer:provided (automation) changelog entry is part of PR label Oct 25, 2025

Copy link
Copy Markdown
Member Author

@nicoddemus My impression was that we wanted to get some toml support and so went with the "quick" ini_options support. But it was a long time ago, I'm probably misremembering.

In any case, we can wait for @RonnyPfannschmidt solution. But I wanted to finish the PR while it's still fresh in my head, maybe Ronny could reuse some of it. The changes since the initial posting:

  • Added pytest.toml/.pytest.toml support
  • Added a changelog
  • Went over the docs
  • Tested on a project of mine which uses a jungle of pyproject.toml and pytest.ini and converted it to native toml.

bluetech marked this pull request as ready for review October 25, 2025 17:45

Copy link
Copy Markdown
Member

In any case, we can wait for @RonnyPfannschmidt solution.

I think we should go ahead with your support, I believe @RonnyPfannschmidt's solution can be built on top of it later (please correct me if I'm wrong Ronn).

It would be nice to release this new support in 9.0. 👍

Copy link
Copy Markdown
Member

My solution would completely replace ini/toml/argpatse settings

Its inspired by typedsetting

Copy link
Copy Markdown
Member

But i believe its fine to go Ahead

Copy link
Copy Markdown
Member

My solution would completely replace ini/toml/argpatse settings

Sounds interesting, but I wonder how it would work with backward compatibility in mind.

Copy link
Copy Markdown
Member

@nicoddemus i'm exploring that part still - but the basic goal is to provide a backward compatible layer - once tests pass pytest-alikeness i can propose upstream changes

Copy link
Copy Markdown
Member Author

Rebased, still missing some coverage.

I also noticed about this code here:

# "pytest.ini" files are always the source of configuration, even if empty.
if filepath.name == "pytest.ini":
return {}

It allows an empty pytest.ini to still be considered the config file. I think it also should check for .pytest.ini. I think this point was forgotten when .pytest.ini support was added (#9988), not intentionally omitted.

Copy link
Copy Markdown
Member Author

OK, this should be ready now.

Comment thread doc/en/how-to/output.rst Outdated
Comment thread doc/en/reference/customize.rst Outdated
This prepares the code and documentation for adding another
configuration file format, TOML.

Add a `mode` field to `ConfigValue` to track the parsing mode.

Add tabs to all configuration file snippets in the docs, so that we may
show both toml and ini in a nice way once toml is added. Uses the
sphinx-inline-tabs package that I saw used by tox documentation.

Avoid references to "pytest.ini" and "ini file" in docs, instead refer
to "configuration file" (I'm sure I missed some).

nicoddemus left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

LGTM!

Comment thread doc/en/reference/customize.rst Outdated
Add support for using native TOML configuration, while maintaining full
backwards compatibility with the existing INI-based configuration
system.

In pyproject.toml, the native configuration is under ``[pytest.tool]``.
Also add support for ``pytest.toml``/``.pytest.toml`` files.

`--override-ini` always uses "ini" mode for compatibility.
bluetech merged commit 8c7be91 into pytest-dev:main Oct 27, 2025
33 checks passed
bluetech deleted the native-toml branch October 27, 2025 16:07

RonnyPfannschmidt left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

i think we should log a plan somewhere to make more use of actual native toml - the ini mapping to more native types is really just a first step

.. code-block:: toml

[pytest]
markers = ["webtest: mark a test as a webtest.", "slow: mark test as slow."]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

this is a example of dissonance

in toml this should be

[pytest.markers]
webtest = "..."
slow = "..."
``

python_functions = *_check
# Example 1: have pytest look for "check" instead of "test"
[pytest]
python_files = ["check_*.py"]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

in future we might want to have python.* as table instead of the prefixes

Copy link
Copy Markdown
Member Author

i think we should log a plan somewhere to make more use of actual native toml - the ini mapping to more native types is really just a first step

Yes that would be good. Would you like me to open an issue?

I'm sure you've thought this through already, but if I were to add support for e.g. your markers example, the first thing that comes to mind is to extend the addini(type=...) parameter from what it currently supports ("string", "args", "paths", "bool" etc.) to also receive a typing expression (e.g. str, list[str], list[Path], bool) which is strictly limited to a subset that we can map back from ini mode. Then add support for dict[str, <str|bool|int|float>], which in toml mode is a table and in ini mode is lines of key: value like markers currently implements manually from "linelist".

So it's basically a mini Pydantic implementation but due to being very restricted for compatibility with ini mode it should be relatively simple.

About the [python] idea, I like the idea of plugins having their own sections, but I'm not sure it's worth breaking compat for. Personally I'd be wary of ever deprecating ini support, it would be huge churn. So then we can have "toml only" options, but that might be getting too complicated...

Copy link
Copy Markdown
Member

@bluetech im currently playing around with a potential solution in https://github.com/cogs-of-testing/cot.config.ingest/blob/5f34c5b51630174487236b27d87cbc19760ab8cd/README.md

if it works as intended then the toml migration wil lbe natural and backward compat will mostly work


def getini(self, name: str) -> Any:
"""Return configuration value from an :ref:`ini file <configfiles>`.
"""Return configuration value the an :ref:`configuration file <configfiles>`.

This comment was marked as spam.

.. code-block:: toml

# pytest.toml or .pytest.toml
[pytest]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

I wish I'd seen this earlier — I tend to prefer keeping the same section names in other TOML files due to the ease of migration between them: coveragepy/coveragepy#1952 (comment).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

I disagree and think that would present a markedly worse UX coveragepy/coveragepy#1952 (comment)

This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bot:chronographer:provided (automation) changelog entry is part of PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Native pyproject.toml configuration

7 participants


Back | FazBrowse Home | New Git URL