|
1 | | -import builtins |
2 | 1 | import collections.abc |
3 | 2 | import re |
4 | 3 | from datetime import datetime |
5 | | -from typing import TYPE_CHECKING, Any, AnyStr, Pattern, Tuple, Union |
| 4 | +from typing import ( |
| 5 | + TYPE_CHECKING, |
| 6 | + Any, |
| 7 | + AnyStr, |
| 8 | + Dict, |
| 9 | + Mapping, |
| 10 | + Optional, |
| 11 | + Pattern, |
| 12 | + Tuple, |
| 13 | + Union, |
| 14 | +) |
6 | 15 |
|
7 | 16 | if TYPE_CHECKING: |
8 | 17 | from _pytest.python_api import ApproxBase |
@@ -45,18 +54,33 @@ def __eq__(self, other: Any) -> bool: |
45 | 54 | return True |
46 | 55 |
|
47 | 56 |
|
48 | | -class dict( |
49 | | - builtins.dict # type: ignore[type-arg] |
50 | | -): # pylint: disable=redefined-builtin |
| 57 | +class MatcherDict: |
51 | 58 | """Special class to eq by matching only presented dict keys""" |
52 | 59 |
|
| 60 | + # Implementation notes: |
| 61 | + # - can't inherit from dict because that makes D() == M.dict() to not call |
| 62 | + # our __eq__, if D is a subclass of a dict |
| 63 | + # - should not call itself dict or use dict in repr because it creates |
| 64 | + # confusing error messages (shadowing python builtins is bad anyway) |
| 65 | + |
| 66 | + def __init__( |
| 67 | + self, d: Optional[Mapping[Any, Any]] = None, **keys: Any |
| 68 | + ) -> None: |
| 69 | + self.d: Dict[Any, Any] = {} |
| 70 | + if d: |
| 71 | + self.d.update(d) |
| 72 | + self.d.update(keys) |
| 73 | + |
| 74 | + def __len__(self) -> int: |
| 75 | + return len(self.d) |
| 76 | + |
53 | 77 | def __repr__(self) -> str: |
54 | | - inner = ", ".join(f"{k}={repr(v)}" for k, v in self.items()) |
55 | | - return f"dict({inner})" |
| 78 | + inner = ", ".join(f"{k}={repr(v)}" for k, v in self.d.items()) |
| 79 | + return f"M.dict({inner})" |
56 | 80 |
|
57 | 81 | def __eq__(self, other: object) -> bool: |
58 | 82 | assert isinstance(other, collections.abc.Mapping) |
59 | | - return all(other.get(name) == v for name, v in self.items()) |
| 83 | + return all(other.get(name) == v for name, v in self.d.items()) |
60 | 84 |
|
61 | 85 |
|
62 | 86 | class unordered: |
@@ -155,7 +179,7 @@ class Matcher(attrs): |
155 | 179 | """ |
156 | 180 |
|
157 | 181 | any = any() |
158 | | - dict = dict |
| 182 | + dict = MatcherDict |
159 | 183 |
|
160 | 184 | @staticmethod |
161 | 185 | def attrs(**attribs: Any) -> attrs: |
|
0 commit comments