from types import GeneratorType class Expr(object): def __init__(self, *args): self.data = args def __iter__(self): return iter(self.data) def __repr__(self): return '%s %s'%(self.__class__.__name__, repr(self.data)) class OR(Expr): pass def expand_rules(rules): result = {} for rule in rules: data = rules[rule] i = 0 for instance in expand_options(data): result["%s_%03d"%(rule, i)] = instance i+=1 return result def permute_dict(d, r=None): if not d: yield r return if r is None: r = {} k = d.keys()[0] tmp = d.copy() del tmp[k] if isinstance(d[k], dict): for w in permute_dict(d[k]): r[k] = w.copy() for foo in permute_dict(tmp, r): yield foo else: for v in expand_options(d[k]): r[k] = v for foo in permute_dict(tmp, r): yield foo def expand_options(data, n=0): if isinstance(data, dict): for v in permute_dict(data): yield v.copy() elif isinstance(data, OR) or isinstance(data, tuple) or isinstance(data, list): for value in data: for v in expand_options(value,n+1): yield v else: yield data def freeciv_formatter(rules): for section in sorted(rules.keys()): print "[%s]"%section for option, data in sorted(rules[section].items()): print option,'=', if isinstance(data, dict): print '{', print ', '.join('"%s"'%x for x in data) print '\t'+', '.join('"%s"'%x for x in data.values()) print '}' else: print data print test_1 = { 'test': 'a', 'test2': 'b' } test_2 = { 'test': {'a': 'b', 'c': 'd'}, 'test2': {'a': 1, 'c': 2} } test_3 = { 'test': (1, 2, 3) } test_4 = { 'test': OR(1, 2, 3) } test_5 = { 'test_single': {'a': (1, 2, 3)}, 'test_double': {'a': (1,2), 'b': (3,4)}, 'test_triple': {'a': (1,2,3), 'b': 'b', 'c': 'c'} } test_6 = { 'test': {'a': (1,2), 'b': (3, 4), 'c': (5,6)} } test_7 = { 'test': {'a': (1, (2, 3), 4), 'b': ((5, 6), (7, 8))} } rules_1 = { 'effect_martial_law_each': { 'name': 'Martial_Law_Each', 'value': 1, 'reqs': OR(dict(type='Gov', name='Anarchy', range='Player'), dict(type='Gov', name='Despotism', range='Player'), dict(type='Gov', name='Monarchy', range='Player')) } } rules_2 = { 'effect_martial_law_each': { 'name': 'Martial_Law_Each', 'value': 1, 'reqs': {'type': 'Gov', 'range': 'Player', 'name': OR('Monarchy', 'Anarchy', 'Despotism')} } } print '; OR of lists' freeciv_formatter(expand_rules(rules_1)) print '; OR of gov names' freeciv_formatter(expand_rules(rules_2))