Source code for jsonschema_diff.core.tools.compare

from __future__ import annotations

from types import NoneType
from typing import TYPE_CHECKING, Any, TypeAlias, cast

if TYPE_CHECKING:  # prevents import cycle
    from .. import Compare


[docs] COMPARE_RULES_TYPE: TypeAlias = dict[ type | tuple[type, type] | str | tuple[str, type, type] | tuple[str, type], type["Compare"], ]
"""Mapping *search pattern* → *Compare* subclass."""
[docs] class CompareRules: """Pick an appropriate comparator class according to rule precedence.""" # ------------------------------------------------------------------ # # Public helpers # ------------------------------------------------------------------ # @staticmethod
[docs] def get_comparator_from_values( rules: COMPARE_RULES_TYPE, default: type["Compare"], key: str, old: Any, new: Any, ) -> type["Compare"]: """Wrapper that resolves comparator from **values**.""" return CompareRules.get_comparator(rules, default, key, type(old), type(new))
@staticmethod
[docs] def get_comparator( rules: COMPARE_RULES_TYPE, default: type["Compare"], key: str, old: type, new: type, ) -> type["Compare"]: """ Resolve a comparator class according to the following lookup order: 1. ``(key, old_type, new_type)`` 2. ``key`` 3. ``(old_type, new_type)`` 4. ``old_type`` or ``new_type`` (if one of them is ``NoneType``) 5. *default* Parameters ---------- rules : dict Precedence map. default : Compare subclass Fallback comparator. key : str Field name. old, new : type Types being compared. """ for search in [ ((key, old, new)), (key), ((old, new)), ]: tuple_types = rules.get(cast(Any, search), None) if tuple_types is not None: return tuple_types else: if old is NoneType: return rules.get(new, default) elif old is not NoneType or old is new: return rules.get(old, default) else: return default