mirror of
				https://github.com/python/cpython.git
				synced 2025-10-30 21:21:22 +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)
 | 
