Last active
May 13, 2016 13:39
-
-
Save reclosedev/894d563eec69a3c74d2dd969735c72d9 to your computer and use it in GitHub Desktop.
Revisions
-
reclosedev revised this gist
May 13, 2016 . No changes.There are no files selected for viewing
-
reclosedev created this gist
May 13, 2016 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,84 @@ """ Module contains ``order_dicts`` decorator. When used, all dicts declarations are converted to OrderedDict. Example:: from new_order import order_dicts @order_dicts def func(): d1 = {1: 2, 3: 4, 5: 6} d2 = {"test": 2 ** 42, "foo": "bar", "baz": d1} print("What do we have here? %s" % d1) print(d2) func() Output:: What do we have here? OrderedDict([(1, 2), (3, 4), (5, 6)]) OrderedDict([('test', 4398046511104), ('foo', 'bar'), ('baz', OrderedDict([(1, 2), (3, 4), (5, 6)]))]) """ import ast import inspect import textwrap class order_dicts(object): """ Decorator to convert all dict literals to OrderedDict. """ def __init__(self, func): self.original_function = func self.updated_function = None def __call__(self, *args, **kwargs): if self.updated_function is None: source = inspect.getsourcelines(self.original_function) source = "".join(source[0]) source = textwrap.dedent(source) code = _convert_dicts_to_ordered(source) exec(code, self.original_function.__globals__) result = self.original_function.__globals__[self.original_function.__name__] while isinstance(result, order_dicts): result = result.original_function self.updated_function = result return self.updated_function(*args, **kwargs) def _convert_dicts_to_ordered(source): root = ast.parse(source) import_odict = ast.parse("from collections import OrderedDict") root.body.insert(0, import_odict.body[0]) root = ChangeDictToOrderedTransformer().visit(root) root = ast.fix_missing_locations(root) return compile(root, "<string>", "exec") class ChangeDictToOrderedTransformer(ast.NodeTransformer): def visit_Dict(self, node): self.generic_visit(node) tuples = [ast.Tuple(elts=[key, value], ctx=ast.Load()) for key, value in zip(node.keys, node.values)] od_node = ast.Call( func=ast.Name(id="OrderedDict", ctx=ast.Load()), args=[ast.Tuple(elts=tuples, ctx=ast.Load())], ctx=ast.Load(), keywords=[], starargs=None, kwargs=None ) return od_node # Demo if __name__ == "__main__": @order_dicts def func(): d1 = {1: 2, 3: 4, 5: 6} d2 = {"test": 2 ** 42, "foo": "bar", "baz": d1} print("What do we have here? %s" % d1) print(d2) func()