Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add mapping_includes matcher #13

Merged
merged 1 commit into from
Jul 26, 2019

Conversation

ErwinJunge
Copy link
Contributor

@ErwinJunge ErwinJunge commented Jul 17, 2019

This adds a matcher called is_mapping_with to allow partial dict matches (i.e. allow extra keys).

@ErwinJunge
Copy link
Contributor Author

FYI: the travis errors are not related to the code changes in this PR, they have something to do with travis setting up py32 and py33.

@mwilliamson
Copy link
Owner

Thanks for the pull request. Rebasing onto master should fix the Python 3.2 and 3.3 errors (by dropping support).

I'm not sure the naming of the function is very clear. We already have an includes() function for iterables. Perhaps mapping_includes would be clearer?

@@ -3,16 +3,21 @@
from .results import matched, unmatched, indented_list


def is_mapping(matchers):
def is_mapping(matchers, allow_extra=False):
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we're creating a separate function to allow extra keys, I don't think we should allow the argument in is_mapping().

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I went with the kwarg for 2 reasons:

  • maximize code reuse
  • it makes is_mapping_with into syntactic sugar around is_mapping

Both of those seemed to me to be good reasons for this structure, but if you prefer that I copypaste and modify is_mapping I'll gladly do so.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Modified.

@istest
def description_describes_keys_and_value_matchers():
matcher = is_mapping_with({"a": equal_to(1), "b": equal_to(2)})
assert_equal("mapping with items:\n * 'a': 1\n * 'b': 2", matcher.describe())
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This description is the same as would be produced with is_mapping(), but there should be some way of distinguishing the two.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, modified.

@ErwinJunge ErwinJunge force-pushed the feature/is_mapping_with branch from 219d48e to ded9c01 Compare July 17, 2019 20:43
@ErwinJunge
Copy link
Contributor Author

Thanks for the pull request. Rebasing onto master should fix the Python 3.2 and 3.3 errors (by dropping support).

I'm not sure the naming of the function is very clear. We already have an includes() function for iterables. Perhaps mapping_includes would be clearer?

Rebased. The naming ties into #14 where I introduce is_sequence_with (which is subtly different from includes)

@mwilliamson
Copy link
Owner

I'm not sure is_sequence_with() is the right name in the other pull request ("with" doesn't imply the subsetting behaviour to me), and this feels closer to includes() than is_sequence_with() since this doesn't care about ordering.

README.rst Outdated
@@ -117,6 +117,18 @@ For instance, ``has_attrs(name="bob")`` is equivalent to ``has_attrs(name=equal_
"b": equal_to(4),
}))

* ``is_mapping_with(**matchers)``: matches a mapping, such as a ``dict``, if it has the same keys with matching values.
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the arguments here are matchers rather than **matchers (I made a mistake, now fixed, when documenting is_mapping())

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, modified.

@ErwinJunge ErwinJunge force-pushed the feature/is_mapping_with branch from ded9c01 to a69aa4a Compare July 17, 2019 21:01
@ErwinJunge ErwinJunge changed the title Add is_mapping_with matcher Add mapping_includes matcher Jul 17, 2019
return "mapping including items:{0}".format(indented_list(sorted(
"{0!r}: {1}".format(key, matcher.describe())
for key, matcher in self._matchers.items()
)))
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The split in logic here feels awkward to me: half the specialisation for mapping_includes() is in this subclass, while the other half is in the superclass. I think it'd be simpler to switch on self._allow_extra in IsMappingMatcher.describe(). Other than that, I think this looks good.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I went with a slightly more subclassing-based approach and got rid of _allow_extra entirely. What do you think of the latest push?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tend to avoid implementation inheritance (or more specifically the template pattern). I'd suggest either switching on self._allow_extra, or creating two separate classes that both delegate to a common matching function.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've put self._allow_extra back in.

@ErwinJunge ErwinJunge force-pushed the feature/is_mapping_with branch from a69aa4a to c0f4883 Compare July 18, 2019 07:25
@ErwinJunge ErwinJunge force-pushed the feature/is_mapping_with branch from c0f4883 to d4476ce Compare July 25, 2019 17:10
@mwilliamson mwilliamson merged commit 7917d82 into mwilliamson:master Jul 26, 2019
@mwilliamson
Copy link
Owner

Thanks! I've merged this, and made a couple of minor tweaks to the implementation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants