def is_compliant(self, obj, *, reasons=None, path=("obj",)):
        """Check whether an object matches the description in this signature.

        This module places few restrictions on what an interface object may be; it does not
        prescribe a specific base class or a specific way of constructing the object, only
        the values that its attributes should have. This method ensures consistency between
        the signature and the interface object, checking every aspect of the provided interface
        object for compliance with the signature.

        It verifies that:

        * :py:`obj` has a :py:`signature` attribute whose value a :class:`Signature` instance
          such that :py:`self == obj.signature`;
        * for each member, :py:`obj` has an attribute with the same name, whose value:

          * for members with :meth:`dimensions <Member.dimensions>` specified, contains a list or
            a tuple (or several levels of nested lists or tuples, for multiple dimensions)
            satisfying the requirements below;
          * for port members, is a :ref:`value-like <lang-valuelike>` object casting to
            a :class:`Signal` or a :class:`Const` whose width and signedness is the same as that
            of the member, and (in case of a :class:`Signal`) whose initial value is that of the
            member;
          * for signature members, matches the description in the signature as verified by
            :meth:`Signature.is_compliant`.

        If the verification fails, this method reports the reason(s) by filling the :py:`reasons`
        container. These reasons are intended to be human-readable: more than one reason may be
        reported but only in cases where this is helpful (e.g. the same error message will not
        repeat 10 times for each of the 10 ports in a list).

        Arguments
        ---------
        reasons : :class:`list` or :py:`None`
            If provided, a container that receives diagnostic messages.
        path : :class:`tuple` of :class:`str`
            The :ref:`path <wiring-path>` to :py:`obj`. Could be set to improve diagnostic
            messages if :py:`obj` is nested within another object, or for clarity.

        Returns
        -------
        :class:`bool`
            :py:`True` if :py:`obj` matches the description in this signature, :py:`False`
            otherwise. If :py:`False` and :py:`reasons` was not :py:`None`, it will contain
            a detailed explanation why.
        """

        if not hasattr(obj, "signature"):
            if reasons is not None:
                reasons.append(f"{_format_path(path)} does not have an attribute 'signature'")
            return False
        if not isinstance(obj.signature, Signature):
            if reasons is not None:
                reasons.append(f"{_format_path(path + ('signature',))} is expected to be "
                               f"a signature, but it is a {obj.signature!r}")
            return False
        if self != obj.signature:
            if reasons is not None:
                reasons.append(f"{_format_path(path + ('signature',))} is expected to be equal "
                               f"to this signature, {self!r}, but it is a {obj.signature!r}")
            return False

        def check_attr_value(member, attr_value, *, path):
            if member.is_port:
                try:
                    attr_value_cast = Value.cast(attr_value)
                except:
                    if reasons is not None:
                        reasons.append(f"{_format_path(path)} is not a value-castable object, "
                                       f"but {attr_value!r}")
                    return False
                if not isinstance(attr_value_cast, (Signal, Const)):
                    if reasons is not None:
                        reasons.append(f"{_format_path(path)} is neither a signal nor a constant, "
                                       f"but {attr_value_cast!r}")
                    return False
                attr_shape = attr_value_cast.shape()
                if Shape.cast(attr_shape) != Shape.cast(member.shape):
                    if reasons is not None:
                        reasons.append(f"{_format_path(path)} is expected to have "
                                       f"the shape {_format_shape(member.shape)}, but it has "
                                       f"the shape {_format_shape(attr_shape)}")
                    return False
                if isinstance(attr_value_cast, Signal):
                    if attr_value_cast.init != member._init_as_const.value:
                        if reasons is not None:
                            reasons.append(f"{_format_path(path)} is expected to have "
                                           f"the initial value {member.init!r}, but it has "
                                           f"the initial value {attr_value_cast.init!r}")
                        return False
                return True
            if member.is_signature:
                return member.signature.is_compliant(attr_value, reasons=reasons, path=path)
            assert False # :nocov:

        def check_dimensions(member, attr_value, dimensions, *, path):
            if not dimensions:
                return check_attr_value(member, attr_value, path=path)

            dimension, *rest_of_dimensions = dimensions
            if not isinstance(attr_value, (tuple, list)):
                if reasons is not None:
                    reasons.append(f"{_format_path(path)} is expected to be a tuple or a list, "
                                   f"but it is a {attr_value!r}")
                return False
            if len(attr_value) != dimension:
                if reasons is not None:
                    reasons.append(f"{_format_path(path)} is expected to have dimension "
                                   f"{dimension}, but its length is {len(attr_value)}")
                return False

            result = True
            for index in range(dimension):
                if not check_dimensions(member, attr_value[index], rest_of_dimensions,
                                        path=(*path, index)):
                    result = False
                    if reasons is None:
                        break # short cicruit if detailed error message isn't required
            return result

        result = True
        for attr_name, member in self.members.items():
            try:
                attr_value = getattr(obj, attr_name)
            except AttributeError:
                if reasons is None:
                    return False
                else:
                    reasons.append(f"{_format_path(path)} does not have an attribute "
                                   f"{attr_name!r}")
                    result = False
                    continue
            if not check_dimensions(member, attr_value, member.dimensions, path=(*path, attr_name)):
                if reasons is None:
                    return False
                else:
                    # `reasons` was mutated by check_dimensions()
                    result = False
                    continue
        return result
Check whether an object matches the description in this signature.

        This module places few restrictions on what an interface object may be; it does not
        prescribe a specific base class or a specific way of constructing the object, only
        the values that its attributes should have. This method ensures consistency between
        the signature and the interface object, checking every aspect of the provided interface
        object for compliance with the signature.

        It verifies that:

        * :py:`obj` has a :py:`signature` attribute whose value a :class:`Signature` instance
          such that :py:`self == obj.signature`;
        * for each member, :py:`obj` has an attribute with the same name, whose value:

          * for members with :meth:`dimensions <Member.dimensions>` specified, contains a list or
            a tuple (or several levels of nested lists or tuples, for multiple dimensions)
            satisfying the requirements below;
          * for port members, is a :ref:`value-like <lang-valuelike>` object casting to
            a :class:`Signal` or a :class:`Const` whose width and signedness is the same as that
            of the member, and (in case of a :class:`Signal`) whose initial value is that of the
            member;
          * for signature members, matches the description in the signature as verified by
            :meth:`Signature.is_compliant`.

        If the verification fails, this method reports the reason(s) by filling the :py:`reasons`
        container. These reasons are intended to be human-readable: more than one reason may be
        reported but only in cases where this is helpful (e.g. the same error message will not
        repeat 10 times for each of the 10 ports in a list).

        Arguments
        ---------
        reasons : :class:`list` or :py:`None`
            If provided, a container that receives diagnostic messages.
        path : :class:`tuple` of :class:`str`
            The :ref:`path <wiring-path>` to :py:`obj`. Could be set to improve diagnostic
            messages if :py:`obj` is nested within another object, or for clarity.

        Returns
        -------
        :class:`bool`
            :py:`True` if :py:`obj` matches the description in this signature, :py:`False`
            otherwise. If :py:`False` and :py:`reasons` was not :py:`None`, it will contain
            a detailed explanation why.
        
amaranth/lib/wiring.py