17db96d56Sopenharmony_ciimport logging
27db96d56Sopenharmony_ciimport sys
37db96d56Sopenharmony_ci
47db96d56Sopenharmony_cifrom c_common.fsutil import expand_filenames, iter_files_by_suffix
57db96d56Sopenharmony_cifrom c_common.scriptutil import (
67db96d56Sopenharmony_ci    VERBOSITY,
77db96d56Sopenharmony_ci    add_verbosity_cli,
87db96d56Sopenharmony_ci    add_traceback_cli,
97db96d56Sopenharmony_ci    add_commands_cli,
107db96d56Sopenharmony_ci    add_kind_filtering_cli,
117db96d56Sopenharmony_ci    add_files_cli,
127db96d56Sopenharmony_ci    add_progress_cli,
137db96d56Sopenharmony_ci    main_for_filenames,
147db96d56Sopenharmony_ci    process_args_by_key,
157db96d56Sopenharmony_ci    configure_logger,
167db96d56Sopenharmony_ci    get_prog,
177db96d56Sopenharmony_ci)
187db96d56Sopenharmony_cifrom c_parser.info import KIND
197db96d56Sopenharmony_ciimport c_parser.__main__ as c_parser
207db96d56Sopenharmony_ciimport c_analyzer.__main__ as c_analyzer
217db96d56Sopenharmony_ciimport c_analyzer as _c_analyzer
227db96d56Sopenharmony_cifrom c_analyzer.info import UNKNOWN
237db96d56Sopenharmony_cifrom . import _analyzer, _capi, _files, _parser, REPO_ROOT
247db96d56Sopenharmony_ci
257db96d56Sopenharmony_ci
267db96d56Sopenharmony_cilogger = logging.getLogger(__name__)
277db96d56Sopenharmony_ci
287db96d56Sopenharmony_ci
297db96d56Sopenharmony_cidef _resolve_filenames(filenames):
307db96d56Sopenharmony_ci    if filenames:
317db96d56Sopenharmony_ci        resolved = (_files.resolve_filename(f) for f in filenames)
327db96d56Sopenharmony_ci    else:
337db96d56Sopenharmony_ci        resolved = _files.iter_filenames()
347db96d56Sopenharmony_ci    return resolved
357db96d56Sopenharmony_ci
367db96d56Sopenharmony_ci
377db96d56Sopenharmony_ci#######################################
387db96d56Sopenharmony_ci# the formats
397db96d56Sopenharmony_ci
407db96d56Sopenharmony_cidef fmt_summary(analysis):
417db96d56Sopenharmony_ci    # XXX Support sorting and grouping.
427db96d56Sopenharmony_ci    supported = []
437db96d56Sopenharmony_ci    unsupported = []
447db96d56Sopenharmony_ci    for item in analysis:
457db96d56Sopenharmony_ci        if item.supported:
467db96d56Sopenharmony_ci            supported.append(item)
477db96d56Sopenharmony_ci        else:
487db96d56Sopenharmony_ci            unsupported.append(item)
497db96d56Sopenharmony_ci    total = 0
507db96d56Sopenharmony_ci
517db96d56Sopenharmony_ci    def section(name, groupitems):
527db96d56Sopenharmony_ci        nonlocal total
537db96d56Sopenharmony_ci        items, render = c_analyzer.build_section(name, groupitems,
547db96d56Sopenharmony_ci                                                 relroot=REPO_ROOT)
557db96d56Sopenharmony_ci        yield from render()
567db96d56Sopenharmony_ci        total += len(items)
577db96d56Sopenharmony_ci
587db96d56Sopenharmony_ci    yield ''
597db96d56Sopenharmony_ci    yield '===================='
607db96d56Sopenharmony_ci    yield 'supported'
617db96d56Sopenharmony_ci    yield '===================='
627db96d56Sopenharmony_ci
637db96d56Sopenharmony_ci    yield from section('types', supported)
647db96d56Sopenharmony_ci    yield from section('variables', supported)
657db96d56Sopenharmony_ci
667db96d56Sopenharmony_ci    yield ''
677db96d56Sopenharmony_ci    yield '===================='
687db96d56Sopenharmony_ci    yield 'unsupported'
697db96d56Sopenharmony_ci    yield '===================='
707db96d56Sopenharmony_ci
717db96d56Sopenharmony_ci    yield from section('types', unsupported)
727db96d56Sopenharmony_ci    yield from section('variables', unsupported)
737db96d56Sopenharmony_ci
747db96d56Sopenharmony_ci    yield ''
757db96d56Sopenharmony_ci    yield f'grand total: {total}'
767db96d56Sopenharmony_ci
777db96d56Sopenharmony_ci
787db96d56Sopenharmony_ci#######################################
797db96d56Sopenharmony_ci# the checks
807db96d56Sopenharmony_ci
817db96d56Sopenharmony_ciCHECKS = dict(c_analyzer.CHECKS, **{
827db96d56Sopenharmony_ci    'globals': _analyzer.check_globals,
837db96d56Sopenharmony_ci})
847db96d56Sopenharmony_ci
857db96d56Sopenharmony_ci#######################################
867db96d56Sopenharmony_ci# the commands
877db96d56Sopenharmony_ci
887db96d56Sopenharmony_ciFILES_KWARGS = dict(excluded=_parser.EXCLUDED, nargs='*')
897db96d56Sopenharmony_ci
907db96d56Sopenharmony_ci
917db96d56Sopenharmony_cidef _cli_parse(parser):
927db96d56Sopenharmony_ci    process_output = c_parser.add_output_cli(parser)
937db96d56Sopenharmony_ci    process_kind = add_kind_filtering_cli(parser)
947db96d56Sopenharmony_ci    process_preprocessor = c_parser.add_preprocessor_cli(
957db96d56Sopenharmony_ci        parser,
967db96d56Sopenharmony_ci        get_preprocessor=_parser.get_preprocessor,
977db96d56Sopenharmony_ci    )
987db96d56Sopenharmony_ci    process_files = add_files_cli(parser, **FILES_KWARGS)
997db96d56Sopenharmony_ci    return [
1007db96d56Sopenharmony_ci        process_output,
1017db96d56Sopenharmony_ci        process_kind,
1027db96d56Sopenharmony_ci        process_preprocessor,
1037db96d56Sopenharmony_ci        process_files,
1047db96d56Sopenharmony_ci    ]
1057db96d56Sopenharmony_ci
1067db96d56Sopenharmony_ci
1077db96d56Sopenharmony_cidef cmd_parse(filenames=None, **kwargs):
1087db96d56Sopenharmony_ci    filenames = _resolve_filenames(filenames)
1097db96d56Sopenharmony_ci    if 'get_file_preprocessor' not in kwargs:
1107db96d56Sopenharmony_ci        kwargs['get_file_preprocessor'] = _parser.get_preprocessor()
1117db96d56Sopenharmony_ci    c_parser.cmd_parse(
1127db96d56Sopenharmony_ci        filenames,
1137db96d56Sopenharmony_ci        relroot=REPO_ROOT,
1147db96d56Sopenharmony_ci        file_maxsizes=_parser.MAX_SIZES,
1157db96d56Sopenharmony_ci        **kwargs
1167db96d56Sopenharmony_ci    )
1177db96d56Sopenharmony_ci
1187db96d56Sopenharmony_ci
1197db96d56Sopenharmony_cidef _cli_check(parser, **kwargs):
1207db96d56Sopenharmony_ci    return c_analyzer._cli_check(parser, CHECKS, **kwargs, **FILES_KWARGS)
1217db96d56Sopenharmony_ci
1227db96d56Sopenharmony_ci
1237db96d56Sopenharmony_cidef cmd_check(filenames=None, **kwargs):
1247db96d56Sopenharmony_ci    filenames = _resolve_filenames(filenames)
1257db96d56Sopenharmony_ci    kwargs['get_file_preprocessor'] = _parser.get_preprocessor(log_err=print)
1267db96d56Sopenharmony_ci    c_analyzer.cmd_check(
1277db96d56Sopenharmony_ci        filenames,
1287db96d56Sopenharmony_ci        relroot=REPO_ROOT,
1297db96d56Sopenharmony_ci        _analyze=_analyzer.analyze,
1307db96d56Sopenharmony_ci        _CHECKS=CHECKS,
1317db96d56Sopenharmony_ci        file_maxsizes=_parser.MAX_SIZES,
1327db96d56Sopenharmony_ci        **kwargs
1337db96d56Sopenharmony_ci    )
1347db96d56Sopenharmony_ci
1357db96d56Sopenharmony_ci
1367db96d56Sopenharmony_cidef cmd_analyze(filenames=None, **kwargs):
1377db96d56Sopenharmony_ci    formats = dict(c_analyzer.FORMATS)
1387db96d56Sopenharmony_ci    formats['summary'] = fmt_summary
1397db96d56Sopenharmony_ci    filenames = _resolve_filenames(filenames)
1407db96d56Sopenharmony_ci    kwargs['get_file_preprocessor'] = _parser.get_preprocessor(log_err=print)
1417db96d56Sopenharmony_ci    c_analyzer.cmd_analyze(
1427db96d56Sopenharmony_ci        filenames,
1437db96d56Sopenharmony_ci        relroot=REPO_ROOT,
1447db96d56Sopenharmony_ci        _analyze=_analyzer.analyze,
1457db96d56Sopenharmony_ci        formats=formats,
1467db96d56Sopenharmony_ci        file_maxsizes=_parser.MAX_SIZES,
1477db96d56Sopenharmony_ci        **kwargs
1487db96d56Sopenharmony_ci    )
1497db96d56Sopenharmony_ci
1507db96d56Sopenharmony_ci
1517db96d56Sopenharmony_cidef _cli_data(parser):
1527db96d56Sopenharmony_ci    filenames = False
1537db96d56Sopenharmony_ci    known = True
1547db96d56Sopenharmony_ci    return c_analyzer._cli_data(parser, filenames, known)
1557db96d56Sopenharmony_ci
1567db96d56Sopenharmony_ci
1577db96d56Sopenharmony_cidef cmd_data(datacmd, **kwargs):
1587db96d56Sopenharmony_ci    formats = dict(c_analyzer.FORMATS)
1597db96d56Sopenharmony_ci    formats['summary'] = fmt_summary
1607db96d56Sopenharmony_ci    filenames = (file
1617db96d56Sopenharmony_ci                 for file in _resolve_filenames(None)
1627db96d56Sopenharmony_ci                 if file not in _parser.EXCLUDED)
1637db96d56Sopenharmony_ci    kwargs['get_file_preprocessor'] = _parser.get_preprocessor(log_err=print)
1647db96d56Sopenharmony_ci    if datacmd == 'show':
1657db96d56Sopenharmony_ci        types = _analyzer.read_known()
1667db96d56Sopenharmony_ci        results = []
1677db96d56Sopenharmony_ci        for decl, info in types.items():
1687db96d56Sopenharmony_ci            if info is UNKNOWN:
1697db96d56Sopenharmony_ci                if decl.kind in (KIND.STRUCT, KIND.UNION):
1707db96d56Sopenharmony_ci                    extra = {'unsupported': ['type unknown'] * len(decl.members)}
1717db96d56Sopenharmony_ci                else:
1727db96d56Sopenharmony_ci                    extra = {'unsupported': ['type unknown']}
1737db96d56Sopenharmony_ci                info = (info, extra)
1747db96d56Sopenharmony_ci            results.append((decl, info))
1757db96d56Sopenharmony_ci            if decl.shortkey == 'struct _object':
1767db96d56Sopenharmony_ci                tempinfo = info
1777db96d56Sopenharmony_ci        known = _analyzer.Analysis.from_results(results)
1787db96d56Sopenharmony_ci        analyze = None
1797db96d56Sopenharmony_ci    elif datacmd == 'dump':
1807db96d56Sopenharmony_ci        known = _analyzer.KNOWN_FILE
1817db96d56Sopenharmony_ci        def analyze(files, **kwargs):
1827db96d56Sopenharmony_ci            decls = []
1837db96d56Sopenharmony_ci            for decl in _analyzer.iter_decls(files, **kwargs):
1847db96d56Sopenharmony_ci                if not KIND.is_type_decl(decl.kind):
1857db96d56Sopenharmony_ci                    continue
1867db96d56Sopenharmony_ci                if not decl.filename.endswith('.h'):
1877db96d56Sopenharmony_ci                    if decl.shortkey not in _analyzer.KNOWN_IN_DOT_C:
1887db96d56Sopenharmony_ci                        continue
1897db96d56Sopenharmony_ci                decls.append(decl)
1907db96d56Sopenharmony_ci            results = _c_analyzer.analyze_decls(
1917db96d56Sopenharmony_ci                decls,
1927db96d56Sopenharmony_ci                known={},
1937db96d56Sopenharmony_ci                analyze_resolved=_analyzer.analyze_resolved,
1947db96d56Sopenharmony_ci            )
1957db96d56Sopenharmony_ci            return _analyzer.Analysis.from_results(results)
1967db96d56Sopenharmony_ci    else:  # check
1977db96d56Sopenharmony_ci        known = _analyzer.read_known()
1987db96d56Sopenharmony_ci        def analyze(files, **kwargs):
1997db96d56Sopenharmony_ci            return _analyzer.iter_decls(files, **kwargs)
2007db96d56Sopenharmony_ci    extracolumns = None
2017db96d56Sopenharmony_ci    c_analyzer.cmd_data(
2027db96d56Sopenharmony_ci        datacmd,
2037db96d56Sopenharmony_ci        filenames,
2047db96d56Sopenharmony_ci        known,
2057db96d56Sopenharmony_ci        _analyze=analyze,
2067db96d56Sopenharmony_ci        formats=formats,
2077db96d56Sopenharmony_ci        extracolumns=extracolumns,
2087db96d56Sopenharmony_ci        relroot=REPO_ROOT,
2097db96d56Sopenharmony_ci        **kwargs
2107db96d56Sopenharmony_ci    )
2117db96d56Sopenharmony_ci
2127db96d56Sopenharmony_ci
2137db96d56Sopenharmony_cidef _cli_capi(parser):
2147db96d56Sopenharmony_ci    parser.add_argument('--levels', action='append', metavar='LEVEL[,...]')
2157db96d56Sopenharmony_ci    parser.add_argument(f'--public', dest='levels',
2167db96d56Sopenharmony_ci                        action='append_const', const='public')
2177db96d56Sopenharmony_ci    parser.add_argument(f'--no-public', dest='levels',
2187db96d56Sopenharmony_ci                        action='append_const', const='no-public')
2197db96d56Sopenharmony_ci    for level in _capi.LEVELS:
2207db96d56Sopenharmony_ci        parser.add_argument(f'--{level}', dest='levels',
2217db96d56Sopenharmony_ci                            action='append_const', const=level)
2227db96d56Sopenharmony_ci    def process_levels(args, *, argv=None):
2237db96d56Sopenharmony_ci        levels = []
2247db96d56Sopenharmony_ci        for raw in args.levels or ():
2257db96d56Sopenharmony_ci            for level in raw.replace(',', ' ').strip().split():
2267db96d56Sopenharmony_ci                if level == 'public':
2277db96d56Sopenharmony_ci                    levels.append('stable')
2287db96d56Sopenharmony_ci                    levels.append('cpython')
2297db96d56Sopenharmony_ci                elif level == 'no-public':
2307db96d56Sopenharmony_ci                    levels.append('private')
2317db96d56Sopenharmony_ci                    levels.append('internal')
2327db96d56Sopenharmony_ci                elif level in _capi.LEVELS:
2337db96d56Sopenharmony_ci                    levels.append(level)
2347db96d56Sopenharmony_ci                else:
2357db96d56Sopenharmony_ci                    parser.error(f'expected LEVEL to be one of {sorted(_capi.LEVELS)}, got {level!r}')
2367db96d56Sopenharmony_ci        args.levels = set(levels)
2377db96d56Sopenharmony_ci
2387db96d56Sopenharmony_ci    parser.add_argument('--kinds', action='append', metavar='KIND[,...]')
2397db96d56Sopenharmony_ci    for kind in _capi.KINDS:
2407db96d56Sopenharmony_ci        parser.add_argument(f'--{kind}', dest='kinds',
2417db96d56Sopenharmony_ci                            action='append_const', const=kind)
2427db96d56Sopenharmony_ci    def process_kinds(args, *, argv=None):
2437db96d56Sopenharmony_ci        kinds = []
2447db96d56Sopenharmony_ci        for raw in args.kinds or ():
2457db96d56Sopenharmony_ci            for kind in raw.replace(',', ' ').strip().split():
2467db96d56Sopenharmony_ci                if kind in _capi.KINDS:
2477db96d56Sopenharmony_ci                    kinds.append(kind)
2487db96d56Sopenharmony_ci                else:
2497db96d56Sopenharmony_ci                    parser.error(f'expected KIND to be one of {sorted(_capi.KINDS)}, got {kind!r}')
2507db96d56Sopenharmony_ci        args.kinds = set(kinds)
2517db96d56Sopenharmony_ci
2527db96d56Sopenharmony_ci    parser.add_argument('--group-by', dest='groupby',
2537db96d56Sopenharmony_ci                        choices=['level', 'kind'])
2547db96d56Sopenharmony_ci
2557db96d56Sopenharmony_ci    parser.add_argument('--format', default='table')
2567db96d56Sopenharmony_ci    parser.add_argument('--summary', dest='format',
2577db96d56Sopenharmony_ci                        action='store_const', const='summary')
2587db96d56Sopenharmony_ci    def process_format(args, *, argv=None):
2597db96d56Sopenharmony_ci        orig = args.format
2607db96d56Sopenharmony_ci        args.format = _capi.resolve_format(args.format)
2617db96d56Sopenharmony_ci        if isinstance(args.format, str):
2627db96d56Sopenharmony_ci            if args.format not in _capi._FORMATS:
2637db96d56Sopenharmony_ci                parser.error(f'unsupported format {orig!r}')
2647db96d56Sopenharmony_ci
2657db96d56Sopenharmony_ci    parser.add_argument('--show-empty', dest='showempty', action='store_true')
2667db96d56Sopenharmony_ci    parser.add_argument('--no-show-empty', dest='showempty', action='store_false')
2677db96d56Sopenharmony_ci    parser.set_defaults(showempty=None)
2687db96d56Sopenharmony_ci
2697db96d56Sopenharmony_ci    # XXX Add --sort-by, --sort and --no-sort.
2707db96d56Sopenharmony_ci
2717db96d56Sopenharmony_ci    parser.add_argument('--ignore', dest='ignored', action='append')
2727db96d56Sopenharmony_ci    def process_ignored(args, *, argv=None):
2737db96d56Sopenharmony_ci        ignored = []
2747db96d56Sopenharmony_ci        for raw in args.ignored or ():
2757db96d56Sopenharmony_ci            ignored.extend(raw.replace(',', ' ').strip().split())
2767db96d56Sopenharmony_ci        args.ignored = ignored or None
2777db96d56Sopenharmony_ci
2787db96d56Sopenharmony_ci    parser.add_argument('filenames', nargs='*', metavar='FILENAME')
2797db96d56Sopenharmony_ci    process_progress = add_progress_cli(parser)
2807db96d56Sopenharmony_ci
2817db96d56Sopenharmony_ci    return [
2827db96d56Sopenharmony_ci        process_levels,
2837db96d56Sopenharmony_ci        process_kinds,
2847db96d56Sopenharmony_ci        process_format,
2857db96d56Sopenharmony_ci        process_ignored,
2867db96d56Sopenharmony_ci        process_progress,
2877db96d56Sopenharmony_ci    ]
2887db96d56Sopenharmony_ci
2897db96d56Sopenharmony_ci
2907db96d56Sopenharmony_cidef cmd_capi(filenames=None, *,
2917db96d56Sopenharmony_ci             levels=None,
2927db96d56Sopenharmony_ci             kinds=None,
2937db96d56Sopenharmony_ci             groupby='kind',
2947db96d56Sopenharmony_ci             format='table',
2957db96d56Sopenharmony_ci             showempty=None,
2967db96d56Sopenharmony_ci             ignored=None,
2977db96d56Sopenharmony_ci             track_progress=None,
2987db96d56Sopenharmony_ci             verbosity=VERBOSITY,
2997db96d56Sopenharmony_ci             **kwargs
3007db96d56Sopenharmony_ci             ):
3017db96d56Sopenharmony_ci    render = _capi.get_renderer(format)
3027db96d56Sopenharmony_ci
3037db96d56Sopenharmony_ci    filenames = _files.iter_header_files(filenames, levels=levels)
3047db96d56Sopenharmony_ci    #filenames = (file for file, _ in main_for_filenames(filenames))
3057db96d56Sopenharmony_ci    if track_progress:
3067db96d56Sopenharmony_ci        filenames = track_progress(filenames)
3077db96d56Sopenharmony_ci    items = _capi.iter_capi(filenames)
3087db96d56Sopenharmony_ci    if levels:
3097db96d56Sopenharmony_ci        items = (item for item in items if item.level in levels)
3107db96d56Sopenharmony_ci    if kinds:
3117db96d56Sopenharmony_ci        items = (item for item in items if item.kind in kinds)
3127db96d56Sopenharmony_ci
3137db96d56Sopenharmony_ci    filter = _capi.resolve_filter(ignored)
3147db96d56Sopenharmony_ci    if filter:
3157db96d56Sopenharmony_ci        items = (item for item in items if filter(item, log=lambda msg: logger.log(1, msg)))
3167db96d56Sopenharmony_ci
3177db96d56Sopenharmony_ci    lines = render(
3187db96d56Sopenharmony_ci        items,
3197db96d56Sopenharmony_ci        groupby=groupby,
3207db96d56Sopenharmony_ci        showempty=showempty,
3217db96d56Sopenharmony_ci        verbose=verbosity > VERBOSITY,
3227db96d56Sopenharmony_ci    )
3237db96d56Sopenharmony_ci    print()
3247db96d56Sopenharmony_ci    for line in lines:
3257db96d56Sopenharmony_ci        print(line)
3267db96d56Sopenharmony_ci
3277db96d56Sopenharmony_ci
3287db96d56Sopenharmony_ci# We do not define any other cmd_*() handlers here,
3297db96d56Sopenharmony_ci# favoring those defined elsewhere.
3307db96d56Sopenharmony_ci
3317db96d56Sopenharmony_ciCOMMANDS = {
3327db96d56Sopenharmony_ci    'check': (
3337db96d56Sopenharmony_ci        'analyze and fail if the CPython source code has any problems',
3347db96d56Sopenharmony_ci        [_cli_check],
3357db96d56Sopenharmony_ci        cmd_check,
3367db96d56Sopenharmony_ci    ),
3377db96d56Sopenharmony_ci    'analyze': (
3387db96d56Sopenharmony_ci        'report on the state of the CPython source code',
3397db96d56Sopenharmony_ci        [(lambda p: c_analyzer._cli_analyze(p, **FILES_KWARGS))],
3407db96d56Sopenharmony_ci        cmd_analyze,
3417db96d56Sopenharmony_ci    ),
3427db96d56Sopenharmony_ci    'parse': (
3437db96d56Sopenharmony_ci        'parse the CPython source files',
3447db96d56Sopenharmony_ci        [_cli_parse],
3457db96d56Sopenharmony_ci        cmd_parse,
3467db96d56Sopenharmony_ci    ),
3477db96d56Sopenharmony_ci    'data': (
3487db96d56Sopenharmony_ci        'check/manage local data (e.g. known types, ignored vars, caches)',
3497db96d56Sopenharmony_ci        [_cli_data],
3507db96d56Sopenharmony_ci        cmd_data,
3517db96d56Sopenharmony_ci    ),
3527db96d56Sopenharmony_ci    'capi': (
3537db96d56Sopenharmony_ci        'inspect the C-API',
3547db96d56Sopenharmony_ci        [_cli_capi],
3557db96d56Sopenharmony_ci        cmd_capi,
3567db96d56Sopenharmony_ci    ),
3577db96d56Sopenharmony_ci}
3587db96d56Sopenharmony_ci
3597db96d56Sopenharmony_ci
3607db96d56Sopenharmony_ci#######################################
3617db96d56Sopenharmony_ci# the script
3627db96d56Sopenharmony_ci
3637db96d56Sopenharmony_cidef parse_args(argv=sys.argv[1:], prog=None, *, subset=None):
3647db96d56Sopenharmony_ci    import argparse
3657db96d56Sopenharmony_ci    parser = argparse.ArgumentParser(
3667db96d56Sopenharmony_ci        prog=prog or get_prog(),
3677db96d56Sopenharmony_ci    )
3687db96d56Sopenharmony_ci
3697db96d56Sopenharmony_ci#    if subset == 'check' or subset == ['check']:
3707db96d56Sopenharmony_ci#        if checks is not None:
3717db96d56Sopenharmony_ci#            commands = dict(COMMANDS)
3727db96d56Sopenharmony_ci#            commands['check'] = list(commands['check'])
3737db96d56Sopenharmony_ci#            cli = commands['check'][1][0]
3747db96d56Sopenharmony_ci#            commands['check'][1][0] = (lambda p: cli(p, checks=checks))
3757db96d56Sopenharmony_ci    processors = add_commands_cli(
3767db96d56Sopenharmony_ci        parser,
3777db96d56Sopenharmony_ci        commands=COMMANDS,
3787db96d56Sopenharmony_ci        commonspecs=[
3797db96d56Sopenharmony_ci            add_verbosity_cli,
3807db96d56Sopenharmony_ci            add_traceback_cli,
3817db96d56Sopenharmony_ci        ],
3827db96d56Sopenharmony_ci        subset=subset,
3837db96d56Sopenharmony_ci    )
3847db96d56Sopenharmony_ci
3857db96d56Sopenharmony_ci    args = parser.parse_args(argv)
3867db96d56Sopenharmony_ci    ns = vars(args)
3877db96d56Sopenharmony_ci
3887db96d56Sopenharmony_ci    cmd = ns.pop('cmd')
3897db96d56Sopenharmony_ci
3907db96d56Sopenharmony_ci    verbosity, traceback_cm = process_args_by_key(
3917db96d56Sopenharmony_ci        args,
3927db96d56Sopenharmony_ci        argv,
3937db96d56Sopenharmony_ci        processors[cmd],
3947db96d56Sopenharmony_ci        ['verbosity', 'traceback_cm'],
3957db96d56Sopenharmony_ci    )
3967db96d56Sopenharmony_ci    if cmd != 'parse':
3977db96d56Sopenharmony_ci        # "verbosity" is sent to the commands, so we put it back.
3987db96d56Sopenharmony_ci        args.verbosity = verbosity
3997db96d56Sopenharmony_ci
4007db96d56Sopenharmony_ci    return cmd, ns, verbosity, traceback_cm
4017db96d56Sopenharmony_ci
4027db96d56Sopenharmony_ci
4037db96d56Sopenharmony_cidef main(cmd, cmd_kwargs):
4047db96d56Sopenharmony_ci    try:
4057db96d56Sopenharmony_ci        run_cmd = COMMANDS[cmd][-1]
4067db96d56Sopenharmony_ci    except KeyError:
4077db96d56Sopenharmony_ci        raise ValueError(f'unsupported cmd {cmd!r}')
4087db96d56Sopenharmony_ci    run_cmd(**cmd_kwargs)
4097db96d56Sopenharmony_ci
4107db96d56Sopenharmony_ci
4117db96d56Sopenharmony_ciif __name__ == '__main__':
4127db96d56Sopenharmony_ci    cmd, cmd_kwargs, verbosity, traceback_cm = parse_args()
4137db96d56Sopenharmony_ci    configure_logger(verbosity)
4147db96d56Sopenharmony_ci    with traceback_cm:
4157db96d56Sopenharmony_ci        main(cmd, cmd_kwargs)
416