blob: 58a3d846371ca1a69830d3cc9bf9499ac9c94ba2 [file] [log] [blame]
# Copyright 2021 The Pigweed Authors
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
# use this file except in compliance with the License. You may obtain a copy of
# the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations under
# the License.
"""Pigweed Console entry point."""
import argparse
import inspect
import logging
from pathlib import Path
import sys
from typing import Optional, Dict
import pw_cli.log
import pw_cli.argument_types
import pw_console
import pw_console.python_logging
import pw_console.test_mode
from pw_console.log_store import LogStore
from pw_console.plugins.calc_pane import CalcPane
from pw_console.plugins.clock_pane import ClockPane
from pw_console.plugins.twenty48_pane import Twenty48Pane
_LOG = logging.getLogger(__package__)
_ROOT_LOG = logging.getLogger('')
# TODO(tonymd): Remove this when no downstream projects are using it.
def create_temp_log_file():
return pw_console.python_logging.create_temp_log_file()
def _build_argument_parser() -> argparse.ArgumentParser:
"""Setup argparse."""
parser = argparse.ArgumentParser(prog="python -m pw_console",
description=__doc__)
parser.add_argument('-l',
'--loglevel',
type=pw_cli.argument_types.log_level,
default=logging.DEBUG,
help='Set the log level'
'(debug, info, warning, error, critical)')
parser.add_argument('--logfile', help='Pigweed Console log file.')
parser.add_argument('--test-mode',
action='store_true',
help='Enable fake log messages for testing purposes.')
parser.add_argument('--config-file',
type=Path,
help='Path to a pw_console yaml config file.')
parser.add_argument('--console-debug-log-file',
help='Log file to send console debug messages to.')
return parser
def main() -> int:
"""Pigweed Console."""
parser = _build_argument_parser()
args = parser.parse_args()
if not args.logfile:
# Create a temp logfile to prevent logs from appearing over stdout. This
# would corrupt the prompt toolkit UI.
args.logfile = pw_console.python_logging.create_temp_log_file()
pw_cli.log.install(level=args.loglevel,
use_color=True,
hide_timestamp=False,
log_file=args.logfile)
if args.console_debug_log_file:
pw_cli.log.install(level=logging.DEBUG,
use_color=True,
hide_timestamp=False,
log_file=args.console_debug_log_file,
logger=logging.getLogger('pw_console'))
global_vars = None
default_loggers = {}
if args.test_mode:
root_log_store = LogStore()
_ROOT_LOG.addHandler(root_log_store)
_ROOT_LOG.debug('pw_console test-mode starting...')
fake_logger = logging.getLogger(
pw_console.test_mode.FAKE_DEVICE_LOGGER_NAME)
default_loggers = {
# Don't include pw_console package logs (_LOG) in the log pane UI.
# Add the fake logger for test_mode.
'Fake Device': [fake_logger],
'PwConsole Debug': [logging.getLogger('pw_console')],
'All Logs': root_log_store,
}
# Give access to adding log messages from the repl via: `LOG.warning()`
global_vars = dict(LOG=fake_logger)
help_text = None
app_title = None
if args.test_mode:
app_title = 'Console Test Mode'
help_text = inspect.cleandoc("""
Welcome to the Pigweed Console Test Mode!
Example commands:
rpcs.pw.rpc.EchoService.Echo(msg='hello!')
LOG.warning('Message appears console log window.')
""")
console = pw_console.PwConsoleEmbed(
global_vars=global_vars,
loggers=default_loggers,
test_mode=args.test_mode,
help_text=help_text,
app_title=app_title,
config_file_path=args.config_file,
)
overriden_window_config: Optional[Dict] = None
# Add example plugins and log panes used to validate behavior in the Pigweed
# Console manual test procedure: https://pigweed.dev/pw_console/testing.html
if args.test_mode:
fake_logger.propagate = False
console.setup_python_logging(loggers_with_no_propagation=[fake_logger])
_ROOT_LOG.debug('pw_console.PwConsoleEmbed init complete')
_ROOT_LOG.debug('Adding plugins...')
console.add_window_plugin(ClockPane())
console.add_window_plugin(CalcPane())
console.add_floating_window_plugin(
Twenty48Pane(include_resize_handle=False), left=4)
_ROOT_LOG.debug('Starting prompt_toolkit full-screen application...')
overriden_window_config = {
'Split 1 stacked': {
'Fake Device': None,
'Fake Keys': {
'duplicate_of': 'Fake Device',
'filters': {
'keys': {
'regex': '[^ ]+'
},
},
},
'Fake USB': {
'duplicate_of': 'Fake Device',
'filters': {
'module': {
'regex': 'USB'
},
},
},
},
'Split 2 tabbed': {
'Python Repl': None,
'All Logs': None,
'PwConsole Debug': None,
'Calculator': None,
'Clock': None,
},
}
console.embed(override_window_config=overriden_window_config)
if args.logfile:
print(f'Logs saved to: {args.logfile}')
return 0
if __name__ == '__main__':
sys.exit(main())