mirror of
				https://github.com/python/cpython.git
				synced 2025-11-02 22:51:25 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			60 lines
		
	
	
	
		
			1.8 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			60 lines
		
	
	
	
		
			1.8 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
import itertools
 | 
						|
 | 
						|
 | 
						|
class PseudoStr(str):
 | 
						|
    pass
 | 
						|
 | 
						|
 | 
						|
class StrProxy:
 | 
						|
    def __init__(self, value):
 | 
						|
        self.value = value
 | 
						|
    def __str__(self):
 | 
						|
        return self.value
 | 
						|
    def __bool__(self):
 | 
						|
        return bool(self.value)
 | 
						|
 | 
						|
 | 
						|
class Object:
 | 
						|
    def __repr__(self):
 | 
						|
        return '<object>'
 | 
						|
 | 
						|
 | 
						|
def wrapped_arg_combos(*args,
 | 
						|
                       wrappers=(PseudoStr, StrProxy),
 | 
						|
                       skip=(lambda w, i, v: not isinstance(v, str)),
 | 
						|
                       ):
 | 
						|
    """Yield every possible combination of wrapped items for the given args.
 | 
						|
 | 
						|
    Effectively, the wrappers are applied to the args according to the
 | 
						|
    powerset of the args indicies.  So the result includes the args
 | 
						|
    completely unwrapped.
 | 
						|
 | 
						|
    If "skip" is supplied (default is to skip all non-str values) and
 | 
						|
    it returns True for a given arg index/value then that arg will
 | 
						|
    remain unwrapped,
 | 
						|
 | 
						|
    Only unique results are returned.  If an arg was skipped for one
 | 
						|
    of the combinations then it could end up matching one of the other
 | 
						|
    combinations.  In that case only one of them will be yielded.
 | 
						|
    """
 | 
						|
    if not args:
 | 
						|
        return
 | 
						|
    indices = list(range(len(args)))
 | 
						|
    # The powerset (from recipe in the itertools docs).
 | 
						|
    combos = itertools.chain.from_iterable(itertools.combinations(indices, r)
 | 
						|
                                           for r in range(len(indices)+1))
 | 
						|
    seen = set()
 | 
						|
    for combo in combos:
 | 
						|
        for wrap in wrappers:
 | 
						|
            indexes = []
 | 
						|
            applied = list(args)
 | 
						|
            for i in combo:
 | 
						|
                arg = args[i]
 | 
						|
                if skip and skip(wrap, i, arg):
 | 
						|
                    continue
 | 
						|
                indexes.append(i)
 | 
						|
                applied[i] = wrap(arg)
 | 
						|
            key = (wrap, tuple(indexes))
 | 
						|
            if key not in seen:
 | 
						|
                yield tuple(applied)
 | 
						|
                seen.add(key)
 |