Compare dictionaries, lists and other objects convenient and readable
Project description
Lookslike - Simple datatype comparison
Lookslike is a library to simplify comparison of two objects (like numbers) within complex structures (like dictionaries) in a simple and readable way.
For example it can be used to compare JSON data from server responses.
A simple example would be this:
{'num': 42, 'alph': 'abcd'} == {'num': Like(int), 'alph': Like(str)} # -> True
Usage
import re
from lookslike import Like, utils
# This basically meant to simplify object comparison:
server_response = {'timestamp': 42, 'uuid': 'abcd'}
server_response == {'timestamp': Like(int), 'uuid': Like(str)} # True
# Check for type
42 == Like(int) # True
42 == Like(float) # False
# Check using regular expressions
'abc' == Like(re.compile("a.*")) # True
'abc' == Like(re.compile('a')) # False
123.456 == Like(re.compile("\d+\.\d+")) # True
# Check using custom function
42 == Like(lambda value: 40 < value < 44) # True
# Combine multiple checks
42 == Like(int, lambda value: 40 < value < 44) # True
42 == Like(float, lambda value: 40 < value < 44) # False
# Convert values
['c', 'b', 'a'] == Like(['a', 'b', 'c'], convert=sorted) # True
{'a': 1, 'b': 'not important'} == Like({'a': 1},
convert=utils.filter_keys(['a'])) # True
# "Real world" example
def test_server_response():
server_response = { # This is your test object of course
'response_id': 42,
'timestamp': 2134567.2355,
'pets': ['cat', 'dog', 'chicken'],
'number_of_pets': 3,
'info_url': 'https://petsdb.info/',
'vet name': 'Dr. Murphey',
'home': {
'home_id': 1242,
'address': {
'street': 'Rabbit street 42',
'city': 'New Bark',
}
}
}
assert server_response == {
'response_id': Like(int),
'timestamp': Like(float),
'pets': Like(['cat', 'chicken', 'dog'], convert=sorted),
'number_of_pets': 3,
'info_url': Like(lambda value: value.startswith('https://')),
'vet name': Like(re.compile('Dr\. .*')),
'home': {
'home_id': Like(int),
'address': Like({'city': 'New Bark'}, convert=utils.filter_keys(['city']))
}
} # True
To consider
When you provide a regex pattern, there are some things to consider:
Pattern has to match the whole string
When you provide a regex Pattern, it has to match the whole string. This is to prevent False-positives. For example:
This regex re.match("a", "abc")
will find a match.
But "abc" == Like(re.compile("a"))
will be False. Instead you have to use
"abc" == Like(re.compile("a.*")
Comparing strings with bytes does not raise an Exception
Normally, you will get a TypeError when doing something like
this re.match(b'abc', 'a')
However, this b'abc' == Like(re.compile("a")
will return False instead without raising
an exception.
Other utilities
If you want to compare JSON only and want a tool that is more standardized you can have a look at jsonschema.
If you want not only to check, but to convert dictionaries to real Python objects, have a look at pydantic.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.