Source code for buildtest.main

"""Entry point for buildtest"""

import os
import shutil
import tempfile
import webbrowser

from rich.traceback import install

from buildtest.cli import BuildTestParser
from buildtest.cli.build import BuildTest, Tee
from buildtest.cli.buildspec import (
    BuildspecCache,
    buildspec_find,
    buildspec_maintainers,
    buildspec_validate_command,
    edit_buildspec_file,
    edit_buildspec_test,
    show_buildspecs,
    show_failed_buildspecs,
    summarize_buildspec_cache,
)
from buildtest.cli.cd import change_directory
from buildtest.cli.cdash import upload_test_cdash, view_cdash_project
from buildtest.cli.clean import clean
from buildtest.cli.commands import list_buildtest_commands
from buildtest.cli.compilers import compiler_cmd
from buildtest.cli.config import config_cmd
from buildtest.cli.debugreport import print_debug_report
from buildtest.cli.helpcolor import print_available_colors
from buildtest.cli.history import build_history
from buildtest.cli.info import buildtest_info
from buildtest.cli.inspect import (
    inspect_buildspec,
    inspect_by_name,
    inspect_list,
    inspect_query,
)
from buildtest.cli.path import path_cmd
from buildtest.cli.report import Report, report_cmd
from buildtest.cli.show import buildtest_show
from buildtest.cli.stats import stats_cmd
from buildtest.config import SiteConfiguration
from buildtest.defaults import (
    BUILDSPEC_CACHE_FILE,
    BUILDTEST_BUILDSPEC_DIR,
    BUILDTEST_EXECUTOR_DIR,
    BUILDTEST_LOGFILE,
    BUILDTEST_USER_HOME,
    console,
)
from buildtest.exceptions import BuildTestError
from buildtest.log import init_logfile
from buildtest.system import BuildTestSystem
from buildtest.tools.editor import set_editor
from buildtest.tools.stylecheck import run_style_checks
from buildtest.tools.tutorialexamples import generate_tutorial_examples
from buildtest.tools.unittests import run_unit_tests
from buildtest.utils.file import (
    create_dir,
    is_file,
    read_file,
    remove_file,
    resolve_path,
)
from buildtest.utils.tools import deep_get


