Skip to content

Instantly share code, notes, and snippets.

@craigds
Created August 21, 2023 22:57
Show Gist options
  • Save craigds/8383da1b62dbfec54db8e4520c2f26ca to your computer and use it in GitHub Desktop.
Save craigds/8383da1b62dbfec54db8e4520c2f26ca to your computer and use it in GitHub Desktop.
import pytest
from _pytest.python_api import ApproxBase
from _pytest.assertion.util import _compare_eq_dict
# Subclassing ApproxBase means we can patch into the pytest machinery for
# custom assertion error messages, since that class provides a `_repr_compare` method
# that is not present on any other types.
# https://github.com/pytest-dev/pytest/blob/556e075d23a91eb42821129a5d874ec3174e17ad/src/_pytest/assertion/util.py#L219
# There doesn't appear to be any other API to do this.
class ContainsSubdict(ApproxBase):
"""
Tests True for equality against a superdict that contains a subdict
"""
def __init__(self, subdict):
self.subdict = subdict
def __repr__(self):
return repr(self.subdict)
def _repr_compare(self, superdict):
if isinstance(self.subdict, list):
for i, subdict, superdict in enumerate(
zip_longest(self.subdict, superdict)
):
if not subdict.items() <= superdict.items():
return [
"comparison failed at item {i} of list:",
*self._repr_compare_dicts(subdict, superdict),
]
return []
else:
return self._repr_compare_dicts(self.subdict, superdict)
def _repr_compare_dicts(self, subdict, superdict):
# Just return the error message for dict equality, but first subtract the items that are
# not relevant to the subdict, otherwise the error message will be too noisy.
smaller_superdict = {k: v for (k, v) in superdict.items() if k in subdict}
return _compare_eq_dict(smaller_superdict, subdict)
def __eq__(self, superdict):
if isinstance(self.subdict, list):
for subdict, superdict in zip_longest(self.subdict, superdict):
if not subdict.items() <= superdict.items():
return False
else:
if not self.subdict.items() <= superdict.items():
return False
return True
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment