Changeset - 32b62df5405f
[Not reviewed]
0 3 0
Brett Smith - 4 years ago 2020-05-30 03:39:27
brettcsmith@brettcsmith.org
cliutil: Better implementation of is_main_script.

The old one could return True if you called accrual.main()
directly from one-off test scripts.
3 files changed with 21 insertions and 6 deletions:
0 comments (0 inline, 0 general)
conservancy_beancount/cliutil.py
Show inline comments
...
 
@@ -25,12 +25,14 @@ import os
 
import pkg_resources
 
import signal
 
import sys
 
import traceback
 
import types
 

	
 
from pathlib import Path
 

	
 
from typing import (
 
    Any,
 
    Iterable,
 
    NoReturn,
 
    Optional,
 
    Sequence,
...
 
@@ -131,16 +133,20 @@ def add_version_argument(parser: argparse.ArgumentParser) -> argparse.Action:
 
        action=InfoAction,
 
        nargs=0,
 
        const=f"{progname} version {VERSION}\n{LICENSE}",
 
        help="Show program version and license information",
 
    )
 

	
 
def is_main_script() -> bool:
 
def is_main_script(prog_name: str) -> bool:
 
    """Return true if the caller is the "main" program."""
 
    stack = inspect.stack(context=False)
 
    return len(stack) <= 3 and stack[-1].function.startswith('<')
 
    stack = iter(inspect.stack(context=False))
 
    next(stack)  # Discard the frame for calling this function
 
    caller_filename = next(stack).filename
 
    return all(frame.filename == caller_filename
 
               or Path(frame.filename).stem == prog_name
 
               for frame in stack)
 

	
 
def setup_logger(logger: Union[str, logging.Logger]='',
 
                 loglevel: int=logging.INFO,
 
                 stream: TextIO=sys.stderr,
 
                 fmt: str='%(name)s: %(levelname)s: %(message)s',
 
) -> logging.Logger:
conservancy_beancount/reports/accrual.py
Show inline comments
...
 
@@ -388,13 +388,13 @@ metadata to match. A single ticket number is a shortcut for
 

	
 
def main(arglist: Optional[Sequence[str]]=None,
 
         stdout: TextIO=sys.stdout,
 
         stderr: TextIO=sys.stderr,
 
         config: Optional[configmod.Config]=None,
 
) -> int:
 
    if cliutil.is_main_script():
 
    if cliutil.is_main_script(PROGNAME):
 
        global logger
 
        logger = logging.getLogger(PROGNAME)
 
        sys.excepthook = cliutil.ExceptHook(logger)
 
    args = parse_arguments(arglist)
 
    cliutil.setup_logger(logger, args.loglevel, stderr)
 
    if config is None:
tests/test_cliutil.py
Show inline comments
...
 
@@ -24,12 +24,17 @@ import re
 
import traceback
 

	
 
import pytest
 

	
 
from conservancy_beancount import cliutil
 

	
 
class AlwaysEqual:
 
    def __eq__(self, other):
 
        return True
 

	
 

	
 
class MockTraceback:
 
    def __init__(self, stack=None, index=0):
 
        if stack is None:
 
            stack = inspect.stack(context=False)
 
        self._stack = stack
 
        self._index = index
...
 
@@ -88,14 +93,18 @@ def test_excepthook_traceback(caplog):
 
    caplog.set_level(logging.DEBUG)
 
    with pytest.raises(SystemExit) as exc_check:
 
        cliutil.ExceptHook()(*args)
 
    assert caplog.records
 
    assert caplog.records[-1].message == ''.join(traceback.format_exception(*args))
 

	
 
def test_is_main_script():
 
    assert not cliutil.is_main_script()
 
@pytest.mark.parametrize('prog_name,expected', [
 
    ('', False),
 
    (AlwaysEqual(), True),
 
])
 
def test_is_main_script(prog_name, expected):
 
    assert cliutil.is_main_script(prog_name) == expected
 

	
 
@pytest.mark.parametrize('arg,expected', [
 
    ('debug', logging.DEBUG),
 
    ('info', logging.INFO),
 
    ('warning', logging.WARNING),
 
    ('warn', logging.WARNING),
0 comments (0 inline, 0 general)