# 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 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): objects = [ bool, bytearray, bytes, complex, dict, float, frozenset, int, list, memoryview, range, set, str, tuple, object, ] output.write(header.read()) output.write("expected_methods = {\n") for obj in objects: output.write(f" '{obj.__name__}': ({obj.__name__}, [\n") output.write( "\n".join( f" {attr!r}," for attr in dir(obj) if attr_is_not_inherited(obj, attr) ) ) output.write("\n ])," + ("\n" if objects[-1] == obj else "\n\n")) output.write("}\n\n") output.write(footer.read()) def get_module_methods(name): try: return set(dir(__import__(name))) if name not in ("this", "antigravity") else None except ModuleNotFoundError: return None 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/")!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"), )