from typing import Callable


def get_attr_form_query_dict_or_kwargs(attr_name: str, query_dict: dict, callback: Callable, default: int, **kwargs):
    """
    Get a value from the given query_dict or from kwargs if absent from the first one. The callback function is used
    to convert the value and if this fails, to fallback to the given default value.

    :param attr_name: the attribute name to look for.
    :type attr_name: str
    :param query_dict: the query dict in which to look for the attribute
    :type query_dict: dict
    :param callback: the function to use in order to convert the attribute
    :type callback: Callable
    :param default: the default value for the attribute, if none is found
    :type default: int
    :param kwargs: the known args in which to look for the attribute first.
    :type kwargs: dict
    :return: the value extracted from query_dict or kwargs if present, default value instead.
    """
    if attr_name in kwargs.keys():
        value = callback(kwargs.get(attr_name, default), default)
    else:
        try:
            value = callback(query_dict.get(attr_name, default), default)
        except KeyError:
            value = default
    return value