Using zope.meta

Purpose

Bring the configuration of the zopefoundation packages into a common state and keep it there.

Configuration types

This directory contains the configuration directories for different types of packages:

  • buildout-recipe

    • Configuration for a zc.buildout recipe. It is tested using multiple processes, so coverage has to be configured in a special way. (Supports pure Python packages which also run on PyPy.)

  • c-code

    • Configuration for package containing C code besides the Python one.

  • pure-python

    • Configuration for a pure Python package.

  • zope-product

    • Configuration for a pure Python package which uses zc.buildout inside tox.ini to be able to pin the installed dependency versions the same way buildout.cfg does it.

  • toolkit

    • Configuration used for the zopetoolkit and groktoolkit repositories.

Configuration templates

Each configuration type folder can override the default configuration in the folder default by providing one or more of these files:

  • packages.txt

    • This file lists the packages which use the configuration in the directory.

  • CONTRIBUTING.md

    • This file is copied as is. It allows developers to easily find our contributing guidelines in the root of the repository.

  • editorconfig

    • This file is copied to .editorconfig and allows developers to have a common editor configuration experience in all repos.

  • gitignore.j2

    • This file is copied to .gitignore and can be appended trough configuration in .meta.cfg.

  • MANIFEST.in.j2

    • Configuration file for the MANIFEST to include all needed files in sdist and wheel.

  • readthedocs.yaml.j2

    • Configuration for https://readthedocs.org to build the documentation over there if the package has documentation.

  • setup.cfg.j2

    • common setup.cfg, which should be copied to the repository of the package

  • tox.ini.j2

    • tox configuration, which should be copied to the repository of the package

  • tests.yml.j2

    • Configuration for GitHub actions.

The config-package script

The config-package script applies package configuration in a given Python package.

Preparation

The scripts needs a venv with some packages installed:

$ python3.11 -m venv .
$ bin/pip install .

To use the configuration provided here in a package call the following script:

$ bin/config-package <path-to-package> --type <config-type-name> [<additional-options>]

See --help for details.

The script does the following steps:

  1. Add the package name to packages.txt of the selected configuration type if it is not yet added.

  2. Copy setup.cfg, tox.ini, tests.yml, MANIFEST.in, .readthedocs.yaml (if needed), and .gitignore to the repository.

  3. Create or update a pyproject.toml project configuration file.

  4. Remove a possibly existing .coveragerc and bootstrap.py. (Coverage is now configured in tox.ini for packages which are no buildout recipes.)

  5. Run the tests via: tox. The tox script may be either on the current $PATH or in the bin subfolder of the current working directory.

  6. Create a branch and a pull request. (Prevent an automatic commit of all changes with the command line switch --no-commit, or an automatic push to GitHub using the command line switch --no-push.)

After running the script you should manually do the following steps:

  1. Check for changes in the updated repository and for the need of a change log entry over there.

  2. Make sure the package is activated on https://coveralls.io by trying to add the repository name and making it active.

  3. Check in possible changes in the zopefoundation/meta repository.

CLI arguments

The following arguments are supported.

--commit-msg=MSG

Use MSG as commit message instead of an artificial one.

--no-commit

Don’t automatically commit changes after the configuration run. Implies –no-push.

--no-push

Avoid pushing at the end of the configuration run.

--no-tests

Don’t run the package’s unit tests as part of the configuration run. Useful for quickly testing iterative configuration changes.

--branch

Define a specific git branch name to be created for the changes. By default the script creates one which includes the name of the configuration type.

The following options are only needed one time as their values are stored in .meta.toml..

--type

Define the configuration type (see Configuration types section above) to be used for the repository.

--template-overrides

Filesystem path to a folder that contains subfolders for configuration type and default templates. Used to override built-in configuration templates. Empty override template files will prevent creating the respective file in the repository you are managing with zope.meta, this way you can purposely omit creating some optional files.

--with-macos

Enable running the tests on macOS on GitHub Actions.

--with-windows

Enable running the tests on Windows on GitHub Actions.

--with-pypy

Enable PyPy support.

--with-future-python

The package supports the next upcoming Python version which does not yet have a final release thus it is not yet generally supported by the zopefoundation packages.

--oldest-python

The oldest version of Python supported by this package. Specified as version number, e.g. 3.12. This setting is optional and defaults to the lowest Python version generally supported by zopefoundation packages.

--with-docs