[docs] def main(): """Entry point to buildtest.""" parser = BuildTestParser() args = parser.parse() system, configuration, buildtest_editor, report_file = setup(args) # print logfile if one specifies buildtest --view-log or buildtest --print-log if handle_log_viewing(args): return if args.listopts: print("\n".join(parser.retrieve_main_options())) return # print the available color options in a table format if buildtest --helpcolor is specified if args.helpcolor: print_available_colors() return # print full path to the lastlog file if buildtest --logpath is specified if args.logpath: console.print(BUILDTEST_LOGFILE) return # buildtest build command if args.subcommands in ["build", "bd"]: handle_build_command(args, configuration, report_file) # buildtest build history if args.subcommands in ["history", "hy"]: build_history(args) # implementation for 'buildtest buildspec find' elif args.subcommands in ["buildspec", "bc"]: handle_buildspec_command(args, configuration, report_file, buildtest_editor) # running buildtest inspect elif args.subcommands in ["inspect", "it"]: handle_inspect_command(args, configuration, report_file) elif args.subcommands in ["stats"]: stats_cmd(name=args.name, configuration=configuration, report_file=report_file) # running buildtest config elif args.subcommands in ["config", "cg"]: # running buildtest config compilers if args.config in ["compilers", "co"]: compiler_cmd(args, configuration) else: config_cmd( command_args=args, configuration=configuration, editor=buildtest_editor, system=system, ) # buildtest report elif args.subcommands in ["report", "rt"]: report_cmd(args, configuration=configuration, report_file=report_file) elif args.subcommands == "path": path_cmd( name=args.name, outfile=args.outfile, errfile=args.errfile, testpath=args.testpath, buildscript=args.buildscript, stagedir=args.stagedir, buildenv=args.buildenv, configuration=configuration, report_file=report_file, ) # running buildtest cdash elif args.subcommands == "cdash": handle_cdash_command(args, configuration, report_file) elif args.subcommands in ["show", "s"]: buildtest_show(command=args.command) elif args.subcommands == "clean": clean(configuration=configuration, yes=args.yes) elif args.subcommands == "cd": change_directory(args.test, configuration=configuration) elif args.subcommands == "docs": webbrowser.open("https://buildtest.readthedocs.io/") elif args.subcommands == "info": buildtest_info(configuration, system) elif args.subcommands in ["debug", "debugreport"]: print_debug_report(system, configuration) elif args.subcommands in ["unittests", "test"]: run_unit_tests( pytestopts=args.pytestopts, sourcefiles=args.sourcefiles, enable_coverage=args.coverage, ) elif args.subcommands == "tutorial-examples": generate_tutorial_examples( examples=args.examples, dryrun=args.dryrun, write=args.write, failfast=args.failfast, ) elif args.subcommands in ["stylecheck", "style"]: run_style_checks( no_black=args.no_black, no_isort=args.no_isort, no_pyflakes=args.no_pyflakes, apply_stylechecks=args.apply, ) elif args.subcommands in ["commands", "cmds"]: list_buildtest_commands(with_aliases=args.with_aliases)
[docs] def setup(args): """This function sets up the environment for buildtest. This function initializes logging, configuration, and system object. This function returns a tuple of system, configuration, buildtest_editor, and report_file. This function is called at the beginning of main() function. Args: args (argparse.Namespace): An argparse namespace object containing command line arguments Returns: Tuple: A tuple of system, configuration, buildtest_editor, and report_file """ install(show_locals=True) no_color = False # disable color if buildtest --no-color or BUILDTEST_COLOR=False is set if args.no_color or os.getenv("BUILDTEST_COLOR") == "False": no_color = True console.no_color = no_color if args.verbose: console.print("Coloring mode: ", "off" if no_color else "on") report_file = args.report if is_file(BUILDTEST_LOGFILE): remove_file(BUILDTEST_LOGFILE) logger = init_logfile(debug=args.debug, loglevel=args.loglevel) create_dir(BUILDTEST_USER_HOME) create_dir(BUILDTEST_EXECUTOR_DIR) create_dir(BUILDTEST_BUILDSPEC_DIR) # Create a build test system, and check requirements system = BuildTestSystem() if args.verbose: console.print("Finish system initialization", style="bold blue") config_file = ( resolve_path(args.configfile) or os.getenv("BUILDTEST_CONFIGFILE") or None ) configuration = SiteConfiguration(config_file, verbose=args.verbose) configuration.detect_system() configuration.validate() if args.verbose: console.print("Finish configuration initialization", style="bold blue") console.print( f"Using configuration file: {configuration.file}", style="bold blue" ) buildtest_editor = set_editor(args.editor) logger.info(f"[red]Processing buildtest configuration file: {configuration.file}") # build buildspec cache file automatically if it doesn't exist if not is_file(BUILDSPEC_CACHE_FILE): search_buildspecs = [] if hasattr(args, "search"): search_buildspecs = args.search BuildspecCache(search_buildspecs=search_buildspecs, configuration=configuration) return system, configuration, buildtest_editor, report_file
[docs] def handle_log_viewing(args): """This function handles the viewing of the log file. If the user specifies --view-log or --print-log, this function will display the log file content and return True. If the log file is not present, this function will raise an exception. If the user does not specify --view-log or --print-log, this function will return False. Args: args (argparse.Namespace): An argparse namespace object containing command line arguments Returns: bool: Return True if user specifies --view-log or --print-log and implements logic, otherwise return False """ if args.view_log or args.print_log: # if logfile is not present we should raise exception since this file is only created upon running 'buildtest build' if not is_file(BUILDTEST_LOGFILE): raise BuildTestError( f"Unable to find logfile: {BUILDTEST_LOGFILE}, please run 'buildtest build'" ) content = read_file(BUILDTEST_LOGFILE) if args.view_log: with console.pager(): console.print(content) else: console.print(content) return True return False
[docs] def handle_build_command(args, configuration, report_file): if args.subcommands in ["build", "bd"]: stdout_file = tempfile.NamedTemporaryFile(delete=True, suffix=".txt") with Tee(stdout_file.name): cmd = BuildTest( account=args.account, buildspecs=args.buildspec, configuration=configuration, display=args.display, dry_run=args.dry_run, exclude_buildspecs=args.exclude, exclude_tags=args.exclude_tags, executors=args.executor, executor_type=args.executor_type, filter_buildspecs=args.filter, helpfilter=args.helpfilter, limit=args.limit, max_jobs=args.max_jobs, maxpendtime=args.maxpendtime, modules=args.modules, modulepurge=args.module_purge, numnodes=args.nodes, numprocs=args.procs, name=args.name, poll_interval=args.pollinterval, profile=args.profile, rebuild=args.rebuild, remove_stagedir=args.remove_stagedir, report_file=report_file, rerun=args.rerun, retry=args.retry, save_profile=args.save_profile, strict=args.strict, tags=args.tags, testdir=args.testdir, timeout=args.timeout, unload_modules=args.unload_modules, validate=args.validate, verbose=args.verbose, write_config_file=args.write_config_file, ) cmd.build() if cmd.build_success(): build_history_dir = cmd.get_build_history_dir() shutil.copyfile( stdout_file.name, os.path.join(build_history_dir, "output.txt") ) stdout_file.close()
[docs] def handle_buildspec_command(args, configuration, report_file, buildtest_editor): if args.buildspecs_subcommand in ["find", "f"]: buildspec_find(args=args, configuration=configuration) elif args.buildspecs_subcommand in ["summary", "sm"]: summarize_buildspec_cache( pager=args.pager, configuration=configuration, color=args.color ) elif args.buildspecs_subcommand in ["show", "s"]: show_buildspecs( test_names=args.name, configuration=configuration, theme=args.theme ) elif args.buildspecs_subcommand in ["show-fail", "sf"]: show_failed_buildspecs( configuration=configuration, test_names=args.name, report_file=report_file, theme=args.theme, ) elif args.buildspecs_subcommand in ["edit-test", "et"]: edit_buildspec_test( test_names=args.name, configuration=configuration, editor=buildtest_editor ) elif args.buildspecs_subcommand in ["edit-file", "ef"]: edit_buildspec_file( buildspecs=args.file, configuration=configuration, editor=buildtest_editor ) elif args.buildspecs_subcommand in ["maintainers", "m"]: name = None if hasattr(args, "name"): name = args.name buildspec_maintainers( configuration=configuration, breakdown=args.breakdown, terse=args.terse, header=args.no_header, color=args.color, name=name, row_count=args.row_count, count=args.count, pager=args.pager, ) elif args.buildspecs_subcommand in ["validate", "val"]: buildspec_validate_command( buildspecs=args.buildspec, excluded_buildspecs=args.exclude, tags=args.tag, executors=args.executor, name=args.name, configuration=configuration, )
[docs] def handle_inspect_command(args, configuration, report_file): report = Report(configuration=configuration, report_file=report_file) if args.inspect in ["list", "ls"]: inspect_list( report, terse=args.terse, no_header=args.no_header, builder=args.builder, color=args.color, pager=args.pager, row_count=args.row_count, ) # implements command 'buildtest inspect name' if args.inspect in ["name", "n"]: inspect_by_name(report, names=args.name, pager=args.pager) if args.inspect in ["query", "q"]: inspect_query( report, name=args.name, theme=args.theme, output=args.output, error=args.error, testpath=args.testpath, buildscript=args.buildscript, buildenv=args.buildenv, pager=args.pager, ) if args.inspect in ["buildspec", "b"]: inspect_buildspec( report, input_buildspecs=args.buildspec, all_records=args.all, pager=args.pager, )
[docs] def handle_cdash_command(args, configuration, report_file): cdash_config = deep_get(configuration.target_config, "cdash") if not cdash_config: raise BuildTestError( f"We found no 'cdash' setting set in configuration file: {configuration.file}. Please specify 'cdash' setting in order to use 'buildtest cdash' command" ) if args.cdash == "view": view_cdash_project( cdash_config=cdash_config, config_file=configuration.file, open_browser=True ) elif args.cdash == "upload": upload_test_cdash( build_name=args.buildname, configuration=configuration, site=args.site, report_file=report_file, open_browser=args.open, )
if __name__ == "__main__": main()