forked from RustPython/RustPython
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathnot_impl_gen.py
More file actions
142 lines (119 loc) · 3.75 KB
/
not_impl_gen.py
File metadata and controls
142 lines (119 loc) · 3.75 KB
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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
# It's recommended to run this with `python3 -I not_impl_gen.py`, to make sure
# that nothing in your global Python environment interferes with what's being
# extracted here.
import pkgutil
import os
import sys
import warnings
sys.path = list(
filter(
lambda path: "site-packages" not in path and "dist-packages" not in path,
sys.path,
)
)
def attr_is_not_inherited(type_, attr):
"""
returns True if type_'s attr is not inherited from any of its base classes
"""
bases = type_.__mro__[1:]
return getattr(type_, attr) not in (getattr(base, attr, None) for base in bases)
def gen_methods(header, footer, output):
types = [
bool,
bytearray,
bytes,
complex,
dict,
enumerate,
filter,
float,
frozenset,
int,
list,
map,
memoryview,
range,
set,
slice,
str,
super,
tuple,
object,
zip,
classmethod,
staticmethod,
property,
Exception,
BaseException,
]
objects = [(t.__name__, t.__name__) for t in types]
objects.extend([
('NoneType', 'type(None)'),
])
iters = [
('bytearray_iterator', 'type(bytearray().__iter__())'),
('bytes_iterator', 'type(bytes().__iter__())'),
('dict_keyiterator', 'type(dict().__iter__())'),
('dict_valueiterator', 'type(dict().values().__iter__())'),
('dict_itemiterator', 'type(dict().items().__iter__())'),
('dict_values', 'type(dict().values())'),
('dict_items', 'type(dict().items())'),
('set_iterator', 'type(set().__iter__())'),
('list_iterator', 'type(list().__iter__())'),
('range_iterator', 'type(range(0).__iter__())'),
('str_iterator', 'type(str().__iter__())'),
('tuple_iterator', 'type(tuple().__iter__())'),
]
output.write(header.read())
output.write("expected_methods = {\n")
for name, typ_code in objects + iters:
typ = eval(typ_code)
output.write(f" '{name}': ({typ_code}, [\n")
output.write(
"\n".join(
f" {attr!r},"
for attr in dir(typ)
if attr_is_not_inherited(typ, attr)
)
)
output.write("\n ])," + ("\n" if objects[-1] == typ else "\n\n"))
output.write("}\n\n")
output.write(footer.read())
def get_module_methods(name):
with warnings.catch_warnings():
# ignore warnings caused by importing deprecated modules
warnings.filterwarnings("ignore", category=DeprecationWarning)
try:
return set(dir(__import__(name))) if name not in ("this", "antigravity") else None
except ModuleNotFoundError:
return None
except Exception as e:
print("!!! {} skipped because {}: {}".format(name, type(e).__name__, str(e)))
def gen_modules(header, footer, output):
output.write(header.read())
modules = dict(
map(
lambda mod: (
mod.name,
# check name b/c modules listed have side effects on import,
# e.g. printing something or opening a webpage
get_module_methods(mod.name)
),
pkgutil.iter_modules(),
)
)
print(
f"""
cpymods = {modules!r}
libdir = {os.path.abspath("../Lib/").encode('utf8')!r}
""",
file=output,
)
output.write(footer.read())
gen_funcs = {"methods": gen_methods, "modules": gen_modules}
for name, gen_func in gen_funcs.items():
gen_func(
header=open(f"generator/not_impl_{name}_header.txt"),
footer=open(f"generator/not_impl_{name}_footer.txt"),
output=open(f"snippets/whats_left_{name}.py", "w"),
)