Utility method to return a dictionary of attribute name > attribute type from the constructor of a given type
    It supports PEP484 and 'attrs' declaration, see https://github.com/python-attrs/attrs.

    :param item_type:
    :return: a dictionary containing for each attr name, a tuple (type, is_mandatory)

def get_constructor_attributes_types(item_type) -> Dict[str, Tuple[Type[Any], bool]]:
    """
    Utility method to return a dictionary of attribute name > attribute type from the constructor of a given type
    It supports PEP484 and 'attrs' declaration, see https://github.com/python-attrs/attrs.

    :param item_type:
    :return: a dictionary containing for each attr name, a tuple (type, is_mandatory)
    """
    res = dict()
    try:
        # -- Try to read an 'attr' declaration and to extract types and optionality
        from parsyfiles.plugins_optional.support_for_attrs import get_attrs_declarations
        decls = get_attrs_declarations(item_type)

        # check that types are correct
        for attr_name, v in decls.items():
            typ, is_optional = v

            # -- Get and check that the attribute type is PEP484 compliant
            typ = get_validated_attribute_type_info(typ, item_type, attr_name)

            # -- optional = attrs'Optional validator was used, or a default value was set, or type is pep484 Optional
            is_optional = is_optional or is_pep484_nonable(typ)

            # -- store both info in result dict
            res[attr_name] = (typ, not is_optional)

        return res

    except:  # ImportError or NotAnAttrsClassError but we obviously cant import the latter.
        pass  # do not specify a type and use 'pass' so as to reset the exception context

    # -- Fallback to PEP484

    # first get the signature of the class constructor
    s = _get_constructor_signature(item_type)

    # then extract the type and optionality of each attribute and raise errors if needed
    for attr_name in s.parameters.keys():
        # skip the 'self' attribute
        if attr_name != 'self':

            # -- Get and check that the attribute type is PEP484 compliant
            typ = get_validated_attribute_type_info(s.parameters[attr_name].annotation, item_type, attr_name)

            # -- is the attribute mandatory ?
            is_mandatory = (s.parameters[attr_name].default is Parameter.empty) and not is_pep484_nonable(typ)

            # -- store both info in result dict
            res[attr_name] = (typ, is_mandatory)

    return res