def toggle_attribute(obj, attr_name, cross_mapped_values, default=None):
    """Toggle attribute between values a and b.

    This function is meant to be turned into partials
    by the get_attribute_toggler function for more efficient
    usage.

    It is slightly different from the toggler achievable with
    the get_attribute_rotator function because it checks the
    value of the attribute before toggling, so there is no
    intrinsic order. The value set depends solely on the
    current value.

    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 the value.
    cross_mapped_values (dict)
        its keys reference each other. Such keys represent
        values from which and to which to toggle.
    default (any python value/object)
        Value to use only in case no key is found.

    >>> class Obj: pass
    ...
    >>> obj = Obj()
    >>> d = {"a":"b", "b":"a"}
    >>> toggler = partial(toggle_attribute, obj, "char", d)

    >>> obj.char = "a"
    >>> toggler()
    >>> obj.char
    'b'
    >>> toggler()
    >>> obj.char
    'a'
    """
    ### retrieve current attribute value to use as key
    key = getattr(obj, attr_name)

    ### retrieve value using key, also defining a default
    ### to be returned if needed
    value = cross_mapped_values.get(key, default)

    ### assign value to the attribute
    setattr(obj, attr_name, value)
Toggle attribute between values a and b.

    This function is meant to be turned into partials
    by the get_attribute_toggler function for more efficient
    usage.

    It is slightly different from the toggler achievable with
    the get_attribute_rotator function because it checks the
    value of the attribute before toggling, so there is no
    intrinsic order. The value set depends solely on the
    current value.

    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 the value.
    cross_mapped_values (dict)
        its keys reference each other. Such keys represent
        values from which and to which to toggle.
    default (any python value/object)
        Value to use only in case no key is found.

    >>> class Obj: pass
    ...
    >>> obj = Obj()
    >>> d = {"a":"b", "b":"a"}
    >>> toggler = partial(toggle_attribute, obj, "char", d)

    >>> obj.char = "a"
    >>> toggler()
    >>> obj.char
    'b'
    >>> toggler()
    >>> obj.char
    'a'
    
nodezator/ourstdlibs/behaviour.py