Skip to content

Annotation equality checks can miss some parent class checks #133

@zhiltsov-max

Description

@zhiltsov-max

The annotation's __eq__() is primarily supported for testing. It's used here:

return expected == actual

In some annotation classes (e.g. RleMask) this method misses some checks due to class inheritance and base method implementation in attrs-defined classes.

Example:

import datumaro as dm
import numpy as np
from datumaro.util import mask_tools

>>> dm.Mask([0], id=1) == dm.Mask([0], id=1)
True
>>> dm.Mask([0], id=1) == dm.Mask([0], id=2)
False

>>> dm.Mask([[0]], id=1) == dm.RleMask(mask_tools.to_uncompressed_rle(mask_tools.mask_to_rle([[0]]), width=1, height=1), id=1)
True
>>> dm.Mask([[0]], id=1) == dm.RleMask(mask_tools.to_uncompressed_rle(mask_tools.mask_to_rle([[0]]), width=1, height=1), id=2)
True

Calls to the parent __eq__() in derived attrs classes is a deep topic with a lot of discussion: python-attrs/attrs#387. It seems we have nothing better than implementing the base class __eq__ manually, but done this way, it won't be used in the autogenerated __eq__ in subclasses.

@attrs(slots=True, kw_only=True, order=False, eq=False)
class Annotation:
    ...

    def __eq__(self, other: Annotation) -> bool:
        # attrs doesn't allow calling the autogenerated __eq__ for different subclasses,
        # but we need to compare the parent fields in some __eq__ overrides in subclasses.
        if not isinstance(other, __class__):
            return False

        return (
            self.id == other.id and
            self.group == other.group and
            self.object_id == other.object_id and
            self.attributes == other.attributes
        )

Originally posted by @zhiltsov-max in #131 (comment)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions