mirror of
				https://github.com/python/cpython.git
				synced 2025-11-03 19:34:08 +00:00 
			
		
		
		
	* bpo-44893: Implement EntryPoint as simple class and deprecate tuple access in favor of attribute access. Syncs with importlib_metadata 4.8.1. * Apply refactorings found in importlib_metadata 4.8.2.
		
			
				
	
	
		
			73 lines
		
	
	
	
		
			2 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			73 lines
		
	
	
	
		
			2 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
from itertools import filterfalse
 | 
						|
 | 
						|
 | 
						|
def unique_everseen(iterable, key=None):
 | 
						|
    "List unique elements, preserving order. Remember all elements ever seen."
 | 
						|
    # unique_everseen('AAAABBBCCDAABBB') --> A B C D
 | 
						|
    # unique_everseen('ABBCcAD', str.lower) --> A B C D
 | 
						|
    seen = set()
 | 
						|
    seen_add = seen.add
 | 
						|
    if key is None:
 | 
						|
        for element in filterfalse(seen.__contains__, iterable):
 | 
						|
            seen_add(element)
 | 
						|
            yield element
 | 
						|
    else:
 | 
						|
        for element in iterable:
 | 
						|
            k = key(element)
 | 
						|
            if k not in seen:
 | 
						|
                seen_add(k)
 | 
						|
                yield element
 | 
						|
 | 
						|
 | 
						|
# copied from more_itertools 8.8
 | 
						|
def always_iterable(obj, base_type=(str, bytes)):
 | 
						|
    """If *obj* is iterable, return an iterator over its items::
 | 
						|
 | 
						|
        >>> obj = (1, 2, 3)
 | 
						|
        >>> list(always_iterable(obj))
 | 
						|
        [1, 2, 3]
 | 
						|
 | 
						|
    If *obj* is not iterable, return a one-item iterable containing *obj*::
 | 
						|
 | 
						|
        >>> obj = 1
 | 
						|
        >>> list(always_iterable(obj))
 | 
						|
        [1]
 | 
						|
 | 
						|
    If *obj* is ``None``, return an empty iterable:
 | 
						|
 | 
						|
        >>> obj = None
 | 
						|
        >>> list(always_iterable(None))
 | 
						|
        []
 | 
						|
 | 
						|
    By default, binary and text strings are not considered iterable::
 | 
						|
 | 
						|
        >>> obj = 'foo'
 | 
						|
        >>> list(always_iterable(obj))
 | 
						|
        ['foo']
 | 
						|
 | 
						|
    If *base_type* is set, objects for which ``isinstance(obj, base_type)``
 | 
						|
    returns ``True`` won't be considered iterable.
 | 
						|
 | 
						|
        >>> obj = {'a': 1}
 | 
						|
        >>> list(always_iterable(obj))  # Iterate over the dict's keys
 | 
						|
        ['a']
 | 
						|
        >>> list(always_iterable(obj, base_type=dict))  # Treat dicts as a unit
 | 
						|
        [{'a': 1}]
 | 
						|
 | 
						|
    Set *base_type* to ``None`` to avoid any special handling and treat objects
 | 
						|
    Python considers iterable as iterable:
 | 
						|
 | 
						|
        >>> obj = 'foo'
 | 
						|
        >>> list(always_iterable(obj, base_type=None))
 | 
						|
        ['f', 'o', 'o']
 | 
						|
    """
 | 
						|
    if obj is None:
 | 
						|
        return iter(())
 | 
						|
 | 
						|
    if (base_type is not None) and isinstance(obj, base_type):
 | 
						|
        return iter((obj,))
 | 
						|
 | 
						|
    try:
 | 
						|
        return iter(obj)
 | 
						|
    except TypeError:
 | 
						|
        return iter((obj,))
 |