A context manager to record raised warnings. Adapted from `warnings.catch_warnings`.
| 156 | |
| 157 | |
| 158 | class WarningsRecorder(warnings.catch_warnings): |
| 159 | """A context manager to record raised warnings. |
| 160 | |
| 161 | Adapted from `warnings.catch_warnings`. |
| 162 | """ |
| 163 | |
| 164 | def __init__(self, *, _ispytest: bool = False) -> None: |
| 165 | check_ispytest(_ispytest) |
| 166 | # Type ignored due to the way typeshed handles warnings.catch_warnings. |
| 167 | super().__init__(record=True) # type: ignore[call-arg] |
| 168 | self._entered = False |
| 169 | self._list: List[warnings.WarningMessage] = [] |
| 170 | |
| 171 | @property |
| 172 | def list(self) -> List["warnings.WarningMessage"]: |
| 173 | """The list of recorded warnings.""" |
| 174 | return self._list |
| 175 | |
| 176 | def __getitem__(self, i: int) -> "warnings.WarningMessage": |
| 177 | """Get a recorded warning by index.""" |
| 178 | return self._list[i] |
| 179 | |
| 180 | def __iter__(self) -> Iterator["warnings.WarningMessage"]: |
| 181 | """Iterate through the recorded warnings.""" |
| 182 | return iter(self._list) |
| 183 | |
| 184 | def __len__(self) -> int: |
| 185 | """The number of recorded warnings.""" |
| 186 | return len(self._list) |
| 187 | |
| 188 | def pop(self, cls: Type[Warning] = Warning) -> "warnings.WarningMessage": |
| 189 | """Pop the first recorded warning, raise exception if not exists.""" |
| 190 | for i, w in enumerate(self._list): |
| 191 | if issubclass(w.category, cls): |
| 192 | return self._list.pop(i) |
| 193 | __tracebackhide__ = True |
| 194 | raise AssertionError("%r not found in warning list" % cls) |
| 195 | |
| 196 | def clear(self) -> None: |
| 197 | """Clear the list of recorded warnings.""" |
| 198 | self._list[:] = [] |
| 199 | |
| 200 | # Type ignored because it doesn't exactly warnings.catch_warnings.__enter__ |
| 201 | # -- it returns a List but we only emulate one. |
| 202 | def __enter__(self) -> "WarningsRecorder": # type: ignore |
| 203 | if self._entered: |
| 204 | __tracebackhide__ = True |
| 205 | raise RuntimeError("Cannot enter %r twice" % self) |
| 206 | _list = super().__enter__() |
| 207 | # record=True means it's None. |
| 208 | assert _list is not None |
| 209 | self._list = _list |
| 210 | warnings.simplefilter("always") |
| 211 | return self |
| 212 | |
| 213 | def __exit__( |
| 214 | self, |
| 215 | exc_type: Optional[Type[BaseException]], |
no outgoing calls