summaryrefslogtreecommitdiff
path: root/src/_pytest/assertion
diff options
context:
space:
mode:
authorKarthikeyan Singaravelan <tir.karthi@gmail.com>2020-07-28 12:24:24 +0000
committerRan Benita <ran@unusedvar.com>2020-10-31 14:41:53 +0200
commit9a0f4e57ee6ec0602e2f5e6e53920bb1d985e316 (patch)
tree52f9029d11846215e2d5efd32dd34ec68dfbf570 /src/_pytest/assertion
parent5913cd20ec7c3f0a8305aa072110da5c896fddb8 (diff)
downloadpytest-9a0f4e57ee6ec0602e2f5e6e53920bb1d985e316.tar.gz
Add support to display field names in namedtuple diffs.
Diffstat (limited to 'src/_pytest/assertion')
-rw-r--r--src/_pytest/assertion/util.py20
1 files changed, 17 insertions, 3 deletions
diff --git a/src/_pytest/assertion/util.py b/src/_pytest/assertion/util.py
index 93fa48b8e..da1ffd15e 100644
--- a/src/_pytest/assertion/util.py
+++ b/src/_pytest/assertion/util.py
@@ -110,6 +110,10 @@ def isset(x: Any) -> bool:
return isinstance(x, (set, frozenset))
+def isnamedtuple(obj: Any) -> bool:
+ return isinstance(obj, tuple) and getattr(obj, "_fields", None) is not None
+
+
def isdatacls(obj: Any) -> bool:
return getattr(obj, "__dataclass_fields__", None) is not None
@@ -171,14 +175,20 @@ def _compare_eq_any(left: Any, right: Any, verbose: int = 0) -> List[str]:
if istext(left) and istext(right):
explanation = _diff_text(left, right, verbose)
else:
- if issequence(left) and issequence(right):
+ if type(left) == type(right) and (
+ isdatacls(left) or isattrs(left) or isnamedtuple(left)
+ ):
+ # Note: unlike dataclasses/attrs, namedtuples compare only the
+ # field values, not the type or field names. But this branch
+ # intentionally only handles the same-type case, which was often
+ # used in older code bases before dataclasses/attrs were available.
+ explanation = _compare_eq_cls(left, right, verbose)
+ elif issequence(left) and issequence(right):
explanation = _compare_eq_sequence(left, right, verbose)
elif isset(left) and isset(right):
explanation = _compare_eq_set(left, right, verbose)
elif isdict(left) and isdict(right):
explanation = _compare_eq_dict(left, right, verbose)
- elif type(left) == type(right) and (isdatacls(left) or isattrs(left)):
- explanation = _compare_eq_cls(left, right, verbose)
elif verbose > 0:
explanation = _compare_eq_verbose(left, right)
if isiterable(left) and isiterable(right):
@@ -408,6 +418,10 @@ def _compare_eq_cls(left: Any, right: Any, verbose: int) -> List[str]:
elif isattrs(left):
all_fields = left.__attrs_attrs__
fields_to_check = [field.name for field in all_fields if getattr(field, "eq")]
+ elif isnamedtuple(left):
+ fields_to_check = left._fields
+ else:
+ assert False
indent = " "
same = []