Skip to content

Commit f34f16b

Browse files
authored
Merge pull request RustPython#1095 from RustPython/coolreader18/whats_left-modules
Add module listing to whats_left.sh
2 parents 6b018a0 + 3668250 commit f34f16b

7 files changed

+166
-41
lines changed

tests/.gitignore

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
snippets/whats_left_to_implement.py
1+
snippets/whats_left_*.py
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
2+
3+
rustpymods = list(
4+
map(
5+
lambda mod: mod[0],
6+
filter(
7+
lambda mod: (mod[1] == "" or mod[1] == ".py") and "LICENSE" not in mod[0],
8+
map(os.path.splitext, os.listdir(libdir)),
9+
),
10+
)
11+
)
12+
rustpymods += list(sys.builtin_module_names)
13+
14+
rustpymods = dict(map(
15+
lambda mod: (
16+
mod,
17+
set(dir(__import__(mod)))
18+
if mod not in ("this", "antigravity")
19+
else None,
20+
),
21+
rustpymods
22+
))
23+
24+
for modname, cpymod in cpymods.items():
25+
if modname in rustpymods:
26+
rustpymod = rustpymods[modname]
27+
if rustpymod:
28+
for item in cpymod - rustpymod:
29+
print(f"{modname}.{item}")
30+
else:
31+
print(f"{modname} (entire module)")
32+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# WARNING: THIS IS AN AUTOMATICALLY GENERATED FILE
2+
# EDIT tests/not_impl_mods_gen.sh, NOT THIS FILE.
3+
# RESULTS OF THIS TEST DEPEND ON THE CPYTHON
4+
# VERSION AND PYTHON ENVIRONMENT USED
5+
# TO RUN not_impl_mods_gen.py
6+
7+
import sys
8+
import os

tests/not_impl_gen.py

+88-35
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,101 @@
1-
objects = [
2-
bool,
3-
bytearray,
4-
bytes,
5-
complex,
6-
dict,
7-
float,
8-
frozenset,
9-
int,
10-
list,
11-
memoryview,
12-
range,
13-
set,
14-
str,
15-
tuple,
16-
object,
17-
]
1+
# It's recommended to run this with `python3 -I not_impl_gen.py`, to make sure
2+
# that nothing in your global Python environment interferes with what's being
3+
# extracted here.
4+
5+
import pkgutil
6+
import os
7+
import sys
8+
9+
sys.path = list(
10+
filter(
11+
lambda path: "site-packages" not in path and "dist-packages" not in path,
12+
sys.path,
13+
)
14+
)
1815

1916

2017
def attr_is_not_inherited(type_, attr):
2118
"""
2219
returns True if type_'s attr is not inherited from any of its base classes
2320
"""
2421

25-
bases = obj.__mro__[1:]
22+
bases = type_.__mro__[1:]
23+
24+
return getattr(type_, attr) not in (getattr(base, attr, None) for base in bases)
25+
26+
27+
def gen_methods(header, footer, output):
28+
objects = [
29+
bool,
30+
bytearray,
31+
bytes,
32+
complex,
33+
dict,
34+
float,
35+
frozenset,
36+
int,
37+
list,
38+
memoryview,
39+
range,
40+
set,
41+
str,
42+
tuple,
43+
object,
44+
]
45+
46+
output.write(header.read())
47+
output.write("expected_methods = {\n")
48+
49+
for obj in objects:
50+
output.write(f" '{obj.__name__}': ({obj.__name__}, [\n")
51+
output.write(
52+
"\n".join(
53+
f" {attr!r},"
54+
for attr in dir(obj)
55+
if attr_is_not_inherited(obj, attr)
56+
)
57+
)
58+
output.write("\n ])," + ("\n" if objects[-1] == obj else "\n\n"))
59+
60+
output.write("}\n\n")
61+
output.write(footer.read())
62+
63+
64+
def gen_modules(header, footer, output):
65+
output.write(header.read())
66+
67+
modules = dict(
68+
map(
69+
lambda mod: (
70+
mod.name,
71+
# check name b/c modules listed have side effects on import,
72+
# e.g. printing something or opening a webpage
73+
set(dir(__import__(mod.name)))
74+
if mod.name not in ("this", "antigravity")
75+
else None,
76+
),
77+
pkgutil.iter_modules(),
78+
)
79+
)
80+
81+
print(
82+
f"""
83+
cpymods = {modules!r}
84+
libdir = {os.path.abspath("../Lib/")!r}
85+
""",
86+
file=output,
87+
)
2688

27-
return getattr(obj, attr) not in (
28-
getattr(base, attr, None) for base in bases)
89+
output.write(footer.read())
2990

3091

31-
header = open("generator/not_impl_header.txt")
32-
footer = open("generator/not_impl_footer.txt")
33-
output = open("snippets/whats_left_to_implement.py", "w")
92+
gen_funcs = {"methods": gen_methods, "modules": gen_modules}
3493

35-
output.write(header.read())
36-
output.write("expected_methods = {\n")
3794

38-
for obj in objects:
39-
output.write(f" '{obj.__name__}': ({obj.__name__}, [\n")
40-
output.write("\n".join(
41-
f" {attr!r},"
42-
for attr in dir(obj)
43-
if attr_is_not_inherited(obj, attr)
44-
))
45-
output.write("\n ])," + ("\n" if objects[-1] == obj else "\n\n"))
95+
for name, gen_func in gen_funcs.items():
96+
gen_func(
97+
header=open(f"generator/not_impl_{name}_header.txt"),
98+
footer=open(f"generator/not_impl_{name}_footer.txt"),
99+
output=open(f"snippets/whats_left_{name}.py", "w"),
100+
)
46101

47-
output.write("}\n\n")
48-
output.write(footer.read())

whats_left.sh

+37-5
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,43 @@
1-
#!/bin/sh
1+
#!/bin/bash
22
set -e
33

4+
ALL_SECTIONS=(methods modules)
5+
6+
GREEN=''
7+
BOLD=''
8+
NC='(B'
9+
10+
h() {
11+
# uppercase input
12+
header_name=$(echo "$@" | tr "[:lower:]" "[:upper:]")
13+
echo "$GREEN$BOLD===== $header_name =====$NC"
14+
}
15+
416
cd "$(dirname "$0")"
5-
cd tests
617

7-
python3 not_impl_gen.py
18+
(
19+
cd tests
20+
# -I means isolate from environment; we don't want any pip packages to be listed
21+
python3 -I not_impl_gen.py
22+
)
23+
24+
# show the building first, so people aren't confused why it's taking so long to
25+
# run whats_left_to_implement
26+
cargo build --release
827

9-
cd ..
28+
if [ $# -eq 0 ]; then
29+
sections=(${ALL_SECTIONS[@]})
30+
else
31+
sections=($@)
32+
fi
1033

11-
cargo run -- tests/snippets/whats_left_to_implement.py
34+
for section in "${sections[@]}"; do
35+
section=$(echo "$section" | tr "[:upper:]" "[:lower:]")
36+
snippet=tests/snippets/whats_left_$section.py
37+
if ! [[ -f $snippet ]]; then
38+
echo "Invalid section $section" >&2
39+
continue
40+
fi
41+
h "$section" >&2
42+
cargo run --release -q -- "$snippet"
43+
done

0 commit comments

Comments
 (0)