def flatten_mapping_values(mapping_obj):
    """Return all values from map, including nested ones.

    The values are return in the form of a generator
    object.

    The mapping_obj parameter receives any python obj for
    which isinstance(obj, collections.abc.Mapping)
    returns True. It's "values" method is used to return
    its values.

    Since the order of the returned values in the
    generator depends on the specific mapping
    implementation there's no way to predict the order in
    which the values are returned.

    Even more so considering the execution flow goes
    through many different mappings in different nesting
    levels. Thus, such mappings may or not have different
    implementations.

    >>> phone_numbers = {
    ...   "Kelly": 5128,
    ...   "Amanda": {
    ...     "home": 8222,
    ...     "work": 4560
    ...   }
    ... }
    >>> actual = flatten_mapping_values(phone_numbers)
    >>> expected = (5128, 8222, 4560)
    >>> sorted(actual) == sorted(expected)
    True
    """
    ### iterate over all values in the mapping obj

    for value in mapping_obj.values():

        ## if the value isn't a mapping just yield it
        if not isinstance(value, Mapping):
            yield value

        ## otherwise, pass the value through this function
        ## again recursively, yielding each nested item
        ## resulting from the call

        # XXX use 'yield from' statement here

        else:

            for nested_value in flatten_mapping_values(value):
                yield nested_value
Return all values from map, including nested ones.

    The values are return in the form of a generator
    object.

    The mapping_obj parameter receives any python obj for
    which isinstance(obj, collections.abc.Mapping)
    returns True. It's "values" method is used to return
    its values.

    Since the order of the returned values in the
    generator depends on the specific mapping
    implementation there's no way to predict the order in
    which the values are returned.

    Even more so considering the execution flow goes
    through many different mappings in different nesting
    levels. Thus, such mappings may or not have different
    implementations.

    >>> phone_numbers = {
    ...   "Kelly": 5128,
    ...   "Amanda": {
    ...     "home": 8222,
    ...     "work": 4560
    ...   }
    ... }
    >>> actual = flatten_mapping_values(phone_numbers)
    >>> expected = (5128, 8222, 4560)
    >>> sorted(actual) == sorted(expected)
    True
    
nodezator/ourstdlibs/behaviour.py