Builtins module for a different python version

I’m making a code analysis tool which is capable of specifying the Python version, which may be different from the version the tool is running on.
If I see an identifier that might be a builtin, I want to examine the builtins (or builtin) module for the specified python version.
Any suggestions?

One possibility is to get the typeshed stub file (stdlib/builtins.pyi or stdlib/@python2/__builtin__.pyi) and then parse it into an AST, then analyze that. The stub has several if sys.version_info ...: statements that need to be evaluated.
Is there a tool somewhere that will do all this for me, and basically give me the type information for each module level name for the given python version? I could copy some code from mypy for both py2 and py3 targets. But is there anything else?

You could take a look at GitHub - JelleZijlstra/typeshed_client: Experimental package for retrieving information from typeshed (I don’t know if it does precisely what you’re looking for; I haven’t really played with it. @Jelle will be able to tell you more :slight_smile: )

Yes, typeshed_client should be able to help here. Example:

In [10]: print(sorted(name for name, info in typeshed_client.get_stub_names("builtins", search_context=typeshed_client.get_search_context(version=(3, 11))).items() if info.is_export
    ...: ed))
['ArithmeticError', 'AssertionError', 'AttributeError', 'BaseException', 'BaseExceptionGroup', 'BlockingIOError', 'BrokenPipeError', 'BufferError', 'BytesWarning', 'ChildProcessError', 'ConnectionAbortedError', 'ConnectionError', 'ConnectionRefusedError', 'ConnectionResetError', 'DeprecationWarning', 'EOFError', 'Ellipsis', 'EncodingWarning', 'EnvironmentError', 'Exception', 'ExceptionGroup', 'FileExistsError', 'FileNotFoundError', 'FloatingPointError', 'FutureWarning', 'GeneratorExit', 'IOError', 'ImportError', 'ImportWarning', 'IndentationError', 'IndexError', 'InterruptedError', 'IsADirectoryError', 'KeyError', 'KeyboardInterrupt', 'LookupError', 'MemoryError', 'ModuleNotFoundError', 'NameError', 'NotADirectoryError', 'NotImplemented', 'NotImplementedError', 'OSError', 'OverflowError', 'PendingDeprecationWarning', 'PermissionError', 'ProcessLookupError', 'RecursionError', 'ReferenceError', 'ResourceWarning', 'RuntimeError', 'RuntimeWarning', 'StopAsyncIteration', 'StopIteration', 'SyntaxError', 'SyntaxWarning', 'SystemError', 'SystemExit', 'TabError', 'TimeoutError', 'TypeError', 'UnboundLocalError', 'UnicodeDecodeError', 'UnicodeEncodeError', 'UnicodeError', 'UnicodeTranslateError', 'UnicodeWarning', 'UserWarning', 'ValueError', 'Warning', 'ZeroDivisionError', 'abs', 'aiter', 'all', 'anext', 'any', 'ascii', 'bin', 'bool', 'breakpoint', 'bytearray', 'bytes', 'callable', 'chr', 'classmethod', 'compile', 'complex', 'copyright', 'credits', 'delattr', 'dict', 'dir', 'divmod', 'ellipsis', 'enumerate', 'eval', 'exec', 'exit', 'filter', 'float', 'format', 'frozenset', 'function', 'getattr', 'globals', 'hasattr', 'hash', 'help', 'hex', 'id', 'input', 'int', 'isinstance', 'issubclass', 'iter', 'len', 'license', 'list', 'locals', 'map', 'max', 'memoryview', 'min', 'next', 'object', 'oct', 'open', 'ord', 'pow', 'print', 'property', 'quit', 'range', 'repr', 'reversed', 'round', 'set', 'setattr', 'slice', 'sorted', 'staticmethod', 'str', 'sum', 'super', 'tuple', 'type', 'vars', 'zip']

In [11]: print(sorted(name for name, info in typeshed_client.get_stub_names("builtins", search_context=typeshed_client.get_search_context(version=(3, 6))).items() if info.is_exporte
    ...: d))
['ArithmeticError', 'AssertionError', 'AttributeError', 'BaseException', 'BlockingIOError', 'BrokenPipeError', 'BufferError', 'BytesWarning', 'ChildProcessError', 'ConnectionAbortedError', 'ConnectionError', 'ConnectionRefusedError', 'ConnectionResetError', 'DeprecationWarning', 'EOFError', 'Ellipsis', 'EnvironmentError', 'Exception', 'FileExistsError', 'FileNotFoundError', 'FloatingPointError', 'FutureWarning', 'GeneratorExit', 'IOError', 'ImportError', 'ImportWarning', 'IndentationError', 'IndexError', 'InterruptedError', 'IsADirectoryError', 'KeyError', 'KeyboardInterrupt', 'LookupError', 'MemoryError', 'ModuleNotFoundError', 'NameError', 'NotADirectoryError', 'NotImplemented', 'NotImplementedError', 'OSError', 'OverflowError', 'PendingDeprecationWarning', 'PermissionError', 'ProcessLookupError', 'RecursionError', 'ReferenceError', 'ResourceWarning', 'RuntimeError', 'RuntimeWarning', 'StopAsyncIteration', 'StopIteration', 'SyntaxError', 'SyntaxWarning', 'SystemError', 'SystemExit', 'TabError', 'TimeoutError', 'TypeError', 'UnboundLocalError', 'UnicodeDecodeError', 'UnicodeEncodeError', 'UnicodeError', 'UnicodeTranslateError', 'UnicodeWarning', 'UserWarning', 'ValueError', 'Warning', 'ZeroDivisionError', 'abs', 'all', 'any', 'ascii', 'bin', 'bool', 'bytearray', 'bytes', 'callable', 'chr', 'classmethod', 'compile', 'complex', 'copyright', 'credits', 'delattr', 'dict', 'dir', 'divmod', 'ellipsis', 'enumerate', 'eval', 'exec', 'exit', 'filter', 'float', 'format', 'frozenset', 'function', 'getattr', 'globals', 'hasattr', 'hash', 'help', 'hex', 'id', 'input', 'int', 'isinstance', 'issubclass', 'iter', 'len', 'license', 'list', 'locals', 'map', 'max', 'memoryview', 'min', 'next', 'object', 'oct', 'open', 'ord', 'pow', 'print', 'property', 'quit', 'range', 'repr', 'reversed', 'round', 'set', 'setattr', 'slice', 'sorted', 'staticmethod', 'str', 'sum', 'super', 'tuple', 'type', 'vars', 'zip']

This is based on the typeshed stubs, so it’s not precise for versions that are no longer supported by typeshed (e.g., 3.5).

1 Like

I am surprised that you are bothering with Python 2. Do you also support Python 1.x? Python 2 is likewise obsolete.

You could try launching the target Python interpreter in a subprocess, import the builtins, and grab the list of builtins using dir() or vars().

I’m confident that will work for any installed Python, including non-CPython implementations. (Tested on Jython, IronPython, MicroPython and PyPy.)

Otherwise, you could keep your own list, built from the docs. If you start with Python 1.0, there are (so far) only 27 versions to track, which mostly changes slowly. If you start with Python 2.7, that makes only 13 so far.

You could track changes to builtins rather than keep multiple redundant lists. E.g. start with the builtins for Python 3.0, then keep a list of additions and removals for each version since then.

That would mean that your tool would only be able to look backwards, to older Python versions, not forwards, to newer ones.