mirror of
				https://github.com/python/cpython.git
				synced 2025-11-04 07:31:38 +00:00 
			
		
		
		
	
		
			
	
	
		
			61 lines
		
	
	
	
		
			1.8 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
		
		
			
		
	
	
			61 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)
							 |