Skip to content

Commit 64e8889

Browse files
committed
use setuptools_scm
2 parents 537f8ca + b37d2cd commit 64e8889

File tree

4 files changed

+46
-13
lines changed

4 files changed

+46
-13
lines changed

pyproject.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
[build-system]
2-
requires = ["setuptools>=48"]
2+
requires = ["setuptools>=48", "setuptools_scm[toml]>=6.3.1"]
33
build-backend = "setuptools.build_meta"
44

5+
[tool.setuptools_scm]
6+
57
[tool.black]
68
line-length = 79
79
include = '\.pyi?$'

pytest_test_utils/matchers.py

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,17 @@
1-
import builtins
21
import collections.abc
32
import re
43
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+
)
615

716
if TYPE_CHECKING:
817
from _pytest.python_api import ApproxBase
@@ -45,18 +54,33 @@ def __eq__(self, other: Any) -> bool:
4554
return True
4655

4756

48-
class dict(
49-
builtins.dict # type: ignore[type-arg]
50-
): # pylint: disable=redefined-builtin
57+
class MatcherDict:
5158
"""Special class to eq by matching only presented dict keys"""
5259

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+
5377
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})"
5680

5781
def __eq__(self, other: object) -> bool:
5882
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())
6084

6185

6286
class unordered:
@@ -155,7 +179,7 @@ class Matcher(attrs):
155179
"""
156180

157181
any = any()
158-
dict = dict
182+
dict = MatcherDict
159183

160184
@staticmethod
161185
def attrs(**attribs: Any) -> attrs:

setup.cfg

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
[metadata]
22
name = pytest_test_utils
3-
version = 0.0.7
43
long_description = file: README.md
54
long_description_content_type = text/markdown
65
license = Apache License 2.0

tests.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,8 +109,8 @@ def test_matcher_repr(matcher: Type[Matcher]) -> None:
109109
assert repr(matcher.attrs(foo="foo")) == "attrs(foo='foo')"
110110
assert repr(matcher.any_of(3, 4)) == "any_of(3, 4)"
111111
assert (
112-
repr(matcher.dict(foo="foo", **{"bar": "bar"}))
113-
== "dict(foo='foo', bar='bar')"
112+
repr(matcher.dict(foo="foo", **{"n": 123})) # type: ignore[arg-type]
113+
== "M.dict(foo='foo', n=123)"
114114
)
115115
assert repr(matcher.instance_of(str)) == "instance_of(str)"
116116
assert (
@@ -132,6 +132,14 @@ def test_matcher_dict(matcher: Type[Matcher]) -> None:
132132
assert actual != matcher.dict(verify="bundle.pem")
133133

134134

135+
def test_matcher_dict_subclass(matcher: Type[Matcher]) -> None:
136+
class SubDict(dict): # type: ignore[type-arg]
137+
pass
138+
139+
assert SubDict(a=1) == matcher.dict()
140+
assert matcher.dict() == SubDict(a=1)
141+
142+
135143
def test_matcher_regex(matcher: Type[Matcher]) -> None:
136144
assert matcher.regex(r"^500 Internal") == "500 Internal Error"
137145
assert matcher.regex("^500 Internal") != "200 OK"

0 commit comments

Comments
 (0)