2121# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
2222# THE SOFTWARE.
2323
24+ # To gradually migrate to mypy we aren't setting these globally yet
25+ # mypy: disallow_untyped_defs=True
26+ # mypy: disallow_untyped_calls=True
27+
2428"""
2529Module to handle command line argument parsing, for all front-ends.
2630"""
2731
2832import argparse
29- from typing import Tuple
33+ from typing import Tuple ,List ,Optional ,NoReturn ,Callable
34+ import code
3035import curtsies
3136import cwcwidth
3237import greenlet
@@ -50,11 +55,11 @@ class ArgumentParserFailed(ValueError):
5055
5156
5257class RaisingArgumentParser (argparse .ArgumentParser ):
53- def error (self ,msg ) :
58+ def error (self ,msg : str ) -> NoReturn :
5459raise ArgumentParserFailed ()
5560
5661
57- def version_banner (base = "bpython" )-> str :
62+ def version_banner (base : str = "bpython" )-> str :
5863return _ ("{} version {} on top of Python {} {}" ).format (
5964base ,
6065__version__ ,
@@ -67,7 +72,14 @@ def copyright_banner() -> str:
6772return _ ("{} See AUTHORS.rst for details." ).format (__copyright__ )
6873
6974
70- def parse (args ,extras = None ,ignore_stdin = False )-> Tuple :
75+ Options = Tuple [str ,str ,Callable [[argparse ._ArgumentGroup ],None ]]
76+
77+
78+ def parse (
79+ args :Optional [List [str ]],
80+ extras :Options = None ,
81+ ignore_stdin :bool = False ,
82+ )-> Tuple :
7183"""Receive an argument list - if None, use sys.argv - parse all args and
7284 take appropriate action. Also receive optional extra argument: this should
7385 be a tuple of (title, description, callback)
@@ -214,7 +226,9 @@ def callback(group):
214226return Config (options .config ),options ,options .args
215227
216228
217- def exec_code (interpreter ,args ):
229+ def exec_code (
230+ interpreter :code .InteractiveInterpreter ,args :List [str ]
231+ )-> None :
218232"""
219233 Helper to execute code in a given interpreter, e.g. to implement the behavior of python3 [-i] file.py
220234
@@ -230,9 +244,10 @@ def exec_code(interpreter, args):
230244old_argv ,sys .argv = sys .argv ,args
231245sys .path .insert (0 ,os .path .abspath (os .path .dirname (args [0 ])))
232246spec = importlib .util .spec_from_loader ("__console__" ,loader = None )
247+ assert spec
233248mod = importlib .util .module_from_spec (spec )
234249sys .modules ["__console__" ]= mod
235- interpreter .locals .update (mod .__dict__ )
236- interpreter .locals ["__file__" ]= args [0 ]
250+ interpreter .locals .update (mod .__dict__ )# type: ignore # TODO use a more specific type that has a .locals attribute
251+ interpreter .locals ["__file__" ]= args [0 ]# type: ignore # TODO use a more specific type that has a .locals attribute
237252interpreter .runsource (source ,args [0 ],"exec" )
238253sys .argv = old_argv