def get_attribute_toggler(
    obj, attr_name, starting_value, mapping_or_value, default=None
):
    """Return function to toggle obj atribute values.

    Creates a partial from the provided arguments using
    the toggle_attribute function.

    obj (any object which can have attributes set on it)
        object whose attribute is used to hold the value.
    attr_name (string)
        name of the attribute where to store a value.
    starting_value (any hashable obj/value),
        starting value to be assigned to the attribute.

    mapping_or_value (a dict or any hashable obj/value)
        The type of mapping_or_value may be different depending
        on two scenarios:

        1) If you have more than two values between which
           you desired to toggle though, you must then
           provide a mapping which associates the current
           value of the attribute with the desired value to
           be assigned when toggling.


        2) value to which we should toggle when executing
           the partial returned. Executing the partial
           returned again should set the previous value
           in the attribute again and so on.

        Either way the arguments are stored in a mapping
        so they fit the first scenario, thus complying with
        the underlying toggle_attribute function.

        The first scenario is just a simplification, since
        having two values to toggle would mean you want to
        toggle between them in this context. There's no
        absolute need to make each value reference each other,
        though. The work of the toggle is just to set a
        value for the attribute based on the current value
        stored there. If no value is found in the dict which
        is associated with the current value, the toggler
        (partial) will do nothing.
    default (any python value/object)
        Value to use only in case no key is found.

    >>> class Obj: pass
    ...
    >>> obj = Obj()
    >>> toggle_char = get_attribute_toggler(
    ...                   obj, 'char', 'a', 'b')
    >>> obj.char
    'a'
    >>> toggle_char()
    >>> obj.char
    'b'
    >>> obj.char = 'c'
    >>> toggle_char()
    >>> obj.char # without default it returns None
    >>>

    >>> obj.char = 'a'
    >>> toggle_char()
    >>> obj.char
    'b'
    >>> d = {1:5, 5:22, 22:13, 13:1}
    >>> toggle_number = get_attribute_toggler(
    ...                     obj, 'number', 22, d, 100)
    >>> obj.number
    22
    >>> toggle_number()
    >>> obj.number
    13
    >>> toggle_number()
    >>> obj.number
    1
    >>> obj.number = 342
    >>> toggle_number()
    >>> obj.number # 342 isn't a key, so returns default
    100

    """
    ### set the starting value of the attribute
    setattr(obj, attr_name, starting_value)

    ### now check the type of the arguments so you can
    ### create or reference the cross_mapped_values dict

    ## if mapping_or_value is a dict, reference it
    if isinstance(mapping_or_value, dict):
        cross_mapped_values = mapping_or_value

    ## otherwise, mapping_or_value is actually a value,
    ## so just use it to build a new dict
    else:
        another_value = mapping_or_value

        cross_mapped_values = {
            starting_value: another_value,
            another_value: starting_value,
        }

    ### return function
    return partial(toggle_attribute, obj, attr_name, cross_mapped_values, default)
Return function to toggle obj atribute values.

    Creates a partial from the provided arguments using
    the toggle_attribute function.

    obj (any object which can have attributes set on it)
        object whose attribute is used to hold the value.
    attr_name (string)
        name of the attribute where to store a value.
    starting_value (any hashable obj/value),
        starting value to be assigned to the attribute.

    mapping_or_value (a dict or any hashable obj/value)
        The type of mapping_or_value may be different depending
        on two scenarios:

        1) If you have more than two values between which
           you desired to toggle though, you must then
           provide a mapping which associates the current
           value of the attribute with the desired value to
           be assigned when toggling.


        2) value to which we should toggle when executing
           the partial returned. Executing the partial
           returned again should set the previous value
           in the attribute again and so on.

        Either way the arguments are stored in a mapping
        so they fit the first scenario, thus complying with
        the underlying toggle_attribute function.

        The first scenario is just a simplification, since
        having two values to toggle would mean you want to
        toggle between them in this context. There's no
        absolute need to make each value reference each other,
        though. The work of the toggle is just to set a
        value for the attribute based on the current value
        stored there. If no value is found in the dict which
        is associated with the current value, the toggler
        (partial) will do nothing.
    default (any python value/object)
        Value to use only in case no key is found.

    >>> class Obj: pass
    ...
    >>> obj = Obj()
    >>> toggle_char = get_attribute_toggler(
    ...                   obj, 'char', 'a', 'b')
    >>> obj.char
    'a'
    >>> toggle_char()
    >>> obj.char
    'b'
    >>> obj.char = 'c'
    >>> toggle_char()
    >>> obj.char # without default it returns None
    >>>

    >>> obj.char = 'a'
    >>> toggle_char()
    >>> obj.char
    'b'
    >>> d = {1:5, 5:22, 22:13, 13:1}
    >>> toggle_number = get_attribute_toggler(
    ...                     obj, 'number', 22, d, 100)
    >>> obj.number
    22
    >>> toggle_number()
    >>> obj.number
    13
    >>> toggle_number()
    >>> obj.number
    1
    >>> obj.number = 342
    >>> toggle_number()
    >>> obj.number # 342 isn't a key, so returns default
    100

    
nodezator/ourstdlibs/behaviour.py