项目作者: qweeze

项目描述 :
A tool for partial comparison of (nested) data structures
高级语言: Python
项目地址: git://github.com/qweeze/matchlib.git
创建时间: 2019-02-17T14:35:06Z
项目社区:https://github.com/qweeze/matchlib

开源协议:MIT License

下载


matchlib

PyPI version

This package provides a handy way to partially compare python data structures
(typically nested lists/dictionaries).

Installation

  1. pip install matchlib

Usage

  1. from matchlib import matches
  2. user = {
  3. 'id': 42,
  4. 'name': 'John Doe',
  5. 'email': 'johndoe@gmail.com',
  6. 'posts': [
  7. {
  8. 'id': 1,
  9. 'text': 'some text'
  10. },
  11. {
  12. 'id': 2,
  13. 'text': 'lorem ipsum',
  14. 'comments': [42, 142, 242]
  15. }
  16. ]
  17. }
  18. assert matches(
  19. user,
  20. {
  21. 'id': ...,
  22. 'name': 'John Doe',
  23. 'email': 'johndoe@gmail.com',
  24. ...: ...
  25. }
  26. )

Same can be achieved using standard == operator with matchlib.Partial object:

  1. from matchlib import Partial
  2. assert user == Partial({
  3. 'id': 42,
  4. 'email': 'johndoe@gmail.com',
  5. ...: ...
  6. })

The ... “wildcard” could be placed at any nested level.
Let’s say we only need to check that comment 142 is present in specific post:

  1. assert user == Partial({
  2. 'posts': [
  3. ...,
  4. {
  5. 'id': 2,
  6. 'comments': [..., 142, ...],
  7. ...: ...
  8. }
  9. ],
  10. ...: ...
  11. })

Matching rules are simple:

  • In lists and tuples ... matches zero or more elements and order is preserved:

    1. Partial([1, 2, ...]) == [1, 2, 3, 4]
    2. Partial([1, 2, ...]) == [1, 2]
    3. Partial([1, 2, ...]) != [0, 1, 2]
    4. Partial([1, 2, ...]) != [2, 1]
  • Same for the sets except they are unordered:

    1. Partial({1, 2, ...}) == {1, 2}
    2. Partial({1, 2, ...}) == {0, 1, 2, 3}
    3. Partial({1, 2, ...}) != {0, 1, 3}
  • As dict value ... matches any object:
    1. Partial({'a': 1, 'b': ...}) == {'a': 1, 'b': 2}
  • As dict key ... matches any key if assosiated values match:
    1. Partial({'a': 1, ...: 2}) == {'a': 2, 'b': 2}
  • When passed as both key and value matches zero or more arbitrary key-value pairs:
    1. Partial({'a': 1, ...: ...}) == {'a': 1, 'b': 2, 'c': 3}

Some more hacks

mathchlib provides a Regex object that allows to match an arbitrary string element
(except if it is a dict key) against a regular expression.
Also pytest.approx is supported for floating-point numbers comparison:

  1. from pytest import approx
  2. from matchlib import Regex, Partial
  3. account = {
  4. 'id': 1,
  5. 'balance': 1007.62,
  6. 'owner': {
  7. 'email': 'user42@domain.com',
  8. }
  9. }
  10. assert account == Partial({
  11. 'id': ...,
  12. 'balance': approx(1000, 0.1),
  13. 'owner': {
  14. 'email': Regex(r'\w+@domain\.com')
  15. }
  16. })

If for any reason you dislike Ellipsis literal (...)
a matchlib.Any object can be used interchangeably.