Skip to main content

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.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distribution

lookslike-0.9-py3-none-any.whl (5.1 kB view hashes)

Uploaded Python 3

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page