blob: ba73b0a4b5fc6b1b13607e4f2f7bf52774ed4e05 [file] [log] [blame]
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)