-
Notifications
You must be signed in to change notification settings - Fork 16
/
Copy pathmoduledump.py
109 lines (82 loc) · 3.77 KB
/
moduledump.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
import collections
import inspect
import importlib
import io
import os
import sys
import types
def flatten(seq):
for obj in seq:
try:
it = iter(obj)
except TypeError:
yield obj
else:
for o in flatten(obj):
yield o
def sorted_mapping(mapping, **kwargs):
out = collections.OrderedDict()
for k in sorted(mapping.keys(), **kwargs):
out[k] = mapping[k]
return out
def order_classes(classes):
classes = list(classes)
ordered = list(flatten(inspect.getclasstree(classes)))
ordered.reverse()
for cls in list(ordered):
if cls not in classes or ordered.count(cls) > 1:
ordered.remove(cls)
ordered.reverse()
return ordered
def order_attributes(attrs):
constants = {}
functions = {}
classes = {}
for key, value in attrs.items():
if isinstance(value, type(int.real)) or key in ("__abstractmethods__", "__base__", "__bases__", "__class__", "__dict__", "__dictoffset__", "__file__", "__flags__", "__itemsize__", "__module__", "__name__", "__package__", "__subclasses__", "__weakrefoffset__"):
pass
elif isinstance(value, (type, types.ClassType)):
classes[key] = value
elif isinstance(value, (types.FunctionType, types.BuiltinFunctionType, type(list.append), type(object.__init__), classmethod, staticmethod)):
if not (key.startswith("__") and key.endswith("__")):
functions[key] = value
else:
constants[key] = value
constants = sorted_mapping(constants)
functions = sorted_mapping(functions)
classes = sorted_mapping(classes)
classes_reverse = collections.OrderedDict((v, k) for k, v in classes.items())
classes_ordered = collections.OrderedDict((classes_reverse[cls], cls) for cls in order_classes(classes.values()))
return collections.OrderedDict(constants.items() + functions.items() + classes_ordered.items())
def stringify_constant(name, value):
return u"{} = {!r}".format(name, value)
def stringify_function(name, value):
return u"def {}(*args, **kwargs): pass".format(name)
def stringify_classmethod(name, value):
return u"def {}(cls, *args, **kwargs): pass".format(name)
def stringify_method(name, value):
return u"def {}(self, *args, **kwargs): pass".format(name)
def stringify_class(name, value):
attrs = list((k, v) for k, v in inspect.getmembers(value) if not hasattr(super(value), k) or v != getattr(super(value), k))
if type(value) not in [type(cls) for cls in value.__bases__]:
attrs = [("__metaclass__", type(value))] + attrs
body = u"\n".join(u" " + line for line in stringify_attributes(order_attributes(collections.OrderedDict(attrs))).splitlines())
return u"\nclass {}({}):\n{}".format(name, ", ".join(cls.__name__ for cls in value.__bases__), body)
def stringify_attributes(attrs):
lines = []
for k, v in attrs.items():
if isinstance(v, (type, types.ClassType)):
lines.append(stringify_class(k, v))
elif isinstance(v, (types.MethodType, type(list.append), type(object.__init__))):
lines.append(stringify_method(k, v))
elif isinstance(v, classmethod):
lines.append(stringify_classmethod(k, v))
elif isinstance(v, (types.FunctionType, types.BuiltinFunctionType, staticmethod)):
lines.append(stringify_function(k, v))
else:
lines.append(stringify_constant(k, v))
return u"\n".join(lines)
if __name__ == "__main__":
name = sys.argv[1]
with io.open(os.extsep.join((name, u"py")), "w") as f:
f.write(stringify_attributes(order_attributes(collections.OrderedDict(inspect.getmembers(importlib.import_module(name))))))