Skip to content

Parse a mini-language for selecting objects by tag or name

[Home | GitLab | PyPI | ReadTheDocs]


The parse-stages Python library may be used by other tools to group objects (e.g. Tox or Nox test environments) for step-by-step processing (e.g. running some tests in parallel, then only running others if the first group passes).

The language used by the library is described in the Grouping stages section.


A program that uses the parse-stages library should specify it in its list of requirements, e.g. using PEP508 syntax:

parse-stages >= 0.1.8, < 0.2

Parsing a stage specification

The parse_spec() function parses a string specification into a BoolExpr object that may later be used to select matching objects (e.g. test environments).

    e_check = parse_stages.parse_spec("@check")
    e_check_quick = parse_stages.parse_spec("@check and @quick")
    e_check_no_ruff = parse_stages.parse_spec("@check and not ruff")

    specs = [(spec, parse_stages.parse_spec(spec)) for spec in args.stage_specs]

Check whether an object matches a parsed specification

The parse-stages library provides two base dataclasses for objects that may be matched against parsed expressions: TaggedFrozen and Tagged. Both classes have the same members:

When a BoolExpr object's evaluate() method is called for a specific TaggedFrozen or Tagged object, it checks whether the specification matches the tags and keywords defined for this object. Tags are matched exactly, while a keyword is considered to match if it is contained in the checked string; e.g. pep would match both pep8 and exp_pep563, while @black would not match a black-reformat tag.

The get_keyword_haystacks() method returns the strings to look in for matching keywords. By default, it only returns the name field; however, it may be extended, e.g. for Nox sessions it may also return the name of the Python function that implements the session, for test classes with methods it may return the class name and the method name, etc.

    # Obtain a list (okay, a dictionary) of test environments in some way
    tox_envs = get_tox_environments()  # {"ruff": {"tags": ["check", "quick"]}, ...}

    # Convert them to objects that the parsed expressions can match
    all_envs = [
        parse_stages.TaggedFrozen(name, env["tags"])
        for name, env in tox_envs.items()

    # Or define our own class that may hold additional information
    class TestEnv(parse_stages.TaggedFrozen):
        """A single test environment: name, tags, etc."""

    all_envs = [TestEnv(name, env["tags"], ...) for name, env in tox_envs.items()]

    # Select the ones that match the "@check" expression
    matched = [env for env in all_envs if e_check.evaluate(env)]

    # Or if we only care about the names...
    quick_names = [ for env in all_envs if e_check_quick.evaluate(env)]


The parse-stages library was written by Peter Pentchev. It is developed in a GitLab repository. This documentation is hosted at Ringlet with a copy at ReadTheDocs.