Enable building the documentation using Sphinx. This will also create a configuration file .readthedocs.yaml for integration with https://readthedocs.org.

--with-sphinx-doctests

Enable running the documentation as doctest using Sphinx.

Options

It is possible to configure some options in a .meta.toml file inside the package repository. This file also stores the template name and commit id of the meta repository at the time of the run. This file is generated during the configuration run, if it does not exist or at least gets updated. Example:

[meta]
template = "pure-python"
commit-id = "< commit-hash >"

[python]
with-pypy = false
with-docs = true
with-sphinx-doctests = false
with-macos = false
with-windows = false

[coverage]
fail-under = 98

[coverage-run]
additional-config = [
    "data_file = $COVERAGE_HOME.coverage",
]
omit = [
    "src/foo/bar.py",
]
source = "src"

[tox]
additional-envlist = [
    "py311-slim",
    "py312-fat",
    ]
testenv-additional-extras = [
    "extra-feature",
    ]
testenv-commands-pre = [
    "{envbindir}/buildout -c ...",
    ]
testenv-commands = [
    "{envbindir}/test {posargs:-cv}",
    "{envbindir}/test_with_gs {posargs:-cv}",
    ]
testenv-deps = [
    "zope.testrunner",
    ]
testenv-setenv = [
    "ZOPE_INTERFACE_STRICT_IRO=1",
]
testenv-additional = [
    "passenv =",
    "    DISPLAY",
    ]
coverage-basepython = "python3.13"
coverage-command = [
    "coverage run {envbindir}/test_with_gs []",
    ]
coverage-setenv = [
    "COVERAGE_HOME={toxinidir}",
    ]
coverage-additional = [
    "depends = py312,docs",
    ]
docs-deps = [
    "urllib3 < 2",
    ]

[flake8]
additional-config = [
    "# D203 1 blank line required before class docstring",
    "# E221 multiple spaces before operator",
    "# E222 multiple spaces after operator",
    "# W503 Line break occurred before a binary operator",
    "per-file-ignores =",
    "    src/foo/bar.py: E221 E222",
    "extend-ignore = D203, W503",
    ]
additional-sources = "testproj foo bar.py"

[manifest]
additional-rules = [
    "include *.foo",
    "include *.bar",
    ]

[check-manifest]
additional-ignores = [
    "docs/html/*",
    "docs/source/_static/*",
    ]
ignore-bad-ideas = [
    "src/foo/bar.mo",
    ]

[isort]
known_third_party = "ipaddress, PasteDeploy"
known_zope = "AccessControl, Acquisition, App"
known_first_party = "Products.GenericSetup, Products.CMFCore"
additional-sources = "{toxinidir}/tests {toxinidir}/bar.py"

[github-actions]
services = [
    "postgres:",
    "  image: postgres",
    ]
additional-config = [
    "- [\"3.12\",   \"py312-slim\"]",
    ]
additional-exclude = [
    "- { os: windows, config: [\"pypy-3.10\", \"pypy3\"] }",
    "- { os: macos, config: [\"pypy-3.10\", \"pypy3\"] }",
    ]
steps-before-checkout = [
    "- name: \"Set some Postgres settings\"",
    "  run: ...",
    ]
additional-install = [
    "sudo apt-get update && sudo apt-get install -y libxml2-dev libxslt-dev",
    "pip install tox-factor"
    ]
additional-build-dependencies = [
    "cffi",
    "python-ldap",
    ]
test-enviroment = [
    "TEST_DSN: 'host=localhost port=5432 user=postgres'"
    ]
test-commands = [
    "tox -f ${{ matrix.config[1] }}",
    ]

[c-code]
manylinux-install-setup = [
    "export CFLAGS=\"-pipe\"",
    ]
manylinux-aarch64-tests = [
    "cd /io/",
    "\"${PYBIN}/pip\" install tox",
    "\"${PYBIN}/tox\" -e py",
    "cd ..",
    ]

[zest-releaser]
options = [
    "prereleaser.before =",
    "    zest.pocompile.compile.main",
    ]

[git]
ignore = [
    "*.mo",
    ]

[pre-commit]
teyit-exclude = "App/tests/fixtures/error\.py"
pyupgrade-exclude = "^src/zope/proxy/__init__\.py$"


[readthedocs]
build-extra = [
    "apt_packages:",
    "  - libldap2-dev",
    ]

Meta Options

template

