Equality
coola.equality ¶
Contain code to check if two objects are equal or not.
coola.equality.objects_are_allclose ¶
objects_are_allclose(
actual: object,
expected: object,
*,
rtol: float = 1e-05,
atol: float = 1e-08,
equal_nan: bool = False,
show_difference: bool = False,
max_depth: int = 1000,
registry: EqualityTesterRegistry | None = None
) -> bool
Indicate if two objects are equal within a tolerance.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
actual
|
object
|
The actual input. |
required |
expected
|
object
|
The expected input. |
required |
rtol
|
float
|
The relative tolerance parameter. Must be non-negative. |
1e-05
|
atol
|
float
|
The absolute tolerance parameter. Must be non-negative. |
1e-08
|
equal_nan
|
bool
|
If |
False
|
show_difference
|
bool
|
If |
False
|
max_depth
|
int
|
Maximum recursion depth for nested comparisons. Must be positive. Defaults to 1000. |
1000
|
registry
|
EqualityTesterRegistry | None
|
The registry with the equality tester to use. |
None
|
Returns:
| Type | Description |
|---|---|
bool
|
|
Raises:
| Type | Description |
|---|---|
ValueError
|
if |
RecursionError
|
if recursion depth exceeds |
Example
>>> import torch
>>> from coola.equality import objects_are_allclose
>>> objects_are_allclose(
... [torch.ones(2, 3), torch.zeros(2)],
... [torch.ones(2, 3), torch.zeros(2)],
... )
True
>>> objects_are_allclose(
... [torch.ones(2, 3), torch.ones(2)],
... [torch.ones(2, 3), torch.zeros(2)],
... )
False
>>> objects_are_allclose(
... [torch.ones(2, 3) + 1e-7, torch.ones(2)],
... [torch.ones(2, 3), torch.ones(2) - 1e-7],
... rtol=0,
... atol=1e-8,
... )
False
coola.equality.objects_are_equal ¶
objects_are_equal(
actual: object,
expected: object,
*,
equal_nan: bool = False,
show_difference: bool = False,
max_depth: int = 1000,
registry: EqualityTesterRegistry | None = None
) -> bool
Indicate if two objects are equal or not.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
actual
|
object
|
The actual input. |
required |
expected
|
object
|
The expected input. |
required |
equal_nan
|
bool
|
If |
False
|
show_difference
|
bool
|
If |
False
|
max_depth
|
int
|
Maximum recursion depth for nested comparisons. Must be positive. Defaults to 1000. |
1000
|
registry
|
EqualityTesterRegistry | None
|
The registry with the equality tester to use. |
None
|
Returns:
| Type | Description |
|---|---|
bool
|
|
Raises:
| Type | Description |
|---|---|
RecursionError
|
if recursion depth exceeds |
Example
>>> import torch
>>> from coola.equality import objects_are_equal
>>> objects_are_equal(
... [torch.ones(2, 3), torch.zeros(2)],
... [torch.ones(2, 3), torch.zeros(2)],
... )
True
>>> objects_are_equal([torch.ones(2, 3), torch.ones(2)], [torch.ones(2, 3), torch.zeros(2)])
False
coola.equality.config ¶
Define the equality configuration.
coola.equality.config.EqualityConfig
dataclass
¶
Define the config to control the comparison rules.
Note
This class is not thread-safe. Each comparison should create its own config instance. Do not share config instances between threads as the internal depth counter is not protected by locks.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
registry
|
EqualityTesterRegistry
|
The registry with the equality tester to use. |
create_default_registry()
|
equal_nan
|
bool
|
If |
False
|
atol
|
float
|
The absolute tolerance parameter for floating-point comparisons. Must be non-negative. Defaults to 0.0. |
0.0
|
rtol
|
float
|
The relative tolerance parameter for floating-point comparisons. Must be non-negative. Defaults to 0.0. |
0.0
|
show_difference
|
bool
|
If |
False
|
max_depth
|
int
|
Maximum recursion depth for nested object comparisons. Must be positive. Defaults to 1000. Set to a lower value to protect against stack overflow with extremely deeply nested structures. |
1000
|
Raises:
| Type | Description |
|---|---|
ValueError
|
if |
Example
>>> from coola.equality.config import EqualityConfig
>>> config = EqualityConfig()
>>> config
EqualityConfig(registry=EqualityTesterRegistry(...), equal_nan=False, atol=0.0, rtol=0.0, show_difference=False, max_depth=1000)
coola.equality.config.EqualityConfig.__post_init__ ¶
__post_init__() -> None
Validate configuration parameters after initialization.
coola.equality.config.EqualityConfig.decrement_depth ¶
decrement_depth() -> None
Increment the current depth counter.
coola.equality.config.EqualityConfig.increment_depth ¶
increment_depth() -> None
Increment the current depth counter.
coola.equality.handler ¶
Contain handlers to help check if two objects are equal or not.
The handlers are designed to work with the Chain of Responsibility pattern.
coola.equality.handler.BaseEqualityHandler ¶
Bases: ABC
Define the base class to implement an equality handler.
A child class needs to implement the following methods:
equalhandle
A terminal handler has its next handler set to None.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
next_handler
|
BaseEqualityHandler | None
|
The next handler. |
None
|
Example
>>> from coola.equality.config import EqualityConfig
>>> from coola.equality.handler import SameObjectHandler, FalseHandler
>>> config = EqualityConfig()
>>> handler = SameObjectHandler()
>>> handler.set_next_handler(FalseHandler())
>>> handler.handle("abc", "abc", config)
True
>>> handler.handle("abc", "ABC", config)
False
coola.equality.handler.BaseEqualityHandler.next_handler
property
¶
next_handler: BaseEqualityHandler | None
The next handler.
coola.equality.handler.BaseEqualityHandler.chain ¶
chain(handler: T) -> T
Chain a handler to the current handler.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
handler
|
T
|
The handler to chain. |
required |
Returns:
| Type | Description |
|---|---|
T
|
The input handler. |
Example
>>> from coola.equality.config import EqualityConfig
>>> from coola.equality.handler import (
... SameObjectHandler,
... SameTypeHandler,
... ObjectEqualHandler,
... )
>>> config = EqualityConfig()
>>> handler = SameObjectHandler()
>>> handler.chain(SameTypeHandler()).chain(ObjectEqualHandler())
>>> handler.handle([1, 2, 3], [1, 2, 3], config)
True
coola.equality.handler.BaseEqualityHandler.chain_all ¶
chain_all(
*handlers: BaseEqualityHandler,
) -> BaseEqualityHandler
Chain multiple handlers in sequence.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
*handlers
|
BaseEqualityHandler
|
Variable number of handlers to chain. |
()
|
Returns:
| Type | Description |
|---|---|
BaseEqualityHandler
|
The last handler in the chain. |
Example
>>> from coola.equality.handler import (
... SameObjectHandler,
... SameTypeHandler,
... SameLengthHandler,
... ObjectEqualHandler,
... )
>>> handler = SameObjectHandler()
>>> handler.chain_all(SameTypeHandler(), SameLengthHandler(), ObjectEqualHandler())
coola.equality.handler.BaseEqualityHandler.equal
abstractmethod
¶
equal(other: object) -> bool
Indicate if two objects are equal or not.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
other
|
object
|
The other object. |
required |
Returns:
| Type | Description |
|---|---|
bool
|
|
Example
>>> from coola.equality.handler import SameObjectHandler, TrueHandler
>>> handler1 = SameObjectHandler()
>>> handler2 = SameObjectHandler()
>>> handler3 = TrueHandler()
>>> handler1.equal(handler2)
True
>>> handler1.equal(handler3)
False
coola.equality.handler.BaseEqualityHandler.get_chain_length ¶
get_chain_length() -> int
Get the total number of handlers in the chain.
Returns:
| Type | Description |
|---|---|
int
|
The total number of handlers in the chain. |
Example
>>> from coola.equality.handler import (
... SameObjectHandler,
... SameTypeHandler,
... SameLengthHandler,
... ObjectEqualHandler,
... )
>>> handler = SameObjectHandler()
>>> handler.chain_all(SameTypeHandler(), SameLengthHandler(), ObjectEqualHandler())
>>> handler.get_chain_length()
4
coola.equality.handler.BaseEqualityHandler.handle
abstractmethod
¶
handle(
actual: object, expected: object, config: EqualityConfig
) -> bool
Return the equality result between the two input objects.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
actual
|
object
|
The actual input. |
required |
expected
|
object
|
The expected input. |
required |
config
|
EqualityConfig
|
The equality configuration. |
required |
Returns:
| Type | Description |
|---|---|
bool
|
|
Example
>>> from coola.equality.config import EqualityConfig
>>> from coola.equality.handler import SameObjectHandler
>>> config = EqualityConfig()
>>> handler = SameObjectHandler()
>>> handler.handle("abc", "abc", config)
True
coola.equality.handler.BaseEqualityHandler.set_next_handler ¶
set_next_handler(
handler: BaseEqualityHandler | None,
) -> None
Set the next handler.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
handler
|
BaseEqualityHandler | None
|
The next handler. |
required |
Example
>>> from coola.equality.handler import SameObjectHandler, TrueHandler
>>> handler = SameObjectHandler()
>>> handler.set_next_handler(TrueHandler())
coola.equality.handler.BaseEqualityHandler.validate_chain ¶
validate_chain() -> None
Validate the current handler chain.
Raises:
| Type | Description |
|---|---|
RuntimeError
|
If the current handler chain is not valid. |
Example
>>> from coola.equality.handler import (
... SameObjectHandler,
... SameTypeHandler,
... SameLengthHandler,
... ObjectEqualHandler,
... )
>>> handler = SameObjectHandler()
>>> handler.chain_all(SameTypeHandler(), SameLengthHandler(), ObjectEqualHandler())
>>> handler.validate_chain()
coola.equality.handler.BaseEqualityHandler.visualize_chain ¶
visualize_chain() -> str
Visualize the current handler chain.
Returns:
| Type | Description |
|---|---|
str
|
A string containing the visualization of the current handler chain. |
Example
>>> from coola.equality.handler import (
... SameObjectHandler,
... SameTypeHandler,
... SameLengthHandler,
... ObjectEqualHandler,
... )
>>> handler = SameObjectHandler()
>>> handler.chain_all(SameTypeHandler(), SameLengthHandler(), ObjectEqualHandler())
>>> print(handler.visualize_chain())
(0): SameObjectHandler()
(1): SameTypeHandler()
(2): SameLengthHandler()
(3): ObjectEqualHandler()
coola.equality.handler.EqualHandler ¶
Bases: HandlerEqualityMixin, BaseEqualityHandler
Check if the two objects have the same data.
This handler returns False if the two objects are different
data, otherwise it returns True. The first object must have
a equal attribute which indicates if the two objects are
equal or not.
Example
>>> import math
>>> from coola.equality.config import EqualityConfig
>>> from coola.equality.handler import EqualHandler
>>> class MyFloat:
... def __init__(self, value: float) -> None:
... self._value = float(value)
... def equal(self, other: object) -> bool:
... if type(other) is not type(self):
... return False
... return self._value == other._value
...
>>> config = EqualityConfig()
>>> handler = EqualHandler()
>>> handler.handle(MyFloat(42), MyFloat(42), config)
True
>>> handler.handle(MyFloat(42), 42, config)
False
>>> handler.handle(MyFloat(42), float("nan"), config)
False
coola.equality.handler.EqualNanHandler ¶
Bases: HandlerEqualityMixin, BaseEqualityHandler
Check if the two objects have the same data.
This handler returns False if the two objects are different
data, otherwise it returns True. The first object must have
a equal attribute which indicates if the two objects are
equal or not.
Example
>>> import math
>>> from coola.equality.config import EqualityConfig
>>> from coola.equality.handler import EqualNanHandler
>>> class MyFloat:
... def __init__(self, value: float) -> None:
... self._value = float(value)
... def equal(self, other: object, equal_nan: bool = False) -> bool:
... if type(other) is not type(self):
... return False
... if equal_nan and math.isnan(self._value) and math.isnan(other._value):
... return True
... return self._value == other._value
...
>>> config = EqualityConfig()
>>> handler = EqualNanHandler()
>>> handler.handle(MyFloat(42), MyFloat(42), config)
True
>>> handler.handle(MyFloat(42), 42, config)
False
>>> handler.handle(MyFloat(float("nan")), MyFloat(float("nan")), config)
False
>>> config.equal_nan = True
>>> handler.handle(MyFloat(float("nan")), MyFloat(float("nan")), config)
True
coola.equality.handler.FalseHandler ¶
Bases: HandlerEqualityMixin, BaseEqualityHandler
Implement a handler that always returns False.
This handler is designed to be used at the end of the chain of responsibility. This handler does not call the next handler.
Example
>>> from coola.equality.config import EqualityConfig
>>> from coola.equality.handler import FalseHandler
>>> config = EqualityConfig()
>>> handler = FalseHandler()
>>> handler.handle("abc", "abc", config)
False
>>> handler.handle("abc", "ABC", config)
False
coola.equality.handler.HandlerEqualityMixin ¶
Mixin providing a standard implementation of the equal() method.
This mixin eliminates code duplication across handlers that only need to compare their type and next_handler. Handlers using this mixin must inherit from BaseEqualityHandler to ensure the next_handler attribute is available.
Design Note
This mixin must be used with classes that inherit from
BaseEqualityHandler. The type annotation self: BaseEqualityHandler
on the equal() method enforces this constraint and enables
type-safe access to the next_handler attribute.
Example
>>> from coola.equality.handler import BaseEqualityHandler, HandlerEqualityMixin
>>> class MyHandler(HandlerEqualityMixin, BaseEqualityHandler):
... def handle(self, actual, expected, config):
... return True
...
>>> handler1 = MyHandler()
>>> handler2 = MyHandler()
>>> handler1.equal(handler2)
True
coola.equality.handler.HandlerEqualityMixin.equal ¶
equal(other: object) -> bool
Indicate if two handlers are equal.
Two handlers are equal if they are of the same type and have equal next_handler chains.
Note
The type annotation self: BaseEqualityHandler ensures this
mixin is only used with BaseEqualityHandler subclasses, enabling
type-safe access to next_handler.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
other
|
object
|
The other object to compare with. |
required |
Returns:
| Type | Description |
|---|---|
bool
|
|
coola.equality.handler.JaxArrayEqualHandler ¶
Bases: HandlerEqualityMixin, BaseEqualityHandler
Check if the two JAX arrays are equal.
This handler returns True if the two arrays are equal,
otherwise False. This handler is designed to be used at
the end of the chain of responsibility. This handler does
not call the next handler.
Example
>>> import jax.numpy as jnp
>>> from coola.equality.config import EqualityConfig
>>> from coola.equality.handler import JaxArrayEqualHandler
>>> config = EqualityConfig()
>>> handler = JaxArrayEqualHandler()
>>> handler.handle(jnp.ones((2, 3)), jnp.ones((2, 3)), config)
True
>>> handler.handle(jnp.ones((2, 3)), jnp.zeros((2, 3)), config)
False
coola.equality.handler.MappingSameKeysHandler ¶
Bases: HandlerEqualityMixin, BaseEqualityHandler
Check if the two objects have the same keys.
This handler returns False if the two objects have different
keys, otherwise it passes the inputs to the next handler.
Example
>>> from coola.equality.config import EqualityConfig
>>> from coola.equality.handler import MappingSameKeysHandler
>>> config = EqualityConfig()
>>> handler = MappingSameKeysHandler()
>>> handler.handle({"a": 1, "b": 2}, {"a": 1, "b": 2, "c": 1}, config)
False
coola.equality.handler.MappingSameValuesHandler ¶
Bases: HandlerEqualityMixin, BaseEqualityHandler
Check if the key-value pairs in the first mapping are in the second mapping.
This handler returns False if the one of the key-value pair in
the first mapping is not in the second mapping, otherwise it
passes the inputs to the next handler.
Notes
This handler assumes that all the keys in the first mapping are
also in the second mapping. The second mapping can have more
keys. To check if two mappings are equal, you can combine this
handler with MappingSameKeysHandler.
Example
>>> from coola.equality.config import EqualityConfig
>>> from coola.equality.handler import MappingSameValuesHandler, TrueHandler
>>> config = EqualityConfig()
>>> handler = MappingSameValuesHandler(next_handler=TrueHandler())
>>> handler.handle({"a": 1, "b": 2}, {"a": 1, "b": 2}, config)
True
>>> handler.handle({"a": 1, "b": 2}, {"a": 1, "b": 3}, config)
False
coola.equality.handler.NanEqualHandler ¶
Bases: HandlerEqualityMixin, BaseEqualityHandler
Check if the two NaNs are equal.
This handler returns True if the two numbers are NaNs,
otherwise it passes the inputs to the next handler.
Example
>>> from coola.equality.config import EqualityConfig
>>> from coola.equality.handler import NanEqualHandler, FalseHandler
>>> config = EqualityConfig()
>>> handler = NanEqualHandler(next_handler=FalseHandler())
>>> handler.handle(float("nan"), float("nan"), config)
False
>>> config.equal_nan = True
>>> handler.handle(float("nan"), float("nan"), config)
True
coola.equality.handler.NumpyArrayEqualHandler ¶
Bases: HandlerEqualityMixin, BaseEqualityHandler
Check if the two NumPy arrays are equal.
This handler returns True if the two arrays are equal,
otherwise False. This handler is designed to be used at
the end of the chain of responsibility. This handler does
not call the next handler.
Example
>>> import numpy as np
>>> from coola.equality.config import EqualityConfig
>>> from coola.equality.handler import NumpyArrayEqualHandler
>>> config = EqualityConfig()
>>> handler = NumpyArrayEqualHandler()
>>> handler.handle(np.ones((2, 3)), np.ones((2, 3)), config)
True
>>> handler.handle(np.ones((2, 3)), np.zeros((2, 3)), config)
False
coola.equality.handler.ObjectEqualHandler ¶
Bases: HandlerEqualityMixin, BaseEqualityHandler
Check if the two objects are equal using the default equality
operator ==.
This handler returns True if the two objects are equal,
otherwise False. This handler is designed to be used at
the end of the chain of responsibility. This handler does
not call the next handler.
Example
>>> from coola.equality.config import EqualityConfig
>>> from coola.equality.handler import ObjectEqualHandler
>>> config = EqualityConfig()
>>> handler = ObjectEqualHandler()
>>> handler.handle(1, 1, config)
True
>>> handler.handle(1, "abc", config)
False
coola.equality.handler.PandasDataFrameEqualHandler ¶
Bases: HandlerEqualityMixin, BaseEqualityHandler
Check if the two pandas.DataFrames are equal.
This handler returns True if the two pandas.DataFrames are
equal, otherwise False. This handler is designed to be used
at the end of the chain of responsibility. This handler does
not call the next handler.
Example
>>> import pandas
>>> from coola.equality.config import EqualityConfig
>>> from coola.equality.handler import PandasDataFrameEqualHandler
>>> config = EqualityConfig()
>>> handler = PandasDataFrameEqualHandler()
>>> handler.handle(
... pandas.DataFrame({"col": [1, 2, 3]}),
... pandas.DataFrame({"col": [1, 2, 3]}),
... config,
... )
True
>>> handler.handle(
... pandas.DataFrame({"col": [1, 2, 3]}),
... pandas.DataFrame({"col": [1, 2, 4]}),
... config,
... )
False
coola.equality.handler.PandasSeriesEqualHandler ¶
Bases: HandlerEqualityMixin, BaseEqualityHandler
Check if the two pandas.Serieses are equal.
This handler returns True if the two pandas.Serieses are
equal, otherwise False. This handler is designed to be used
at the end of the chain of responsibility. This handler does
not call the next handler.
Example
>>> import pandas
>>> from coola.equality.config import EqualityConfig
>>> from coola.equality.handler import PandasSeriesEqualHandler
>>> config = EqualityConfig()
>>> handler = PandasSeriesEqualHandler()
>>> handler.handle(pandas.Series([1, 2, 3]), pandas.Series([1, 2, 3]), config)
True
>>> handler.handle(pandas.Series([1, 2, 3]), pandas.Series([1, 2, 4]), config)
False
coola.equality.handler.PolarsDataFrameEqualHandler ¶
Bases: HandlerEqualityMixin, BaseEqualityHandler
Check if the two polars.DataFrames are equal.
This handler returns True if the two polars.DataFrames are
equal, otherwise False. This handler is designed to be used
at the end of the chain of responsibility. This handler does
not call the next handler.
Example
>>> import polars as pl
>>> from coola.equality.config import EqualityConfig
>>> from coola.equality.handler import PolarsDataFrameEqualHandler
>>> config = EqualityConfig()
>>> handler = PolarsDataFrameEqualHandler()
>>> handler.handle(
... pl.DataFrame({"col": [1, 2, 3]}),
... pl.DataFrame({"col": [1, 2, 3]}),
... config,
... )
True
>>> handler.handle(
... pl.DataFrame({"col": [1, 2, 3]}),
... pl.DataFrame({"col": [1, 2, 4]}),
... config,
... )
False
coola.equality.handler.PolarsLazyFrameEqualHandler ¶
Bases: HandlerEqualityMixin, BaseEqualityHandler
Check if the two polars.LazyFrames are equal.
This handler returns True if the two polars.LazyFrames are
equal, otherwise False. This handler is designed to be used
at the end of the chain of responsibility. This handler does
not call the next handler.
Example
>>> import polars as pl
>>> from coola.equality.config import EqualityConfig
>>> from coola.equality.handler import PolarsLazyFrameEqualHandler
>>> config = EqualityConfig()
>>> handler = PolarsLazyFrameEqualHandler()
>>> handler.handle(
... pl.LazyFrame({"col": [1, 2, 3]}),
... pl.LazyFrame({"col": [1, 2, 3]}),
... config,
... )
True
>>> handler.handle(
... pl.LazyFrame({"col": [1, 2, 3]}),
... pl.LazyFrame({"col": [1, 2, 4]}),
... config,
... )
False
coola.equality.handler.PolarsSeriesEqualHandler ¶
Bases: HandlerEqualityMixin, BaseEqualityHandler
Check if the two polars.Serieses are equal.
This handler returns True if the two polars.Serieses are
equal, otherwise False. This handler is designed to be used
at the end of the chain of responsibility. This handler does
not call the next handler.
Example
>>> import polars as pl
>>> from coola.equality.config import EqualityConfig
>>> from coola.equality.handler import PolarsSeriesEqualHandler
>>> config = EqualityConfig()
>>> handler = PolarsSeriesEqualHandler()
>>> handler.handle(pl.Series([1, 2, 3]), pl.Series([1, 2, 3]), config)
True
>>> handler.handle(pl.Series([1, 2, 3]), pl.Series([1, 2, 4]), config)
False
coola.equality.handler.PyarrowEqualHandler ¶
Bases: HandlerEqualityMixin, BaseEqualityHandler
Check if the two pyarrow arrays or tables are equal.
This handler returns True if the two arrays or tables are
equal, otherwise False. This handler is designed to be used at
the end of the chain of responsibility. This handler does
not call the next handler.
Note that config.equal_nan, config.atol and config.rtol
arguments are ignored.
Example
>>> import pyarrow
>>> from coola.equality.config import EqualityConfig
>>> from coola.equality.handler import PyarrowEqualHandler
>>> config = EqualityConfig()
>>> handler = PyarrowEqualHandler()
>>> handler.handle(pyarrow.array([1, 2, 3]), pyarrow.array([1, 2, 3]), config)
True
>>> handler.handle(pyarrow.array([1, 2, 3]), pyarrow.array([1, 2, 4]), config)
False
coola.equality.handler.SameAttributeHandler ¶
Bases: BaseEqualityHandler
Check if the two objects have the same attribute.
This handler returns False if the two objects have different
attributes, otherwise it passes the inputs to the next handler.
The objects must have the attribute.
Example
>>> import numpy as np
>>> from coola.equality.config import EqualityConfig
>>> from coola.equality.handler import SameAttributeHandler, TrueHandler
>>> config = EqualityConfig()
>>> handler = SameAttributeHandler(name="shape", next_handler=TrueHandler())
>>> handler.handle(np.ones((2, 3)), np.ones((2, 3)), config)
True
>>> handler.handle(np.ones((2, 3)), np.ones((3, 2)), config)
False
coola.equality.handler.SameDTypeHandler ¶
Bases: HandlerEqualityMixin, BaseEqualityHandler
Check if the two objects have the same data type.
This handler returns False if the two objects have different
data types, otherwise it passes the inputs to the next handler.
The objects must have a dtype attribute (e.g. object.dtype)
which returns the data type of the object. This handler works on
numpy.ndarrays and torch.Tensors objects.
Example
>>> import numpy as np
>>> from coola.equality.config import EqualityConfig
>>> from coola.equality.handler import SameDTypeHandler, TrueHandler
>>> config = EqualityConfig()
>>> handler = SameDTypeHandler(next_handler=TrueHandler())
>>> handler.handle(np.ones((2, 3)), np.ones((2, 3)), config)
True
>>> handler.handle(np.ones((2, 3), dtype=float), np.ones((2, 3), dtype=int), config)
False
coola.equality.handler.SameDataHandler ¶
Bases: HandlerEqualityMixin, BaseEqualityHandler
Check if the two objects have the same data.
This handler returns False if the two objects have different
data, otherwise it passes the inputs to the next handler.
The objects must have a data attribute (e.g. object.data)
which returns the data of the object.
Example
>>> import numpy as np
>>> from coola.equality.config import EqualityConfig
>>> from coola.equality.handler import SameDataHandler, TrueHandler
>>> config = EqualityConfig()
>>> handler = SameDataHandler(next_handler=TrueHandler())
>>> handler.handle(np.ones((2, 3)), np.ones((2, 3)), config)
True
>>> handler.handle(np.ones((2, 3)), np.zeros((2, 3)), config)
False
coola.equality.handler.SameLengthHandler ¶
Bases: HandlerEqualityMixin, BaseEqualityHandler
Check if the two objects have the same length.
This handler returns False if the two objects have different
lengths, otherwise it passes the inputs to the next handler.
Example
>>> from coola.equality.config import EqualityConfig
>>> from coola.equality.handler import SameLengthHandler
>>> config = EqualityConfig()
>>> handler = SameLengthHandler()
>>> handler.handle([1, 2, 3], [1, 2, 3, 4], config)
False
coola.equality.handler.SameObjectHandler ¶
Bases: HandlerEqualityMixin, BaseEqualityHandler
Check if the two objects refer to the same object.
This handler returns True if the two objects refer to the
same object, otherwise it passes the inputs to the next handler.
Example
>>> from coola.equality.config import EqualityConfig
>>> from coola.equality.handler import SameObjectHandler
>>> config = EqualityConfig()
>>> handler = SameObjectHandler()
>>> handler.handle("abc", "abc", config)
True
coola.equality.handler.SameShapeHandler ¶
Bases: HandlerEqualityMixin, BaseEqualityHandler
Check if the two objects have the same shape.
This handler returns False if the two objects have different
shapes, otherwise it passes the inputs to the next handler.
The objects must have a shape attribute (e.g. object.shape)
which returns the shape of the object. This handler works on
jax.numpy.ndarrays, numpy.ndarrays, pandas.DataFrame,
polars.DataFrame and torch.Tensors objects.
Example
>>> import numpy as np
>>> from coola.equality.config import EqualityConfig
>>> from coola.equality.handler import SameShapeHandler, TrueHandler
>>> config = EqualityConfig()
>>> handler = SameShapeHandler(next_handler=TrueHandler())
>>> handler.handle(np.ones((2, 3)), np.ones((2, 3)), config)
True
>>> handler.handle(np.ones((2, 3)), np.ones((3, 2)), config)
False
coola.equality.handler.SameTypeHandler ¶
Bases: HandlerEqualityMixin, BaseEqualityHandler
Check if the two objects have the same type.
This handler returns False if the two objects have different
types, otherwise it passes the inputs to the next handler.
Example
>>> from coola.equality.config import EqualityConfig
>>> from coola.equality.handler import SameTypeHandler
>>> config = EqualityConfig()
>>> handler = SameTypeHandler()
>>> handler.handle(1, "abc", config)
False
coola.equality.handler.ScalarEqualHandler ¶
Bases: HandlerEqualityMixin, BaseEqualityHandler
Check if the two numbers are equal or not.
This handler returns False if the two numbers are
different, otherwise it returns True. It is possible to
control the tolerance by using atol and rtol.
By default, the tolerances are set to 0.
Example
>>> from coola.equality.config import EqualityConfig
>>> from coola.equality.handler import ScalarEqualHandler
>>> config = EqualityConfig()
>>> handler = ScalarEqualHandler()
>>> handler.handle(42.0, 42.0, config)
True
>>> config.atol = 1e-3
>>> handler.handle(42.0, 42.0001, config)
True
>>> handler.handle(float("nan"), float("nan"), config)
False
coola.equality.handler.SequenceSameValuesHandler ¶
Bases: HandlerEqualityMixin, BaseEqualityHandler
Check if the two sequences have the same values.
This handler returns False if the two sequences have at least
one different value, otherwise it passes the inputs to the next
handler. If the sequences have different length, this handler
checks only the values of the shortest sequence.
Example
>>> from coola.equality.config import EqualityConfig
>>> from coola.equality.handler import SequenceSameValuesHandler, TrueHandler
>>> config = EqualityConfig()
>>> handler = SequenceSameValuesHandler(next_handler=TrueHandler())
>>> handler.handle([1, 2, 3], [1, 2, 3], config)
True
>>> handler.handle([1, 2, 3], [1, 2, 4], config)
False
coola.equality.handler.TorchTensorEqualHandler ¶
Bases: HandlerEqualityMixin, BaseEqualityHandler
Check if the two tensors are equal.
This handler returns True if the two tensors are equal,
otherwise False. This handler is designed to be used at
the end of the chain of responsibility. This handler does
not call the next handler.
Example
>>> import torch
>>> from coola.equality.config import EqualityConfig
>>> from coola.equality.handler import TorchTensorEqualHandler
>>> config = EqualityConfig()
>>> handler = TorchTensorEqualHandler()
>>> handler.handle(torch.ones(2, 3), torch.ones(2, 3), config)
True
>>> handler.handle(torch.ones(2, 3), torch.zeros(2, 3), config)
False
coola.equality.handler.TorchTensorSameDeviceHandler ¶
Bases: HandlerEqualityMixin, BaseEqualityHandler
Check if the two tensors have the same device.
This handler returns False if the two objects have different
devices, otherwise it passes the inputs to the next handler.
Example
>>> import torch
>>> from coola.equality.config import EqualityConfig
>>> from coola.equality.handler import TrueHandler, TorchTensorSameDeviceHandler
>>> config = EqualityConfig()
>>> handler = TorchTensorSameDeviceHandler(next_handler=TrueHandler())
>>> handler.handle(torch.ones(2, 3), torch.ones(3, 2), config)
True
coola.equality.handler.TrueHandler ¶
Bases: HandlerEqualityMixin, BaseEqualityHandler
Implement a handler that always returns True.
This handler is designed to be used at the end of the chain of responsibility. This handler does not call the next handler.
Example
>>> from coola.equality.config import EqualityConfig
>>> from coola.equality.handler import TrueHandler
>>> config = EqualityConfig()
>>> handler = TrueHandler()
>>> handler.handle("abc", "abc", config)
True
>>> handler.handle("abc", "ABC", config)
True
coola.equality.handler.check_recursion_depth ¶
check_recursion_depth(
config: EqualityConfig,
) -> Generator[None, None, None]
Context manager to track and enforce recursion depth limits.
This context manager increments the recursion depth counter on entry and decrements it on exit (even if an exception occurs). It raises a RecursionError if the maximum depth is exceeded.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
config
|
EqualityConfig
|
The equality configuration containing depth settings. |
required |
Raises:
| Type | Description |
|---|---|
RecursionError
|
if the current depth exceeds max_depth. |
Example
>>> from coola.equality.config import EqualityConfig
>>> from coola.equality.handler import check_recursion_depth
>>> config = EqualityConfig(max_depth=5)
>>> with check_recursion_depth(config):
... print(config._current_depth)
...
1
coola.equality.handler.create_chain ¶
create_chain(
*handlers: BaseEqualityHandler,
) -> BaseEqualityHandler
Create a chain of handlers and return the first handler.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
handlers
|
BaseEqualityHandler
|
Handlers to chain. |
()
|
Returns:
| Type | Description |
|---|---|
BaseEqualityHandler
|
The first handler of the chain. |
Example
>>> from coola.equality.handler import (
... create_chain,
... SameObjectHandler,
... SameTypeHandler,
... ObjectEqualHandler,
... )
>>> handler = create_chain(SameObjectHandler(), SameTypeHandler(), ObjectEqualHandler())
>>> print(handler.visualize_chain())
(0): SameObjectHandler()
(1): SameTypeHandler()
(2): ObjectEqualHandler()
coola.equality.handler.handlers_are_equal ¶
handlers_are_equal(
handler1: BaseEqualityHandler | None,
handler2: BaseEqualityHandler | None,
) -> bool
Indicate whether two handlers are equal.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
handler1
|
BaseEqualityHandler | None
|
The first handler. |
required |
handler2
|
BaseEqualityHandler | None
|
The second handler. |
required |
Returns:
| Type | Description |
|---|---|
bool
|
|
Example
>>> from coola.equality.handler import SameObjectHandler, FalseHandler, handlers_are_equal
>>> handlers_are_equal(SameObjectHandler(), SameObjectHandler())
True
>>> handlers_are_equal(SameObjectHandler(), FalseHandler())
False
>>> handlers_are_equal(None, SameObjectHandler())
False
>>> handlers_are_equal(SameObjectHandler(), None)
False
>>> handlers_are_equal(None, None)
True
coola.equality.tester ¶
Contain the equality testers to check if two objects are equal or not.
This module provides a comprehensive system for comparing objects of different types using a registry-based approach with specialized equality testers. The testers use the chain of responsibility pattern with handlers to perform various equality checks.
Key components
- BaseEqualityTester: Abstract base class for all equality testers
- EqualityTesterRegistry: Registry that dispatches to appropriate testers by type
- Specialized testers for Python built-ins (list, dict, int, float, etc.)
- Testers for third-party libraries (NumPy, PyTorch, Pandas, Polars, JAX, xarray, PyArrow)
The default registry is pre-configured with testers for common types and can be extended with custom testers using register_equality_testers().
Example
>>> from coola.equality.tester import get_default_registry
>>> from coola.equality.config import EqualityConfig
>>> registry = get_default_registry()
>>> config = EqualityConfig()
>>> # Compare lists with nested structures
>>> registry.objects_are_equal([1, {"a": 2}], [1, {"a": 2}], config)
True
coola.equality.tester.BaseEqualityTester ¶
Bases: ABC, Generic[T]
Define the base class to implement an equality operator.
This abstract base class defines the interface for all equality testers in coola. Equality testers are responsible for comparing objects of a specific type using a chain of handlers that implement the chain of responsibility pattern.
The generic type parameter T indicates the primary type this tester is designed to handle, though the actual implementation may handle related types as well.
Subclasses must implement
equal(): Check if another tester is of the same typeobjects_are_equal(): Check if two objects are equal using handler chain
Example
>>> from coola.equality.config import EqualityConfig
>>> from coola.equality.tester import DefaultEqualityTester
>>> config = EqualityConfig()
>>> tester = DefaultEqualityTester()
>>> tester.objects_are_equal(42, 42, config)
True
>>> tester.objects_are_equal("meow", "meov", config)
False
coola.equality.tester.BaseEqualityTester.equal
abstractmethod
¶
equal(other: object) -> bool
Indicate if two equality testers are equal (same type).
This method checks if another object is an equality tester of the same type as this one. It's used for comparing equality tester instances themselves, not the objects they test.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
other
|
object
|
The other object to compare against. |
required |
Returns:
| Type | Description |
|---|---|
bool
|
|
bool
|
otherwise |
Example
>>> from coola.equality.tester import DefaultEqualityTester, MappingEqualityTester
>>> tester1 = DefaultEqualityTester()
>>> tester2 = DefaultEqualityTester()
>>> tester3 = MappingEqualityTester()
>>> tester1.equal(tester2)
True
>>> tester1.equal(tester3)
False
coola.equality.tester.BaseEqualityTester.objects_are_equal
abstractmethod
¶
objects_are_equal(
actual: T, expected: object, config: EqualityConfig
) -> bool
Indicate if two objects are equal or not.
This method delegates equality checking to a chain of handlers that implement various checks (e.g., same object, same type, same values). The handler chain is typically set up in the tester's init method.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
actual
|
T
|
The actual object to compare. |
required |
expected
|
object
|
The expected object to compare against. |
required |
config
|
EqualityConfig
|
The equality configuration controlling comparison behavior (e.g., tolerance for floating point, whether to treat NaN as equal). |
required |
Returns:
| Type | Description |
|---|---|
bool
|
|
bool
|
logic and the provided configuration, otherwise |
Example
>>> from coola.equality.config import EqualityConfig
>>> from coola.equality.tester import DefaultEqualityTester
>>> config = EqualityConfig()
>>> tester = DefaultEqualityTester()
>>> tester.objects_are_equal(42, 42, config)
True
>>> tester.objects_are_equal("meow", "meov", config)
False
coola.equality.tester.DefaultEqualityTester ¶
Bases: BaseEqualityTester[object]
Implement a default equality tester.
This tester serves as the fallback for types without specialized equality
testers. It uses Python's built-in == operator to test equality between
objects. The tester uses a handler chain to perform checks in order:
1. SameObjectHandler: Check if objects are the same instance (identity)
2. SameTypeHandler: Check if objects have the same type
3. ObjectEqualHandler: Use == operator for equality comparison
This tester is registered for the object type in the default registry,
making it the catch-all for unregistered types via Python's MRO.
Example
Basic usage with primitives:
>>> from coola.equality.config import EqualityConfig
>>> from coola.equality.tester import DefaultEqualityTester
>>> config = EqualityConfig()
>>> tester = DefaultEqualityTester()
>>> tester.objects_are_equal(42, 42, config=config)
True
>>> tester.objects_are_equal("meow", "meov", config)
False
Different types are not equal:
>>> from coola.equality.config import EqualityConfig
>>> from coola.equality.tester import DefaultEqualityTester
>>> config = EqualityConfig()
>>> tester = DefaultEqualityTester()
>>> tester.objects_are_equal(42, "42", config)
False
coola.equality.tester.EqualEqualityTester ¶
Bases: BaseEqualityTester[object]
Implement an equality tester for objects with equal method.
This tester is designed for objects that implement an equal(other) method
for equality comparison. It uses a handler chain that checks:
1. SameObjectHandler: Check for object identity
2. SameTypeHandler: Verify same type
3. EqualHandler: Call the object's equal() method
This tester is used for comparing BaseEqualityTester instances themselves in the default registry.
Example
Custom class with equal method:
>>> from coola.equality.config import EqualityConfig
>>> from coola.equality.tester import EqualEqualityTester
>>> class MyFloat:
... def __init__(self, value: float) -> None:
... self._value = float(value)
... def equal(self, other: object) -> bool:
... if type(other) is not type(self):
... return False
... return self._value == other._value
...
>>> config = EqualityConfig()
>>> tester = EqualEqualityTester()
>>> tester.objects_are_equal(MyFloat(42), MyFloat(42), config=config)
True
>>> tester.objects_are_equal(MyFloat(42), MyFloat(1), config=config)
False
coola.equality.tester.EqualNanEqualityTester ¶
Bases: BaseEqualityTester[object]
Implement an equality tester for objects with NaN-aware equal method.
This tester is designed for objects that implement an equal(other, equal_nan)
method that supports NaN equality. When config.equal_nan is True, NaN values
are considered equal to each other. The handler chain:
1. SameObjectHandler: Check for object identity
2. SameTypeHandler: Verify same type
3. EqualNanHandler: Call object's equal() with equal_nan parameter
Example
Custom class with NaN-aware equal method:
>>> import math
>>> from coola.equality.config import EqualityConfig
>>> from coola.equality.tester import EqualNanEqualityTester
>>> class MyFloat:
... def __init__(self, value: float) -> None:
... self._value = float(value)
... def equal(self, other: object, equal_nan: bool = False) -> bool:
... if type(other) is not type(self):
... return False
... if equal_nan and math.isnan(self._value) and math.isnan(other._value):
... return True
... return self._value == other._value
...
>>> config = EqualityConfig()
>>> tester = EqualNanEqualityTester()
>>> tester.objects_are_equal(MyFloat(42), MyFloat(42), config=config)
True
>>> tester.objects_are_equal(MyFloat(float("nan")), MyFloat(float("nan")), config=config)
False
>>> config.equal_nan = True
>>> tester.objects_are_equal(MyFloat(float("nan")), MyFloat(float("nan")), config=config)
True
coola.equality.tester.EqualityTesterRegistry ¶
Registry that manages and dispatches equality testers based on data type.
This registry maintains a mapping from Python types to equality tester instances and uses the Method Resolution Order (MRO) for type lookup. When checking equality, it automatically selects the most specific registered equality tester for the data's type, falling back to parent types or a default tester if needed.
The registry includes an LRU cache for type lookups to optimize performance in applications that repeatedly check equality of similar data structures.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
initial_state
|
dict[type, BaseEqualityTester[Any]] | None
|
Optional initial mapping of types to equality testers. If provided, the state is copied to prevent external mutations. |
None
|
Attributes:
| Name | Type | Description |
|---|---|---|
_state |
TypeRegistry[BaseEqualityTester]
|
Internal mapping of registered types to equality testers |
Example
Basic usage:
>>> from coola.equality.tester import (
... EqualityTesterRegistry,
... SequenceEqualityTester,
... DefaultEqualityTester,
... )
>>> from coola.equality.config import EqualityConfig
>>> registry = EqualityTesterRegistry(
... {object: DefaultEqualityTester(), list: SequenceEqualityTester()}
... )
>>> registry
EqualityTesterRegistry(
(state): TypeRegistry(
(<class 'object'>): DefaultEqualityTester()
(<class 'list'>): SequenceEqualityTester()
)
)
>>> config = EqualityConfig()
>>> registry.objects_are_equal([1, 2, 3], [1, 2, 3], config=config)
True
coola.equality.tester.EqualityTesterRegistry.find_equality_tester ¶
find_equality_tester(
data_type: type,
) -> BaseEqualityTester[Any]
Find the appropriate equality tester for a given type.
Uses the Method Resolution Order (MRO) to find the most specific registered equality tester. For example, if you register a tester for Sequence but not for list, lists will use the Sequence tester.
Results are cached using an LRU cache (256 entries) for performance, as tester lookup is a hot path in recursive equality checking.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data_type
|
type
|
The Python type to find an equality tester for |
required |
Returns:
| Type | Description |
|---|---|
BaseEqualityTester[Any]
|
The most specific registered equality tester for this type, a parent |
BaseEqualityTester[Any]
|
type's tester via MRO, or the default tester |
Example
>>> from collections.abc import Sequence
>>> from coola.equality.tester import (
... EqualityTesterRegistry,
... SequenceEqualityTester,
... DefaultEqualityTester,
... )
>>> registry = EqualityTesterRegistry({object: DefaultEqualityTester()})
>>> registry.register(Sequence, SequenceEqualityTester())
>>> # list does not inherit from Sequence, so it uses DefaultEqualityTester
>>> tester = registry.find_equality_tester(list)
>>> tester
DefaultEqualityTester()
coola.equality.tester.EqualityTesterRegistry.has_equality_tester ¶
has_equality_tester(data_type: type) -> bool
Check if an equality tester is explicitly registered for the given type.
Note that this only checks for direct registration. Even if this returns False, find_equality_tester() may still return a tester via MRO lookup or the default tester.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data_type
|
type
|
The type to check |
required |
Returns:
| Type | Description |
|---|---|
bool
|
True if an equality tester is explicitly registered for this type, |
bool
|
False otherwise |
Example
>>> from coola.equality.tester import EqualityTesterRegistry, SequenceEqualityTester
>>> registry = EqualityTesterRegistry()
>>> registry.register(list, SequenceEqualityTester())
>>> registry.has_equality_tester(list)
True
>>> registry.has_equality_tester(tuple)
False
coola.equality.tester.EqualityTesterRegistry.objects_are_equal ¶
objects_are_equal(
actual: object, expected: object, config: EqualityConfig
) -> bool
Check if two objects are equal by recursively comparing their structure.
This is the main entry point for equality checking. It automatically: 1. Determines the actual object's type 2. Finds the appropriate equality tester 3. Delegates to that tester's objects_are_equal method 4. The tester recursively processes nested structures
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
actual
|
object
|
The actual object. |
required |
expected
|
object
|
The expected object. |
required |
config
|
EqualityConfig
|
The equality configuration. |
required |
Returns:
| Type | Description |
|---|---|
bool
|
True if the objects are equal according to the registered testers, |
bool
|
False otherwise |
Example
Checking if two lists of integers are equal:
>>> from coola.equality.config import EqualityConfig
>>> from coola.equality.tester import get_default_registry
>>> registry = get_default_registry()
>>> config = EqualityConfig()
>>> registry.objects_are_equal([1, 2, 3], [1, 2, 3], config=config)
True
Checking if two lists of tensors are equal:
>>> import torch
>>> from coola.equality.config import EqualityConfig
>>> from coola.equality.tester import get_default_registry
>>> registry = get_default_registry()
>>> config = EqualityConfig()
>>> registry.objects_are_equal(
... [torch.ones(2, 3), torch.zeros(2)],
... [torch.ones(2, 3), torch.zeros(2)],
... config=config,
... )
True
coola.equality.tester.EqualityTesterRegistry.register ¶
register(
data_type: type,
tester: BaseEqualityTester[Any],
exist_ok: bool = False,
) -> None
Register an equality tester for a given data type.
This method associates an equality tester instance with a specific Python type. When checking equality for data of this type, the registered tester will be used. The cache is automatically cleared after registration to ensure consistency.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data_type
|
type
|
The Python type to register (e.g., list, dict, custom classes) |
required |
tester
|
BaseEqualityTester[Any]
|
The equality tester instance that handles this type |
required |
exist_ok
|
bool
|
If False (default), raises an error if the type is already registered. If True, overwrites the existing registration silently. |
False
|
Raises:
| Type | Description |
|---|---|
RuntimeError
|
If the type is already registered and exist_ok is False |
Example
>>> from coola.equality.tester import EqualityTesterRegistry, SequenceEqualityTester
>>> registry = EqualityTesterRegistry()
>>> registry.register(list, SequenceEqualityTester())
>>> registry.has_equality_tester(list)
True
coola.equality.tester.EqualityTesterRegistry.register_many ¶
register_many(
mapping: Mapping[type, BaseEqualityTester[Any]],
exist_ok: bool = False,
) -> None
Register multiple equality testers at once.
This is a convenience method for bulk registration that internally calls register() for each type-tester pair.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
mapping
|
Mapping[type, BaseEqualityTester[Any]]
|
Dictionary mapping Python types to equality tester instances |
required |
exist_ok
|
bool
|
If False (default), raises an error if any type is already registered. If True, overwrites existing registrations silently. |
False
|
Raises:
| Type | Description |
|---|---|
RuntimeError
|
If any type is already registered and exist_ok is False |
Example
>>> from coola.equality.tester import (
... EqualityTesterRegistry,
... SequenceEqualityTester,
... MappingEqualityTester,
... )
>>> registry = EqualityTesterRegistry()
>>> registry.register_many(
... {
... list: SequenceEqualityTester(),
... dict: MappingEqualityTester(),
... }
... )
>>> registry
EqualityTesterRegistry(
(state): TypeRegistry(
(<class 'list'>): SequenceEqualityTester()
(<class 'dict'>): MappingEqualityTester()
)
)
coola.equality.tester.HandlerEqualityTester ¶
Bases: BaseEqualityTester[T]
Implement an equality tester that uses an equality handler.
Example
>>> from coola.equality.config import EqualityConfig
>>> from coola.equality.handler import (
... ObjectEqualHandler,
... SameObjectHandler,
... SameTypeHandler,
... create_chain,
... )
>>> from coola.equality.tester import HandlerEqualityTester
>>> config = EqualityConfig()
>>> handler = create_chain(SameObjectHandler(), SameTypeHandler(), ObjectEqualHandler())
>>> tester = HandlerEqualityTester(handler)
>>> print(tester)
HandlerEqualityTester(
(0): SameObjectHandler()
(1): SameTypeHandler()
(2): ObjectEqualHandler()
)
>>> tester.objects_are_equal(42, 42, config=config)
True
>>> tester.objects_are_equal("meow", "meov", config)
False
coola.equality.tester.JaxArrayEqualityTester ¶
Bases: BaseEqualityTester[ndarray]
Implement an equality tester for jax.numpy.ndarray.
This tester compares JAX arrays element-wise with support for NaN equality and tolerance-based comparisons. The handler chain: 1. SameObjectHandler: Check for object identity 2. SameTypeHandler: Verify both are JAX arrays 3. SameDTypeHandler: Check arrays have the same dtype 4. SameShapeHandler: Verify arrays have the same shape 5. JaxArrayEqualHandler: Element-wise comparison with tolerance support
The tester respects config.equal_nan for NaN comparisons and config.atol/rtol for floating-point tolerance.
Example
Basic array comparison:
>>> import jax.numpy as jnp
>>> from coola.equality.config import EqualityConfig
>>> from coola.equality.tester import JaxArrayEqualityTester
>>> config = EqualityConfig()
>>> tester = JaxArrayEqualityTester()
>>> tester.objects_are_equal(jnp.ones((2, 3)), jnp.ones((2, 3)), config)
True
>>> tester.objects_are_equal(jnp.ones((2, 3)), jnp.zeros((2, 3)), config)
False
coola.equality.tester.MappingEqualityTester ¶
Bases: BaseEqualityTester[Mapping[Any, Any]]
Implement a mapping equality tester.
This tester handles dictionary-like objects (dict, Mapping ABC) by recursively comparing their keys and values. The handler chain: 1. SameObjectHandler: Check for object identity 2. SameTypeHandler: Verify same type 3. SameLengthHandler: Check both mappings have same number of keys 4. MappingSameKeysHandler: Verify both have the same keys 5. MappingSameValuesHandler: Recursively compare values using registry 6. TrueHandler: Return True if all checks pass
The values are compared recursively, so nested dictionaries, lists, and other complex structures are handled correctly.
Example
Basic mapping comparison:
>>> from coola.equality.config import EqualityConfig
>>> from coola.equality.tester import MappingEqualityTester
>>> config = EqualityConfig()
>>> tester = MappingEqualityTester()
>>> tester.objects_are_equal({"a": 1, "b": 2}, {"a": 1, "b": 2}, config)
True
>>> tester.objects_are_equal({"a": 1, "b": 2}, {"a": 1, "b": 4}, config)
False
Nested mapping comparison:
>>> from coola.equality.config import EqualityConfig
>>> from coola.equality.tester import MappingEqualityTester
>>> config = EqualityConfig()
>>> tester = MappingEqualityTester()
>>> tester.objects_are_equal(
... {"a": {"x": 1}, "b": [1, 2]},
... {"a": {"x": 1}, "b": [1, 2]},
... config,
... )
True
coola.equality.tester.NumpyArrayEqualityTester ¶
Bases: BaseEqualityTester[ndarray]
Implement an equality tester for numpy.ndarray.
This tester compares NumPy arrays element-wise with support for NaN equality and tolerance-based comparisons. The handler chain: 1. SameObjectHandler: Check for object identity 2. SameTypeHandler: Verify both are numpy arrays 3. SameDTypeHandler: Check arrays have the same dtype 4. SameShapeHandler: Verify arrays have the same shape 5. NumpyArrayEqualHandler: Element-wise comparison with tolerance support
The tester respects config.equal_nan for NaN comparisons and config.atol/rtol for floating-point tolerance.
Example
Basic array comparison:
>>> import numpy as np
>>> from coola.equality.config import EqualityConfig
>>> from coola.equality.tester import NumpyArrayEqualityTester
>>> config = EqualityConfig()
>>> tester = NumpyArrayEqualityTester()
>>> tester.objects_are_equal(np.ones((2, 3)), np.ones((2, 3)), config)
True
>>> tester.objects_are_equal(np.ones((2, 3)), np.zeros((2, 3)), config)
False
NaN comparison with equal_nan:
>>> import numpy as np
>>> from coola.equality.config import EqualityConfig
>>> from coola.equality.tester import NumpyArrayEqualityTester
>>> config = EqualityConfig(equal_nan=True)
>>> tester = NumpyArrayEqualityTester()
>>> tester.objects_are_equal(
... np.array([1.0, float("nan")]),
... np.array([1.0, float("nan")]),
... config,
... )
True
coola.equality.tester.NumpyMaskedArrayEqualityTester ¶
Bases: BaseEqualityTester[MaskedArray]
Implement an equality tester for numpy.ma.MaskedArray.
This tester compares NumPy masked arrays by checking data, mask, and fill_value. The handler chain: 1. SameObjectHandler: Check for object identity 2. SameTypeHandler: Verify both are masked arrays 3. SameDTypeHandler: Check arrays have the same dtype 4. SameShapeHandler: Verify arrays have the same shape 5. SameDataHandler: Compare the underlying data arrays 6. SameAttributeHandler("mask"): Compare the mask arrays 7. SameAttributeHandler("fill_value"): Compare fill values 8. TrueHandler: Return True if all checks pass
Example
Basic masked array comparison:
>>> import numpy as np
>>> from coola.equality.config import EqualityConfig
>>> from coola.equality.tester import NumpyMaskedArrayEqualityTester
>>> config = EqualityConfig()
>>> tester = NumpyMaskedArrayEqualityTester()
>>> tester.objects_are_equal(
... np.ma.array(data=[0.0, 1.0, 1.2], mask=[0, 1, 0]),
... np.ma.array(data=[0.0, 1.0, 1.2], mask=[0, 1, 0]),
... config,
... )
True
>>> tester.objects_are_equal(
... np.ma.array(data=[0.0, 1.0, 1.2], mask=[0, 1, 0]),
... np.ma.array(data=[0.0, 1.0, 2.0], mask=[0, 1, 0]),
... config,
... )
False
Different masks are not equal:
>>> import numpy as np
>>> from coola.equality.config import EqualityConfig
>>> from coola.equality.tester import NumpyMaskedArrayEqualityTester
>>> config = EqualityConfig()
>>> tester = NumpyMaskedArrayEqualityTester()
>>> tester.objects_are_equal(
... np.ma.array(data=[0.0, 1.0, 1.2], mask=[0, 1, 0]),
... np.ma.array(data=[0.0, 1.0, 1.2], mask=[1, 1, 0]),
... config,
... )
False
coola.equality.tester.PandasDataFrameEqualityTester ¶
Bases: BaseEqualityTester[DataFrame]
Implement an equality tester for pandas.DataFrame.
This tester uses pandas' DataFrame equality testing which compares shape, column names, data types, index, and values. The handler chain: 1. SameObjectHandler: Check for object identity 2. SameTypeHandler: Verify both are pandas DataFrames 3. PandasDataFrameEqualHandler: Use pandas' assert_frame_equal internally
Note
The tester uses pandas' internal comparison logic which handles NaN values and performs comprehensive DataFrame equality checking.
Example
Basic DataFrame comparison:
>>> import pandas as pd
>>> from coola.equality.config import EqualityConfig
>>> from coola.equality.tester import PandasDataFrameEqualityTester
>>> config = EqualityConfig()
>>> tester = PandasDataFrameEqualityTester()
>>> tester.objects_are_equal(
... pd.DataFrame({"col": [1, 2, 3]}),
... pd.DataFrame({"col": [1, 2, 3]}),
... config,
... )
True
>>> tester.objects_are_equal(
... pd.DataFrame({"col": [1, 2, 3]}),
... pd.DataFrame({"col": [1, 2, 4]}),
... config,
... )
False
Different column names are not equal:
>>> import pandas as pd
>>> from coola.equality.config import EqualityConfig
>>> from coola.equality.tester import PandasDataFrameEqualityTester
>>> config = EqualityConfig()
>>> tester = PandasDataFrameEqualityTester()
>>> tester.objects_are_equal(
... pd.DataFrame({"col1": [1, 2, 3]}),
... pd.DataFrame({"col2": [1, 2, 3]}),
... config,
... )
False
coola.equality.tester.PandasSeriesEqualityTester ¶
Bases: BaseEqualityTester[Series]
Implement an equality tester for pandas.Series.
This tester uses pandas' Series equality testing which compares length, data type, index, and values. The handler chain: 1. SameObjectHandler: Check for object identity 2. SameTypeHandler: Verify both are pandas Series 3. PandasSeriesEqualHandler: Use pandas' assert_series_equal internally
Note
The tester uses pandas' internal comparison logic which handles NaN values and performs comprehensive Series equality checking.
Example
Basic Series comparison:
>>> import pandas as pd
>>> from coola.equality.config import EqualityConfig
>>> from coola.equality.tester import PandasSeriesEqualityTester
>>> config = EqualityConfig()
>>> tester = PandasSeriesEqualityTester()
>>> tester.objects_are_equal(pd.Series([1, 2, 3]), pd.Series([1, 2, 3]), config)
True
>>> tester.objects_are_equal(pd.Series([1, 2, 3]), pd.Series([1, 2, 4]), config)
False
Different index values are not equal:
>>> import pandas as pd
>>> from coola.equality.config import EqualityConfig
>>> from coola.equality.tester import PandasSeriesEqualityTester
>>> config = EqualityConfig()
>>> tester = PandasSeriesEqualityTester()
>>> tester.objects_are_equal(
... pd.Series([1, 2, 3], index=["a", "b", "c"]),
... pd.Series([1, 2, 3], index=["x", "y", "z"]),
... config,
... )
False
coola.equality.tester.PolarsDataFrameEqualityTester ¶
Bases: BaseEqualityTester[DataFrame]
Implement an equality tester for polars.DataFrame.
This tester uses Polars' DataFrame equality testing. The handler chain: 1. SameObjectHandler: Check for object identity 2. SameTypeHandler: Verify both are polars DataFrames 3. PolarsDataFrameEqualHandler: Use Polars' internal equality testing
Example
Basic DataFrame comparison:
>>> import polars as pl
>>> from coola.equality.config import EqualityConfig
>>> from coola.equality.tester import PolarsDataFrameEqualityTester
>>> config = EqualityConfig()
>>> tester = PolarsDataFrameEqualityTester()
>>> tester.objects_are_equal(
... pl.DataFrame({"col": [1, 2, 3]}),
... pl.DataFrame({"col": [1, 2, 3]}),
... config,
... )
True
>>> tester.objects_are_equal(
... pl.DataFrame({"col": [1, 2, 3]}),
... pl.DataFrame({"col": [1, 2, 4]}),
... config,
... )
False
coola.equality.tester.PolarsLazyFrameEqualityTester ¶
Bases: BaseEqualityTester[LazyFrame]
Implement an equality tester for polars.LazyFrame.
This tester uses Polars' LazyFrame equality testing. The handler chain: 1. SameObjectHandler: Check for object identity 2. SameTypeHandler: Verify both are polars LazyFrames 3. PolarsLazyFrameEqualHandler: Use Polars' internal equality testing
Note
LazyFrames represent query plans and are collected (materialized) for comparison, which may have performance implications for large datasets.
Example
Basic LazyFrame comparison:
>>> import polars as pl
>>> from coola.equality.config import EqualityConfig
>>> from coola.equality.tester import PolarsLazyFrameEqualityTester
>>> config = EqualityConfig()
>>> tester = PolarsLazyFrameEqualityTester()
>>> tester.objects_are_equal(
... pl.LazyFrame({"col": [1, 2, 3]}),
... pl.LazyFrame({"col": [1, 2, 3]}),
... config,
... )
True
>>> tester.objects_are_equal(
... pl.LazyFrame({"col": [1, 2, 3]}),
... pl.LazyFrame({"col": [1, 2, 4]}),
... config,
... )
False
coola.equality.tester.PolarsSeriesEqualityTester ¶
Bases: BaseEqualityTester[Series]
Implement an equality tester for polars.Series.
This tester uses Polars' Series equality testing. The handler chain: 1. SameObjectHandler: Check for object identity 2. SameTypeHandler: Verify both are polars Series 3. PolarsSeriesEqualHandler: Use Polars' internal equality testing
Example
Basic Series comparison:
>>> import polars as pl
>>> from coola.equality.config import EqualityConfig
>>> from coola.equality.tester import PolarsSeriesEqualityTester
>>> config = EqualityConfig()
>>> tester = PolarsSeriesEqualityTester()
>>> tester.objects_are_equal(pl.Series([1, 2, 3]), pl.Series([1, 2, 3]), config)
True
>>> tester.objects_are_equal(pl.Series([1, 2, 3]), pl.Series([1, 2, 4]), config)
False
coola.equality.tester.PyarrowEqualityTester ¶
Bases: BaseEqualityTester[Array]
Implement an equality tester for pyarrow.Arrays and
pyarrow.Tables.
This tester uses PyArrow's equals() method for comparison. The handler chain: 1. SameObjectHandler: Check for object identity 2. SameTypeHandler: Verify both are pyarrow objects 3. PyarrowEqualHandler: Use PyArrow's equals() method
Note
The config.equal_nan, config.atol, and config.rtol arguments
are ignored as PyArrow's equals() method does not support these parameters.
PyArrow performs its own equality checking logic.
Example
Basic array comparison:
>>> import pyarrow as pa
>>> from coola.equality.config import EqualityConfig
>>> from coola.equality.tester import PyarrowEqualityTester
>>> config = EqualityConfig()
>>> tester = PyarrowEqualityTester()
>>> tester.objects_are_equal(pa.array([1, 2, 3]), pa.array([1, 2, 3]), config)
True
>>> tester.objects_are_equal(pa.array([1, 2, 3]), pa.array([1, 2, 4]), config)
False
Table comparison:
>>> import pyarrow as pa
>>> from coola.equality.config import EqualityConfig
>>> from coola.equality.tester import PyarrowEqualityTester
>>> config = EqualityConfig()
>>> tester = PyarrowEqualityTester()
>>> table1 = pa.table({"col": [1, 2, 3]})
>>> table2 = pa.table({"col": [1, 2, 3]})
>>> tester.objects_are_equal(table1, table2, config)
True
coola.equality.tester.ScalarEqualityTester ¶
Bases: BaseEqualityTester[float]
Implement a scalar equality tester.
This tester handles numeric scalar types (int, float) with support for NaN equality and tolerance-based comparisons. The handler chain: 1. SameObjectHandler: Check for object identity 2. SameTypeHandler: Verify same type 3. NanEqualHandler: Handle NaN comparisons based on config.equal_nan 4. ScalarEqualHandler: Compare values with tolerance (config.atol, config.rtol)
This tester is registered for both int and float types in the default registry.
Example
Basic scalar comparison:
>>> from coola.equality.config import EqualityConfig
>>> from coola.equality.tester import ScalarEqualityTester
>>> config = EqualityConfig()
>>> tester = ScalarEqualityTester()
>>> tester.objects_are_equal(42.0, 42.0, config)
True
>>> tester.objects_are_equal(42.0, 1.0, config)
False
NaN comparison with equal_nan enabled:
>>> from coola.equality.config import EqualityConfig
>>> from coola.equality.tester import ScalarEqualityTester
>>> config = EqualityConfig(equal_nan=True)
>>> tester = ScalarEqualityTester()
>>> tester.objects_are_equal(float("nan"), float("nan"), config)
True
Tolerance-based comparison:
>>> from coola.equality.config import EqualityConfig
>>> from coola.equality.tester import ScalarEqualityTester
>>> config = EqualityConfig(atol=1e-6)
>>> tester = ScalarEqualityTester()
>>> tester.objects_are_equal(1.0, 1.0000001, config)
True
coola.equality.tester.SequenceEqualityTester ¶
Bases: BaseEqualityTester[Sequence[Any]]
Implement a sequence equality tester.
This tester handles sequence types (list, tuple, deque, Sequence ABC) by recursively comparing their elements. The handler chain: 1. SameObjectHandler: Check for object identity 2. SameTypeHandler: Verify same type 3. SameLengthHandler: Check both sequences have same length 4. SequenceSameValuesHandler: Recursively compare elements using registry 5. TrueHandler: Return True if all checks pass
Elements are compared in order and recursively, so nested lists, dicts, and other complex structures are handled correctly.
Example
Basic sequence comparison:
>>> from coola.equality.config import EqualityConfig
>>> from coola.equality.tester import SequenceEqualityTester
>>> config = EqualityConfig()
>>> tester = SequenceEqualityTester()
>>> tester.objects_are_equal([1, 2, 3], [1, 2, 3], config)
True
>>> tester.objects_are_equal([1, 2, 3], [1, 2, 4], config)
False
Nested sequence comparison:
>>> from coola.equality.config import EqualityConfig
>>> from coola.equality.tester import SequenceEqualityTester
>>> config = EqualityConfig()
>>> tester = SequenceEqualityTester()
>>> tester.objects_are_equal(
... [[1, 2], {"a": 3}],
... [[1, 2], {"a": 3}],
... config,
... )
True
coola.equality.tester.TorchPackedSequenceEqualityTester ¶
Bases: BaseEqualityTester[PackedSequence]
Implement an equality tester for
torch.nn.utils.rnn.PackedSequence.
This tester compares PyTorch packed sequences by checking data tensor and metadata attributes. The handler chain: 1. SameObjectHandler: Check for object identity 2. SameTypeHandler: Verify both are PackedSequence 3. SameDataHandler: Compare the data tensors 4. SameAttributeHandler("batch_sizes"): Compare batch_sizes tensors 5. SameAttributeHandler("sorted_indices"): Compare sorted_indices (if present) 6. SameAttributeHandler("unsorted_indices"): Compare unsorted_indices (if present) 7. TrueHandler: Return True if all checks pass
Example
Basic packed sequence comparison:
>>> import torch
>>> from coola.equality.config import EqualityConfig
>>> from coola.equality.tester import TorchPackedSequenceEqualityTester
>>> config = EqualityConfig()
>>> tester = TorchPackedSequenceEqualityTester()
>>> seq1 = torch.nn.utils.rnn.pack_padded_sequence(
... torch.tensor([[1.0, 2.0], [3.0, 4.0]]),
... lengths=torch.tensor([2, 1]),
... batch_first=True,
... enforce_sorted=False,
... )
>>> seq2 = torch.nn.utils.rnn.pack_padded_sequence(
... torch.tensor([[1.0, 2.0], [3.0, 4.0]]),
... lengths=torch.tensor([2, 1]),
... batch_first=True,
... enforce_sorted=False,
... )
>>> tester.objects_are_equal(seq1, seq2, config)
True
coola.equality.tester.TorchTensorEqualityTester ¶
Bases: BaseEqualityTester[Tensor]
Implement an equality tester for torch.Tensor.
This tester compares PyTorch tensors element-wise with support for device, dtype, shape checking, NaN equality, and tolerance-based comparisons. The handler chain: 1. SameObjectHandler: Check for object identity 2. SameTypeHandler: Verify both are torch tensors 3. SameDTypeHandler: Check tensors have the same dtype 4. SameShapeHandler: Verify tensors have the same shape 5. TorchTensorSameDeviceHandler: Ensure tensors are on the same device 6. TorchTensorEqualHandler: Element-wise comparison with tolerance support
The tester respects config.equal_nan for NaN comparisons and config.atol/rtol for floating-point tolerance.
Example
Basic tensor comparison:
>>> import torch
>>> from coola.equality.config import EqualityConfig
>>> from coola.equality.tester import TorchTensorEqualityTester
>>> config = EqualityConfig()
>>> tester = TorchTensorEqualityTester()
>>> tester.objects_are_equal(torch.ones(2, 3), torch.ones(2, 3), config)
True
>>> tester.objects_are_equal(torch.ones(2, 3), torch.zeros(2, 3), config)
False
NaN comparison with equal_nan:
>>> import torch
>>> from coola.equality.config import EqualityConfig
>>> from coola.equality.tester import TorchTensorEqualityTester
>>> config = EqualityConfig(equal_nan=True)
>>> tester = TorchTensorEqualityTester()
>>> tester.objects_are_equal(
... torch.tensor([1.0, float("nan")]),
... torch.tensor([1.0, float("nan")]),
... config,
... )
True
Tensors on different devices are not equal:
>>> import torch
>>> from coola.equality.config import EqualityConfig
>>> from coola.equality.tester import TorchTensorEqualityTester
>>> config = EqualityConfig()
>>> tester = TorchTensorEqualityTester()
>>> # This example assumes CUDA is available
>>> tester.objects_are_equal(
... torch.ones(2, 3),
... torch.ones(2, 3).cuda() if torch.cuda.is_available() else torch.ones(2, 3),
... config,
... ) # doctest: +SKIP
False
coola.equality.tester.XarrayDataArrayEqualityTester ¶
Bases: BaseEqualityTester[DataArray]
Implement an equality tester for xarray.DataArray.
This tester compares xarray DataArrays by checking their variable, name, and coordinates. The handler chain: 1. SameObjectHandler: Check for object identity 2. SameTypeHandler: Verify both are xarray DataArrays 3. SameAttributeHandler("variable"): Compare the underlying Variable 4. SameAttributeHandler("name"): Compare the DataArray names 5. SameAttributeHandler("_coords"): Compare the coordinate mappings 6. TrueHandler: Return True if all checks pass
Example
Basic DataArray comparison:
>>> import numpy as np
>>> import xarray as xr
>>> from coola.equality.config import EqualityConfig
>>> from coola.equality.tester import XarrayDataArrayEqualityTester
>>> config = EqualityConfig()
>>> tester = XarrayDataArrayEqualityTester()
>>> tester.objects_are_equal(
... xr.DataArray(np.arange(6), dims=["z"]),
... xr.DataArray(np.arange(6), dims=["z"]),
... config,
... )
True
>>> tester.objects_are_equal(
... xr.DataArray(np.ones(6), dims=["z"]),
... xr.DataArray(np.zeros(6), dims=["z"]),
... config,
... )
False
coola.equality.tester.XarrayDatasetEqualityTester ¶
Bases: BaseEqualityTester[Dataset]
Implement an equality tester for xarray.Dataset.
This tester compares xarray Datasets by checking their data variables, coordinates, and attributes. The handler chain: 1. SameObjectHandler: Check for object identity 2. SameTypeHandler: Verify both are xarray Datasets 3. SameAttributeHandler("data_vars"): Compare data variable dictionaries 4. SameAttributeHandler("coords"): Compare coordinate dictionaries 5. SameAttributeHandler("attrs"): Compare attribute dictionaries 6. TrueHandler: Return True if all checks pass
Example
Basic Dataset comparison:
>>> import numpy as np
>>> import xarray as xr
>>> from coola.equality.config import EqualityConfig
>>> from coola.equality.tester import XarrayDatasetEqualityTester
>>> config = EqualityConfig()
>>> tester = XarrayDatasetEqualityTester()
>>> tester.objects_are_equal(
... xr.Dataset({"x": xr.DataArray(np.arange(6), dims=["z"])}),
... xr.Dataset({"x": xr.DataArray(np.arange(6), dims=["z"])}),
... config,
... )
True
>>> tester.objects_are_equal(
... xr.Dataset({"x": xr.DataArray(np.zeros(6), dims=["z"])}),
... xr.Dataset({"x": xr.DataArray(np.ones(6), dims=["z"])}),
... config,
... )
False
coola.equality.tester.XarrayVariableEqualityTester ¶
Bases: BaseEqualityTester[Variable]
Implement an equality tester for xarray.Variable.
This tester compares xarray Variables by checking their data, dimensions, and attributes. The handler chain: 1. SameObjectHandler: Check for object identity 2. SameTypeHandler: Verify both are xarray Variables 3. SameDataHandler: Compare the underlying data arrays 4. SameAttributeHandler("dims"): Compare the dimension names 5. SameAttributeHandler("attrs"): Compare attribute dictionaries 6. TrueHandler: Return True if all checks pass
Example
Basic Variable comparison:
>>> import numpy as np
>>> import xarray as xr
>>> from coola.equality.config import EqualityConfig
>>> from coola.equality.tester import XarrayVariableEqualityTester
>>> config = EqualityConfig()
>>> tester = XarrayVariableEqualityTester()
>>> tester.objects_are_equal(
... xr.Variable(dims=["z"], data=np.arange(6)),
... xr.Variable(dims=["z"], data=np.arange(6)),
... config,
... )
True
>>> tester.objects_are_equal(
... xr.Variable(dims=["z"], data=np.zeros(6)),
... xr.Variable(dims=["z"], data=np.ones(6)),
... config,
... )
False
coola.equality.tester.get_default_registry ¶
get_default_registry() -> EqualityTesterRegistry
Get or create the default global registry with common Python types.
Returns a singleton registry instance that is pre-configured with equality testers for Python's built-in types including sequences (list, tuple), mappings (dict), and scalar types (int, float).
This function uses a singleton pattern to ensure the same registry instance is returned on subsequent calls, which is efficient and maintains consistency across an application.
Returns:
| Type | Description |
|---|---|
EqualityTesterRegistry
|
A EqualityTesterRegistry instance with equality testers registered for: - Scalar types (int, float) - Sequences (list, tuple, deque, Sequence ABC) - Mappings (dict, Mapping ABC) - Third-party library types (numpy, torch, pandas, polars, jax, xarray, pyarrow) |
Notes
The singleton pattern means modifications to the returned registry affect all future calls to this function. If you need an isolated registry, create a new EqualityTesterRegistry instance directly.
Example
>>> from coola.equality.tester import get_default_registry
>>> from coola.equality.config import EqualityConfig
>>> registry = get_default_registry()
>>> # Registry is ready to use with common Python types
>>> config = EqualityConfig()
>>> registry.objects_are_equal([1, 2, 3], [1, 2, 3], config)
True
>>> registry.objects_are_equal([1, 2, 3], [1, 1], config)
False
coola.equality.tester.register_equality_testers ¶
register_equality_testers(
mapping: Mapping[type, BaseEqualityTester[Any]],
exist_ok: bool = False,
) -> None
Register custom equality testers to the default global registry.
This allows users to add support for custom types without modifying global state directly.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
mapping
|
Mapping[type, BaseEqualityTester[Any]]
|
Dictionary mapping types to equality tester instances |
required |
exist_ok
|
bool
|
If False, raises error if any type already registered |
False
|
Example
>>> from coola.equality.tester import register_equality_testers, BaseEqualityTester
>>> class MyType:
... def __init__(self, value):
... self.value = value
...
>>> class MyEqualityTester(BaseEqualityTester[MyType]):
... def equal(self, other: object) -> bool:
... return type(other) is type(self)
... def objects_are_equal(
... self, actual: MyType, expected: object, config: EqualityConfig
... ) -> bool:
... if type(other) is not type(self):
... return False
... return actual.value == expected.value
...
>>> register_equality_testers({MyType: MyEqualityTester()})