Multi-syntax configuration examples

Monday 5 June 2023

Coverage.py reads settings from a number of different files, in either INI-file or TOML syntax, with different section headings depending on the file. This could be confusing: the docs showed the syntax needed for .coveragerc, but if you were using one of the other files, you had to mentally convert from one syntax to another.

To make it easier, I updated the documentation to show all the syntax possibilities when showing examples of configuration files. I used sphinx-code-tabs to create tabbed code sections.

The result looks like this: a three-tabbed code box. The tabs have the names of configuration files. Selecting a tab shows the syntax you need for that particular file:

Tab .coveragerc selected
Tab pyproject.toml selected
Tab setup.cfg selected

Originally I wanted to write the settings just once, and use cog to run Python code to convert from INI syntax to TOML.

If you haven’t seen cog before, it lets you insert small chunks of Python into static files. The Python code is executed to generate more static content that appears alongside the Python code. It’s a simple tool that works well when you have a mostly static file, but you want part of it to be computed.

But I sensed that converting between syntaxes be difficult, especially since some of my examples (as the ones above) have comments in them.

So I went with a simpler approach: the Python snippets in the doc files have both INI and TOML chunks. The INI chunk is lightly massaged to make two of the tabs, since they only differ in the section names. To ensure the two input chunks are in sync, the code reads the configuration examples, and checks that the INI and TOML chunks create the same settings values.

This guarantees that the different syntaxes are all valid, both as generic INI or TOML, but also as coverage.py settings. And it guarantees that the two chunks show the same settings, differing only in syntax.

It’s a little bulky in the resulting .rst files, but it provides the reader with the information they need, and it keeps me from making mistakes.

If you want to see the code, the cog code is in cog_helpers.py, and a small example of how it’s used in the documentation is in context.rst.

Comments

[gravatar]

Very nice! As a maintainer of a popular third-party build tool, do you foresee a day when pyproject.toml will be the last config format standing? More important than answer, how would you go about making the decision to drop support for a config format?

I’m curious because I see a cost to maintaining multiple formats and documenting their syntax. It’s also not very much in the spirit of the Zen of Python, which advocates for “one…obvious way to do it”. However, forcing users to migrate perfectly working configuration is also not to be taken lightly.

[gravatar]

It’s a good question about how long to support older settings files, a special case of the more general question of long to support anything!

I tend to keep things running unless it causes active pain. The configuration code in coverage.py isn’t changing, so it will probably stay this way for a long time.

As an aside, last week ReadTheDocs said that .readthedocs.yaml files would be required, and I thought, “can’t I put those settings in pyproject.toml?” Nope.

Add a comment:

Ignore this:
Leave this empty:
Name is required. Either email or web are required. Email won't be displayed and I won't spam you. Your web site won't be indexed by search engines.
Don't put anything here:
Leave this empty:
Comment text is Markdown.