Skip to content

Instantly share code, notes, and snippets.

@bofm

bofm/paths_eq.py

Created Jul 10, 2020
Embed
What would you like to do?
from dataclasses import dataclass
import pytest
from lib.util import paths_eq
from collections.abc import Mapping
_MISS = object()
def get(obj, field, default=None):
if field.isnumeric():
i = int(field)
try:
return obj[i]
except IndexError:
return default
elif isinstance(obj, Mapping):
return obj.get(field, default)
return getattr(obj, field, default)
def getpath(obj, path, default=None):
for sp in path.split('.'):
obj = get(obj, sp, _MISS)
if obj == _MISS:
return default
return obj
def path_eq(path, a, b):
return getpath(a, path, _MISS) == getpath(b, path, _MISS)
def paths_eq(paths, a, b):
return all(path_eq(p, a, b) for p in paths)
@dataclass
class A:
a: int
@dataclass
class B:
a: A
l: list
@pytest.mark.parametrize(
'a,b,paths,expected_result',
[
[{}, {}, [], True],
[[], [], [], True],
[None, None, [], True],
[object(), object(), [], True],
[{1}, {1}, ['a'], True],
[{'a': 1}, {'a': 1}, ['a'], True],
[{'a': {'b': 1}}, {'a': {'b': 1}}, ['a'], True],
[{'a': {'b': 1}}, {'a': {'b': 2}}, ['a'], False],
[{'a': A(a=1)}, {'a': A(a=1)}, ['a'], True],
[{'a': A(a=1)}, {'a': A(a=2)}, ['a'], False],
[{'b': B(a=A(a=1), l=[1, 2])}, {'b': B(a=A(a=1), l=[1, 2])}, ['b'], True],
[{'b': B(a=A(a=1), l=[1, 2])}, {'b': B(a=A(a=1), l=[1, 2])}, ['b.a'], True],
[{'b': B(a=A(a=1), l=[1, 2])}, {'b': B(a=A(a=1), l=[1, 3])}, ['b.a'], True],
[{'b': B(a=A(a=1), l=[1, 2])}, {'b': B(a=A(a=1), l=[1, 3])}, ['b'], False],
[{'b': B(a=A(a=1), l=[1, 2])}, {'b': B(a=A(a=1), l=[1, 2])}, ['b.l'], True],
[{'b': B(a=A(a=1), l=[1, 2])}, {'b': B(a=A(a=1), l=[1, 3])}, ['b.l'], False],
[{'b': B(a=A(a=1), l=[1, 2])}, {'b': B(a=A(a=1), l=[1, 3])}, ['a', 'a.b'], True],
[{'l': [1, 2, 3]}, {'l': [1, 2, 3]}, ['l.0'], True],
[{'l': [1, 2, 3]}, {'l': [2, 2, 3]}, ['l.0'], False],
[{'l': [1, 2, 3]}, {'l': [2, 2, 3]}, ['l.99'], True],
],
)
def test_paths_equal(a, b, paths, expected_result):
actual_result = paths_eq(paths, a, b)
assert expected_result == actual_result
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment