diff --git a/tests/test_main.py b/tests/test_main.py index d9e90fb9..b3df87e0 100644 --- a/tests/test_main.py +++ b/tests/test_main.py @@ -43,8 +43,7 @@ def test_no_color_exception(monkeypatch, capsys): captured = capsys.readouterr() - # Removing trailing whitespace on lines wrapped by Rich; trying to test it was ugly. - # TODO: Assert no color + # Removing trailing whitespace on wrapped lines; trying to test it was ugly. assert [line.rstrip() for line in captured.out.splitlines()] == [ "ERROR InvalidDistribution: Cannot find file (or expand pattern):", " 'missing.whl'", diff --git a/twine/__main__.py b/twine/__main__.py index 3651ae40..1173eb63 100644 --- a/twine/__main__.py +++ b/twine/__main__.py @@ -18,36 +18,16 @@ from typing import Any import requests -import rich.console -import rich.highlighter -import rich.logging -import rich.theme from twine import cli from twine import exceptions def main() -> Any: + # Ensure that all log messages are displayed. + # Color will be configured during cli.dispatch() after argparse. root_logger = logging.getLogger("twine") - root_logger.addHandler( - rich.logging.RichHandler( - console=rich.console.Console( - theme=rich.theme.Theme( - { - "logging.level.debug": "green", - "logging.level.info": "blue", - "logging.level.warning": "yellow", - "logging.level.error": "red", - "logging.level.critical": "reverse red", - } - ), - force_terminal=True, - ), - show_time=False, - show_path=False, - highlighter=rich.highlighter.NullHighlighter(), - ) - ) + root_logger.addHandler(logging.StreamHandler(sys.stdout)) try: error = cli.dispatch(sys.argv[1:]) diff --git a/twine/cli.py b/twine/cli.py index f65bc035..9b7e9a06 100644 --- a/twine/cli.py +++ b/twine/cli.py @@ -12,9 +12,14 @@ # See the License for the specific language governing permissions and # limitations under the License. import argparse +import logging from typing import Any, List, Tuple import importlib_metadata +import rich.console +import rich.highlighter +import rich.logging +import rich.theme from packaging import requirements import twine @@ -34,10 +39,44 @@ def dep_versions() -> str: ) +def configure_logging() -> None: + root_logger = logging.getLogger("twine") + + # Overwrite basic configuration in main() + # TODO: Use dictConfig() instead? + for handler in root_logger.handlers: + root_logger.removeHandler(handler) + + root_logger.addHandler( + rich.logging.RichHandler( + # TODO: Maybe make console a module attribute to facilitate testing and + # using Rich's other functionality. + console=rich.console.Console( + # TODO: Set this if FORCE_COLOR or PY_COLORS in os.environ + force_terminal=True, + no_color=getattr(args, "no_color", False), + theme=rich.theme.Theme( + { + "logging.level.debug": "green", + "logging.level.info": "blue", + "logging.level.warning": "yellow", + "logging.level.error": "red", + "logging.level.critical": "reverse red", + } + ), + ), + show_time=False, + show_path=False, + highlighter=rich.highlighter.NullHighlighter(), + ) + ) + + def dispatch(argv: List[str]) -> Any: registered_commands = importlib_metadata.entry_points( group="twine.registered_commands" ) + parser = argparse.ArgumentParser(prog="twine") parser.add_argument( "--version", @@ -60,9 +99,10 @@ def dispatch(argv: List[str]) -> Any: help=argparse.SUPPRESS, nargs=argparse.REMAINDER, ) - parser.parse_args(argv, namespace=args) + configure_logging() + main = registered_commands[args.command].load() return main(args.args)