• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

psf / black / 7692220850

29 Jan 2024 06:46AM UTC coverage: 96.45%. Remained the same
7692220850

Pull #4192

github

web-flow
Bump peter-evans/create-or-update-comment from 3.1.0 to 4.0.0

Bumps [peter-evans/create-or-update-comment](https://github.com/peter-evans/create-or-update-comment) from 3.1.0 to 4.0.0.
- [Release notes](https://github.com/peter-evans/create-or-update-comment/releases)
- [Commits](https://github.com/peter-evans/create-or-update-comment/compare/23ff15729...71345be02)

---
updated-dependencies:
- dependency-name: peter-evans/create-or-update-comment
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Pull Request #4192: Bump peter-evans/create-or-update-comment from 3.1.0 to 4.0.0

3021 of 3232 branches covered (0.0%)

7145 of 7408 relevant lines covered (96.45%)

4.82 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

85.71
/tests/optional.py
1
"""
2
Allows configuring optional test markers in config, see pyproject.toml.
3

4
Run optional tests with `pytest --run-optional=...`.
5

6
Mark tests to run only if an optional test ISN'T selected by prepending the mark with
7
"no_".
8

9
You can specify a "no_" prefix straight in config, in which case you can mark tests
10
to run when this tests ISN'T selected by omitting the "no_" prefix.
11

12
Specifying the name of the default behavior in `--run-optional=` is harmless.
13

14
Adapted from https://pypi.org/project/pytest-optional-tests/, (c) 2019 Reece Hart
15
"""
16

17
import itertools
5✔
18
import logging
5✔
19
import re
5✔
20
from functools import lru_cache
5✔
21
from typing import TYPE_CHECKING, FrozenSet, List, Set
5✔
22

23
import pytest
5✔
24

25
try:
5✔
26
    from pytest import StashKey
5✔
27
except ImportError:
×
28
    # pytest < 7
29
    #
30
    # "isort: skip" is needed or it moves the "type: ignore" to the following line
31
    # because of the line length, and then mypy complains.
32
    # Of course, adding the "isort: skip" means that
33
    # flake8-bugbear then also complains about the line length,
34
    # so we *also* need a "noqa" comment for good measure :)
35
    from _pytest.store import (  # type: ignore[import-not-found, no-redef]  # isort: skip  # noqa: B950
×
36
        StoreKey as StashKey,
37
    )
38

39
log = logging.getLogger(__name__)
5✔
40

41

42
if TYPE_CHECKING:
5!
43
    from _pytest.config import Config
×
44
    from _pytest.config.argparsing import Parser
×
45
    from _pytest.mark.structures import MarkDecorator
×
46
    from _pytest.nodes import Node
×
47

48

49
ALL_POSSIBLE_OPTIONAL_MARKERS = StashKey[FrozenSet[str]]()
5✔
50
ENABLED_OPTIONAL_MARKERS = StashKey[FrozenSet[str]]()
5✔
51

52

53
def pytest_addoption(parser: "Parser") -> None:
5✔
54
    group = parser.getgroup("collect")
5✔
55
    group.addoption(
5✔
56
        "--run-optional",
57
        action="append",
58
        dest="run_optional",
59
        default=None,
60
        help="Optional test markers to run; comma-separated",
61
    )
62
    parser.addini("optional-tests", "List of optional tests markers", "linelist")
5✔
63

64

65
def pytest_configure(config: "Config") -> None:
5✔
66
    """Optional tests are markers.
67

68
    Use the syntax in https://docs.pytest.org/en/stable/mark.html#registering-marks.
69
    """
70
    ot_ini = config.inicfg.get("optional-tests") or []
5✔
71
    ot_markers = set()
5✔
72
    ot_run: Set[str] = set()
5✔
73
    if isinstance(ot_ini, str):
5!
74
        ot_ini = ot_ini.strip().split("\n")
×
75
    marker_re = re.compile(r"^\s*(?P<no>no_)?(?P<marker>\w+)(:\s*(?P<description>.*))?")
5✔
76
    for ot in ot_ini:
5✔
77
        m = marker_re.match(ot)
5✔
78
        if not m:
5!
79
            raise ValueError(f"{ot!r} doesn't match pytest marker syntax")
×
80

81
        marker = (m.group("no") or "") + m.group("marker")
5✔
82
        description = m.group("description")
5✔
83
        config.addinivalue_line("markers", f"{marker}: {description}")
5✔
84
        config.addinivalue_line(
5✔
85
            "markers", f"{no(marker)}: run when `{marker}` not passed"
86
        )
87
        ot_markers.add(marker)
5✔
88

89
    # collect requested optional tests
90
    passed_args = config.getoption("run_optional")
5✔
91
    if passed_args:
5!
92
        ot_run.update(itertools.chain.from_iterable(a.split(",") for a in passed_args))
5✔
93
    ot_run |= {no(excluded) for excluded in ot_markers - ot_run}
5✔
94
    ot_markers |= {no(m) for m in ot_markers}
5✔
95

96
    log.info("optional tests to run:", ot_run)
5✔
97
    unknown_tests = ot_run - ot_markers
5✔
98
    if unknown_tests:
5!
99
        raise ValueError(f"Unknown optional tests wanted: {unknown_tests!r}")
×
100

101
    store = config._store
5✔
102
    store[ALL_POSSIBLE_OPTIONAL_MARKERS] = frozenset(ot_markers)
5✔
103
    store[ENABLED_OPTIONAL_MARKERS] = frozenset(ot_run)
5✔
104

105

106
def pytest_collection_modifyitems(config: "Config", items: "List[Node]") -> None:
5✔
107
    store = config._store
5✔
108
    all_possible_optional_markers = store[ALL_POSSIBLE_OPTIONAL_MARKERS]
5✔
109
    enabled_optional_markers = store[ENABLED_OPTIONAL_MARKERS]
5✔
110

111
    for item in items:
5✔
112
        all_markers_on_test = {m.name for m in item.iter_markers()}
5✔
113
        optional_markers_on_test = all_markers_on_test & all_possible_optional_markers
5✔
114
        if not optional_markers_on_test or (
5✔
115
            optional_markers_on_test & enabled_optional_markers
116
        ):
117
            continue
5✔
118
        log.info("skipping non-requested optional", item)
5✔
119
        item.add_marker(skip_mark(frozenset(optional_markers_on_test)))
5✔
120

121

122
@lru_cache()
5✔
123
def skip_mark(tests: FrozenSet[str]) -> "MarkDecorator":
5✔
124
    names = ", ".join(sorted(tests))
5✔
125
    return pytest.mark.skip(reason=f"Marked with disabled optional tests ({names})")
5✔
126

127

128
@lru_cache()
5✔
129
def no(name: str) -> str:
5✔
130
    if name.startswith("no_"):
5!
131
        return name[len("no_") :]
5✔
132
    return "no_" + name
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc