add type annotations to mesonmain

An oddity: sys.stdout is statically defined as type TextIO instead of
TextIOWrapper, and thus doesn't have a .reconfigure method. This is
because they expect people to override sys.stdout with other objects,
which we do not do. Instead, assume it is always correct.

There are two final errors due to metaprogramming:
```
mesonbuild/mesonmain.py:196:13: error: Returning Any from function declared to return "int"  [no-any-return]
mesonbuild/mesonmain.py:225:9: error: Returning Any from function declared to return "int"  [no-any-return]
```
pull/12839/head
Eli Schwartz 1 year ago
parent 4e83675bf8
commit fc41fd3542
No known key found for this signature in database
GPG Key ID: CEB167EFB5722BD6
  1. 38
      mesonbuild/mesonmain.py
  2. 3
      mesonbuild/rewriter.py

@ -15,11 +15,12 @@ import os.path
import platform
import importlib
import argparse
import typing as T
from .utils.core import MesonException, MesonBugException
from . import mlog
def errorhandler(e, command):
def errorhandler(e: Exception, command: str) -> int:
import traceback
if isinstance(e, MesonException):
mlog.exception(e)
@ -43,8 +44,8 @@ def errorhandler(e, command):
if command == 'runpython':
return 2
elif isinstance(e, OSError):
mlog.exception("Unhandled python OSError. This is probably not a Meson bug, "
"but an issue with your build environment.")
mlog.exception(Exception("Unhandled python OSError. This is probably not a Meson bug, "
"but an issue with your build environment."))
return e.errno
else: # Exception
msg = 'Unhandled python exception'
@ -58,7 +59,7 @@ def errorhandler(e, command):
# Note: when adding arguments, please also add them to the completion
# scripts in $MESONSRC/data/shell-completions/
class CommandLineParser:
def __init__(self):
def __init__(self) -> None:
# only import these once we do full argparse processing
from . import mconf, mdist, minit, minstall, mintro, msetup, mtest, rewriter, msubprojects, munstable_coredata, mcompile, mdevenv
from .scripts import env2mfile
@ -68,8 +69,8 @@ class CommandLineParser:
self.term_width = shutil.get_terminal_size().columns
self.formatter = lambda prog: argparse.HelpFormatter(prog, max_help_position=int(self.term_width / 2), width=self.term_width)
self.commands = {}
self.hidden_commands = []
self.commands: T.Dict[str, argparse.ArgumentParser] = {}
self.hidden_commands: T.List[str] = []
self.parser = argparse.ArgumentParser(prog='meson', formatter_class=self.formatter)
self.subparsers = self.parser.add_subparsers(title='Commands', dest='command',
description='If no command is specified it defaults to setup command.')
@ -109,7 +110,8 @@ class CommandLineParser:
self.add_command('unstable-coredata', munstable_coredata.add_arguments, munstable_coredata.run,
help_msg=argparse.SUPPRESS)
def add_command(self, name, add_arguments_func, run_func, help_msg, aliases=None):
def add_command(self, name: str, add_arguments_func: T.Callable[[argparse.ArgumentParser], None],
run_func: T.Callable[[argparse.Namespace], int], help_msg: str, aliases: T.List[str] = None) -> None:
aliases = aliases or []
# FIXME: Cannot have hidden subparser:
# https://bugs.python.org/issue22848
@ -123,13 +125,13 @@ class CommandLineParser:
for i in [name] + aliases:
self.commands[i] = p
def add_runpython_arguments(self, parser: argparse.ArgumentParser):
def add_runpython_arguments(self, parser: argparse.ArgumentParser) -> None:
parser.add_argument('-c', action='store_true', dest='eval_arg', default=False)
parser.add_argument('--version', action='version', version=platform.python_version())
parser.add_argument('script_file')
parser.add_argument('script_args', nargs=argparse.REMAINDER)
def run_runpython_command(self, options):
def run_runpython_command(self, options: argparse.Namespace) -> int:
sys.argv[1:] = options.script_args
if options.eval_arg:
exec(options.script_file)
@ -139,17 +141,17 @@ class CommandLineParser:
runpy.run_path(options.script_file, run_name='__main__')
return 0
def add_help_arguments(self, parser):
def add_help_arguments(self, parser: argparse.ArgumentParser) -> None:
parser.add_argument('command', nargs='?', choices=list(self.commands.keys()))
def run_help_command(self, options):
def run_help_command(self, options: argparse.Namespace) -> int:
if options.command:
self.commands[options.command].print_help()
else:
self.parser.print_help()
return 0
def run(self, args):
def run(self, args: T.List[str]) -> int:
implicit_setup_command_notice = False
# If first arg is not a known command, assume user wants to run the setup
# command.
@ -193,7 +195,7 @@ class CommandLineParser:
'Meson will require Python 3.7 or newer', fatal=False)
mlog.shutdown()
def run_script_command(script_name, script_args):
def run_script_command(script_name: str, script_args: T.List[str]) -> int:
# Map script name to module name for those that doesn't match
script_map = {'exe': 'meson_exe',
'install': 'meson_install',
@ -216,16 +218,16 @@ def run_script_command(script_name, script_args):
mlog.exception(e)
return 1
def ensure_stdout_accepts_unicode():
def ensure_stdout_accepts_unicode() -> None:
if sys.stdout.encoding and not sys.stdout.encoding.upper().startswith('UTF-'):
sys.stdout.reconfigure(errors='surrogateescape')
sys.stdout.reconfigure(errors='surrogateescape') # type: ignore[attr-defined]
def set_meson_command(mainfile):
def set_meson_command(mainfile: str) -> None:
# Set the meson command that will be used to run scripts and so on
from . import mesonlib
mesonlib.set_meson_command(mainfile)
def run(original_args, mainfile):
def run(original_args: T.List[str], mainfile: str) -> int:
if os.environ.get('MESON_SHOW_DEPRECATIONS'):
# workaround for https://bugs.python.org/issue34624
import warnings
@ -274,7 +276,7 @@ def run(original_args, mainfile):
set_meson_command(mainfile)
return CommandLineParser().run(args)
def main():
def main() -> int:
# Always resolve the command path so Ninja can find it for regen, tests, etc.
if 'meson.exe' in sys.executable:
assert os.path.isabs(sys.executable)

@ -18,6 +18,7 @@ import json, os, re, sys
import typing as T
if T.TYPE_CHECKING:
from argparse import ArgumentParser, HelpFormatter
from .mparser import BaseNode
class RewriterException(MesonException):
@ -25,7 +26,7 @@ class RewriterException(MesonException):
# Note: when adding arguments, please also add them to the completion
# scripts in $MESONSRC/data/shell-completions/
def add_arguments(parser, formatter):
def add_arguments(parser: ArgumentParser, formatter: T.Callable[[str], HelpFormatter]) -> None:
parser.add_argument('-s', '--sourcedir', type=str, default='.', metavar='SRCDIR', help='Path to source directory.')
parser.add_argument('-V', '--verbose', action='store_true', default=False, help='Enable verbose output')
parser.add_argument('-S', '--skip-errors', dest='skip', action='store_true', default=False, help='Skip errors instead of aborting')

Loading…
Cancel
Save