def validate_component_cli(component_types: Tuple[Type[BaseComponentAPI], ...], boot_info: BootInfo) -> None: # Let the components do runtime validation for component_cls in component_types: try: component_cls.validate_cli(boot_info) except ValidationError as exc: parser.exit(message=str(exc))
def main_entry(trinity_boot: BootFn, app_identifier: str, component_types: Tuple[Type[BaseComponentAPI], ...], sub_configs: Sequence[Type[BaseAppConfig]]) -> None: if is_prerelease(): # this modifies the asyncio logger, but will be overridden by any custom settings below enable_warnings_by_default() for component_cls in component_types: component_cls.configure_parser(parser, subparser) argcomplete.autocomplete(parser) args = parser.parse_args() if not args.genesis and args.network_id not in PRECONFIGURED_NETWORKS: parser.error( f"Unsupported network id: {args.network_id}. To use a network besides " "mainnet, ropsten or goerli, you must supply a genesis file with a flag, like " "`--genesis path/to/genesis.json`, also you must specify a data " "directory with `--data-dir path/to/data/directory`") # The `common_log_level` is derived from `--log-level <Level>` / `-l <Level>` without # specifying any module. If present, it is used for both `stderr` and `file` logging. common_log_level = args.log_levels and args.log_levels.get(None) has_ambigous_logging_config = ( (common_log_level is not None and args.stderr_log_level is not None) or (common_log_level is not None and args.file_log_level is not None)) if has_ambigous_logging_config: parser.error(f"""\n Ambiguous logging configuration: The `--log-level (-l)` flag sets the log level for both file and stderr logging. To configure different log level for file and stderr logging, remove the `--log-level` flag and use `--stderr-log-level` and/or `--file-log-level` separately. Alternatively, remove the `--stderr-log-level` and/or `--file-log-level` flags to share one single log level across both handlers. """) trinity_config = load_trinity_config_from_parser_args( parser, args, app_identifier, sub_configs) ensure_data_dir_is_initialized(trinity_config) # +---------------+ # | LOGGING SETUP | # +---------------+ # Setup logging to stderr stderr_logger_level = ( args.stderr_log_level if args.stderr_log_level is not None else (common_log_level if common_log_level is not None else logging.INFO)) handler_stderr = setup_stderr_logging(stderr_logger_level) # Setup file based logging file_logger_level = ( args.file_log_level if args.file_log_level is not None else (common_log_level if common_log_level is not None else logging.DEBUG)) handler_file = setup_file_logging(trinity_config.logfile_path, file_logger_level) # Set the individual logger levels that have been specified. logger_levels = {} if args.log_levels is None else args.log_levels set_logger_levels(logger_levels) # get the root logger and set it to the level of the stderr logger. logger = logging.getLogger() logger.setLevel(stderr_logger_level) # This prints out the ASCII "trinity" header in the terminal display_launch_logs(trinity_config) # Setup the log listener which child processes relay their logs through log_listener = IPCListener(handler_stderr, handler_file) # Determine what logging level child processes should use. child_process_log_level = min( stderr_logger_level, file_logger_level, *logger_levels.values(), ) boot_info = BootInfo( args=args, trinity_config=trinity_config, child_process_log_level=child_process_log_level, logger_levels=logger_levels, profile=bool(args.profile), ) # Let the components do runtime validation for component_cls in component_types: try: component_cls.validate_cli(boot_info) except ValidationError as exc: parser.exit(message=str(exc)) # Components can provide a subcommand with a `func` which does then control # the entire process from here. if hasattr(args, 'func'): args.func(args, trinity_config) return runtime_component_types = tuple(component_cls for component_cls in component_types if issubclass(component_cls, ComponentAPI)) with log_listener.run(trinity_config.logging_ipc_path): processes = trinity_boot(boot_info) loop = asyncio.get_event_loop() def kill_trinity_with_reason(reason: str) -> None: kill_trinity_gracefully(trinity_config, logger, processes, reason=reason) component_manager_service = ComponentManager( boot_info, runtime_component_types, ) manager = AsyncioManager(component_manager_service) loop.add_signal_handler( signal.SIGTERM, manager.cancel, 'SIGTERM', ) loop.add_signal_handler( signal.SIGINT, component_manager_service.shutdown, 'CTRL+C', ) try: loop.run_until_complete(manager.run()) except BaseException as err: logger.error("Error during trinity run: %r", err) raise finally: kill_trinity_with_reason(component_manager_service.reason) if trinity_config.trinity_tmp_root_dir: shutil.rmtree(trinity_config.trinity_root_dir)