Skip to content

Commit 3e6896e

Browse files
committed
feat: Add extended standard logger support
CustomLogger to replace uneven print/trace solution. Add trace level support, set standard level to warning/error. Using --verbose or -v options, set the app logger to INFO, -vv set the app logger to DEBUG, -vvv set the app logger to TRACE status and last -vvvv to DEEP status. Signed-off-by: Helio Chissini de Castro <[email protected]>
1 parent af339f8 commit 3e6896e

File tree

4 files changed

+124
-6
lines changed

4 files changed

+124
-6
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ pip3 # Python compiled files
22
*.py[cod]
33

44
# virtualenv and other misc bits
5+
.venv
56
/src/*.egg-info
67
*.egg-info
78
/dist

src/python_inspector/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,4 @@
1313
pyinspector_settings = settings.Settings()
1414

1515
settings.create_cache_directory(pyinspector_settings.CACHE_THIRDPARTY_DIR)
16+

src/python_inspector/logging.py

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
#
2+
# Copyright (c) nexB Inc. and others. All rights reserved.
3+
# ScanCode is a trademark of nexB Inc.
4+
# SPDX-License-Identifier: Apache-2.0
5+
# See http://www.apache.org/licenses/LICENSE-2.0 for the license text.
6+
# See https://github.com/aboutcode-org/python-inspector for support or download.
7+
# See https://aboutcode.org for more information about nexB OSS projects.
8+
#
9+
10+
import logging
11+
from types import TracebackType
12+
from typing import Any, Optional, Tuple, Type, Union
13+
14+
# Add TRACE custom level to be third leve, as verbose will match
15+
# -v == logLevel INFO
16+
# -vv == logLevel DEBUG
17+
# -vvv == logLevel TRACE
18+
TRACE_LEVEL: int = 5
19+
DEEP_LEVEL: int = 4
20+
21+
22+
class CustomLogger(logging.Logger):
23+
def trace(
24+
self: logging.Logger,
25+
msg: Any,
26+
*args: Any,
27+
exc_info: Union[
28+
bool,
29+
BaseException,
30+
Tuple[Type[BaseException], BaseException, TracebackType],
31+
None,
32+
] = None,
33+
stack_info: bool = False,
34+
stacklevel: int = 1,
35+
extra: Optional[dict[str, Any]] = None,
36+
) -> None:
37+
if self.isEnabledFor(TRACE_LEVEL):
38+
self._log(
39+
TRACE_LEVEL,
40+
msg,
41+
args,
42+
exc_info=exc_info,
43+
extra=extra,
44+
stack_info=stack_info,
45+
stacklevel=stacklevel,
46+
)
47+
48+
def deep(
49+
self: logging.Logger,
50+
msg: Any,
51+
*args: Any,
52+
exc_info: Union[
53+
bool,
54+
BaseException,
55+
Tuple[Type[BaseException], BaseException, TracebackType],
56+
None,
57+
] = None,
58+
stack_info: bool = False,
59+
stacklevel: int = 1,
60+
extra: Optional[dict[str, Any]] = None,
61+
) -> None:
62+
if self.isEnabledFor(DEEP_LEVEL):
63+
self._log(
64+
DEEP_LEVEL,
65+
msg,
66+
args,
67+
exc_info=exc_info,
68+
extra=extra,
69+
stack_info=stack_info,
70+
stacklevel=stacklevel,
71+
)
72+
73+
74+
logging.Logger.trace = trace
75+
logging.Logger.deep = deep
76+
77+
78+
def setup_logger(level: str = "WARNING") -> None:
79+
"""
80+
Configures the logger for the 'python-inspector' application.
81+
82+
This function sets up a custom logging level, assigns a custom logger class,
83+
and configures the logger with the specified logging level. If no handlers are present,
84+
it adds a stream handler with a simple formatter.
85+
86+
Args:
87+
level (str): The logging level to set for the logger (e.g., 'DEBUG', 'INFO', 'WARNING', "TRACE").
88+
"""
89+
# Setup out trace level
90+
logging.addLevelName(TRACE_LEVEL, "TRACE")
91+
logging.addLevelName(DEEP_LEVEL, "DEEP")
92+
logging.setLoggerClass(CustomLogger)
93+
94+
_logger = logging.getLogger("python-inspector")
95+
_logger.setLevel(level)
96+
_logger.propagate = False
97+
98+
if not _logger.hasHandlers():
99+
handler = logging.StreamHandler()
100+
formatter = logging.Formatter("[%(levelname)s] %(message)s")
101+
handler.setFormatter(formatter)
102+
_logger.addHandler(handler)
103+
104+
105+
# Logger as a singleton
106+
logger: logging.Logger = logging.getLogger("python-inspector")

src/python_inspector/resolve_cli.py

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@
1313

1414
import click
1515

16-
from python_inspector import settings
17-
from python_inspector import utils_pypi
16+
from python_inspector import logging, utils_pypi
17+
from python_inspector import pyinspector_settings as settings
1818
from python_inspector.cli_utils import FileOptionType
1919
from python_inspector.utils import write_output_in_file
2020

@@ -162,9 +162,10 @@ def print_version(ctx, param, value):
162162
"distribution is available then binary distributions are used",
163163
)
164164
@click.option(
165+
"-v",
165166
"--verbose",
166-
is_flag=True,
167-
help="Enable verbose debug output.",
167+
count=True,
168+
help="Increase verbosity: -v=INFO, -vv=DEBUG, -vvv=TRACE.",
168169
)
169170
@click.option(
170171
"-V",
@@ -198,11 +199,11 @@ def resolve_dependencies(
198199
pdt_output,
199200
netrc_file,
200201
max_rounds,
202+
verbose,
201203
use_cached_index=False,
202204
use_pypi_json_api=False,
203205
analyze_setup_py_insecurely=False,
204206
prefer_source=False,
205-
verbose=TRACE,
206207
generic_paths=False,
207208
ignore_errors=False,
208209
):
@@ -237,6 +238,16 @@ def resolve_dependencies(
237238
click.secho("Only one of --json or --json-pdt can be used.", err=True)
238239
ctx.exit(1)
239240

241+
# Setup verbose level
242+
if verbose >= 3:
243+
logging.setup_logger("TRACE")
244+
elif verbose == 2:
245+
logging.setup_logger("DEBUG")
246+
elif verbose == 1:
247+
logging.setup_logger("INFO")
248+
else:
249+
logging.setup_logger()
250+
240251
options = get_pretty_options(ctx, generic_paths=generic_paths)
241252

242253
notice = (
@@ -268,7 +279,6 @@ def resolve_dependencies(
268279
max_rounds=max_rounds,
269280
use_cached_index=use_cached_index,
270281
use_pypi_json_api=use_pypi_json_api,
271-
verbose=verbose,
272282
analyze_setup_py_insecurely=analyze_setup_py_insecurely,
273283
printer=click.secho,
274284
prefer_source=prefer_source,

0 commit comments

Comments
 (0)