1from typing import Any
2from typing import Generic
3from typing import TypeVar
4
5import attr
6
7from _pytest.compat import final
8from _pytest.compat import TYPE_CHECKING
9
10if TYPE_CHECKING:
11    from typing import Type  # noqa: F401 (used in type string)
12
13
14class PytestWarning(UserWarning):
15    """Base class for all warnings emitted by pytest."""
16
17    __module__ = "pytest"
18
19
20@final
21class PytestAssertRewriteWarning(PytestWarning):
22    """Warning emitted by the pytest assert rewrite module."""
23
24    __module__ = "pytest"
25
26
27@final
28class PytestCacheWarning(PytestWarning):
29    """Warning emitted by the cache plugin in various situations."""
30
31    __module__ = "pytest"
32
33
34@final
35class PytestConfigWarning(PytestWarning):
36    """Warning emitted for configuration issues."""
37
38    __module__ = "pytest"
39
40
41@final
42class PytestCollectionWarning(PytestWarning):
43    """Warning emitted when pytest is not able to collect a file or symbol in a module."""
44
45    __module__ = "pytest"
46
47
48@final
49class PytestDeprecationWarning(PytestWarning, DeprecationWarning):
50    """Warning class for features that will be removed in a future version."""
51
52    __module__ = "pytest"
53
54
55@final
56class PytestExperimentalApiWarning(PytestWarning, FutureWarning):
57    """Warning category used to denote experiments in pytest.
58
59    Use sparingly as the API might change or even be removed completely in a
60    future version.
61    """
62
63    __module__ = "pytest"
64
65    @classmethod
66    def simple(cls, apiname: str) -> "PytestExperimentalApiWarning":
67        return cls(
68            "{apiname} is an experimental api that may change over time".format(
69                apiname=apiname
70            )
71        )
72
73
74@final
75class PytestUnhandledCoroutineWarning(PytestWarning):
76    """Warning emitted for an unhandled coroutine.
77
78    A coroutine was encountered when collecting test functions, but was not
79    handled by any async-aware plugin.
80    Coroutine test functions are not natively supported.
81    """
82
83    __module__ = "pytest"
84
85
86@final
87class PytestUnknownMarkWarning(PytestWarning):
88    """Warning emitted on use of unknown markers.
89
90    See :ref:`mark` for details.
91    """
92
93    __module__ = "pytest"
94
95
96_W = TypeVar("_W", bound=PytestWarning)
97
98
99@final
100@attr.s
101class UnformattedWarning(Generic[_W]):
102    """A warning meant to be formatted during runtime.
103
104    This is used to hold warnings that need to format their message at runtime,
105    as opposed to a direct message.
106    """
107
108    category = attr.ib(type="Type[_W]")
109    template = attr.ib(type=str)
110
111    def format(self, **kwargs: Any) -> _W:
112        """Return an instance of the warning category, formatted with given kwargs."""
113        return self.category(self.template.format(**kwargs))
114
115
116PYTESTER_COPY_EXAMPLE = PytestExperimentalApiWarning.simple("testdir.copy_example")
117