Name of the configuration type, to be used as the template for the repository. Currently read-only.

commit-id

Commit of the meta repository, which was used for the last configuration run. Currently read-only.

Python options

with-macos

Run the tests also on macOS on GitHub Actions: true/false, default: false

with-windows

Run the tests also on Windows on GitHub Actions: true/false, default: false

with-pypy

Does the package support PyPy: true/false

with-docs

Build the documentation via Sphinx: true/false

with-sphinx-doctests

Run the documentation as doctest using Sphinx: true/false

Coverage options

The corresponding section is named: [coverage].

fail-under

A minimal value of code coverage below which a test failure is issued.

Coverage:run options

The corresponding section is named: [coverage-run].

additional-config

Additional options for the [run] section of the coverage configuration. This option has to be a list of strings.

omit

Files to be omitted from the coverage report. This option has to be a list of strings. It defaults to an empty list.

source

This option defines the value of source in the coverage [run] section. This option has to be a string. It defaults to the name of the package if it is not set.

tox.ini options

The corresponding section is named: [tox].

additional-envlist

This option contains additional entries for the envlist in tox.ini. The configuration for the needed additional environments can be added using testenv-additional (see below). This option has to be a list of strings without indentation.

testenv-additional-extras

Additional entries for the extras option in [testenv] of tox.ini. This option has to be a list of strings without indentation.

testenv-commands-pre

Replacement for the default commands_pre option in [testenv] of tox.ini. This option has to be a list of strings without indentation.

testenv-commands

Replacement for the default commands option in [testenv] of tox.ini. This option has to be a list of strings without indentation.

testenv-deps

Additional dependencies for the deps option in [testenv] of tox.ini. This option has to be a list of strings without indentation. It is empty by default.

testenv-setenv

Set the value of the setenv option in [testenv] of tox.ini. Depending in the template used this might be an addition to the predefined values for this option. This option has to be a list of strings.

testenv-additional

Additional lines for the section [testenv] in tox.ini. This option has to be a list of strings.

coverage-basepython

This option replaces the value for the basepython option in the section [testenv:coverage]. This option has to be a string. The default value is python3.

coverage-command

This option replaces the coverage call in the section [testenv:coverage] in tox.ini. Caution: only the actual call to collect the coverage data is replaced. The calls to create the reporting are not changed. This option has to be a list or a string. If it is not set or empty the default is used.

coverage-setenv

This option defines the contents for the option setenv in the section [testenv:coverage] in tox.ini. If it has a default value (e. g. as in the buildout-recipe template), the default value is replaced by the value given here. This option has to be a list of strings.

coverage-additional

This option allows to add additional lines below [testenv:coverage] in tox.ini. This option has to be a list of strings.

docs-deps

This option allows to add additional install dependencies for [testenv:docs] in tox.ini. This option has to be a list of strings and is empty by default. Caution: The values set for this option override the ones set in [testenv].

Flake8 options

The corresponding section is named: [flake8].

additional-config

Additional configuration options be added at the end of the flake8 configuration section in setup.cfg. Caution: This option has to be a list of strings so the leading white spaces and comments are preserved when writing the value to setup.cfg.

additional-sources

Sometimes not only src and setup.py contain Python code to be checked by flake8. Additional files or directories can be configured here. This option is a string. The sources inside have to be space separated.

Manifest options

The corresponding section is named: [manifest].

additional-rules

Additional rules to be added at the end of the MANIFEST.in file. This option has to be a list of strings.

Check-manifest options

The corresponding section is named: [check-manifest].

additional-ignores

Additional files to be ignored by check-manifest via its section in setup.cfg. This option has to be a list of strings.

ignore-bad-ideas

Ignore bad idea files/directories matching these patterns. This option has to be a list of strings.

Isort options

The corresponding section is named: [isort].

Please note the usage of underscores for the option name, which used to be consistent with the name of the option in isort.

Currently only the configuration type zope-product supports isort configurations.

known_third_party

This option defines the value for known_third_party in the isort configuration. This option has to be a string. It defaults to "docutils, pkg_resources, pytz".

known_zope

This option defines the value for known_zope in the isort configuration. This option has to be a string. It defaults to the empty string.

known_first_party

This option defines the value for known_first_party in the isort configuration. This option has to be a string. It defaults to the empty string.

known_local_folder

This option defines the value for known_local_folder in the isort configuration. This option has to be a string. It defaults to the empty string.

additional-sources

This option defines additional files and/or directories where isort should be applied. This option has to be a string. It defaults to the empty string.

additional-config

Additional options for the [isort] section. This option has to be a list of strings.

GitHub Actions options

The corresponding section is named: [github-actions].

services

Lines which will be added in the services section of the GitHub Actions build section. This option has to be a list of strings.

additional-config

Additional entries for the config matrix. This option has to be a list of strings without leading whitespace but it has to start with a hyphen.

additional-exclude

Additional entries to exclude from the config matrix. This option has to be a list of strings without leading whitespace but it has to start with a hyphen.

steps-before-checkout

Add steps definitions to be inserted into tests.yml before the checkout action i. e. as the first step. This option has to be a list of strings.

additional-install

Additional lines to be executed during the install dependencies step when running the tests on GitHub Actions. This option has to be a list of strings. For the template c-code this option is currently used to replace how to install the package itself and run tests and coverage.

test-environment

Environment variables to be set during the test run. This option has to be a list of strings.

test-commands

Replacement for the test command in tests.yml. This option has to be a list of strings.

C-code options

The corresponding section is named: [c-code] it is used only for packages built with the template c-code.

manylinux-install-setup

Additional setup steps necessary in manylinux-install.sh. This option has to be a list of strings and defaults to an empty list.

manylinux-aarch64-tests

Replacement for the tests against the aarch64 architecture. This option has to be a list of strings and defaults to testing using tox against all supported Python versions, which could be too slow for some packages.

zest.releaser options

The corresponding section is named: [zest-releaser] (with an - instead of the .).

options

(Additional) options used to configure zest.releaser. This option has to be a list of strings and defaults to an empty list.

git options

The corresponding section is named: [git].

ignore

Additional lines to be added to the .gitignore file. This option has to be a list of strings and defaults to an empty list.

pre-commit options

The corresponding section is named: [pre-commit].

teyit-exclude

Regex for files to be hidden from teyit. It fails on files containing syntax errors. This option has to be a string and is omitted when not defined.

pyupgrade-exclude

Regex for files to be hidden from pyupgrade. It might be a bit overly optimistic with its changes. This option has to be a string and is omitted when not defined.

ReadTheDocs options

The corresponding section is named: [readthedocs].

build-extra

Additional lines to be added to the build configuration in the ReadTheDocs configuration file .readthedocs.yaml. This option has to be a list of strings and defaults to an empty list.

Configuration script hints

  • Calling config-package again updates a previously created pull request if there are changes made in the files config-package touches.

  • Call bin/check-python-versions <path-to-package> -h to see how to fix version mismatches in the lint tox environment.

Other helper scripts

Updating to the currently supported Python versions

There is a script update-python-support for updating a repository to the currently supported Python versions as defined in shared/package.py.

Usage

To update a repository to the currently supported Python versions call:

$ bin/update-python-support <path-to-package>

It supports a parameter --interactive to gather user input for its changes and not automatically commit them. It also supports a parameter --no-commit that prevents automatic commits but attempts to cut down on interactively asking for user input. Some of that still happens due to limitations of the zest.releaser scripts used by update-python-support.

Calling a script on multiple repositories

The config-package script only runs on a single repository. To update multiple repositories at once you can use multi-call. It runs a given script on all repositories listed in a packages.txt file.

Usage

To run a script on all packages listed in a packages.txt file call multi-call the following way:

$ bin/multi-call <name-of-the-script> <path-to-packages.txt> <path-to-clones> <arguments-for-script>

See --help for details.

The script does the following steps:

  1. It does the following steps for each line in the given packages.txt which does not start with #.

  2. Check if there is a repository in <path-to-clones> with the name of the repository. If it does not exist: clone it. If it exists: clean the clone from changes, switch to master branch and pull from origin.

  3. Call the given script with the package name and arguments for the script.

Caution

Running this script stashes any uncommitted changes in the repositories, run git stash pop to recover them.

Re-enabling GitHub Actions

After a certain period of time (currently 60 days) without commits GitHub automatically disables Actions. They can be re-enabled manually per repository. There is a script to do this for all repositories. It does no harm if Actions is already enabled for a repository.

Preparation

  • Install GitHub’s CLI application, see https://github.com/cli/cli.

  • Authorize using the application:

    • gh auth login

    • It is probably enough to do it once.

Usage

To run the script just call it:

$ bin/re-enable-actions