pyenv-virtualenv for Windows 1.2
A 'pyenv' plugin to manage Python virtual environments, depending on different Python versions, for various Python projects.
Loading...
Searching...
No Matches
log.py
Go to the documentation of this file.
1##
2# @package log
3# @file log.py
4# @author Michael Paul Korthals
5# @date 2025-07-10
6# @version 1.0.0
7# @copyright © 2025 Michael Paul Korthals. All rights reserved.
8# See License details in the documentation.
9#
10# Library to output colored logging in "pyenv-virtualenv".
11#
12
13# --- IMPORTS ----------------------------------------------------------
14
15# Python
16import collections
17import os
18import platform
19import traceback
20
21# Community
22# (None)
23
24# My
25# (None)
26
27
28# --- CONSTANTS --------------------------------------------------------
29
30## List of log level attributes for comprehensive logging.
31# NOTE: Color of level 20 is default color in terminals with
32# black background like e.g. the cmd.exe window in Windows.
33# @see Logging
34LOG_LEVELS = [
35 {'level': 50, 'name': 'critical', 'color': '\x1b[101m'},
36 {'level': 40, 'name': 'error', 'color': '\x1b[91m'},
37 {'level': 35, 'name': 'success', 'color': '\x1b[92m'},
38 {'level': 30, 'name': 'warning', 'color': '\x1b[93m'},
39 {'level': 25, 'name': 'notice', 'color': '\x1b[95m'},
40 {'level': 20, 'name': 'info', 'color': '\x1b[37m'},
41 {'level': 15, 'name': 'verbose', 'color': '\x1b[94m'},
42 {'level': 10, 'name': 'debug', 'color': '\x1b[32m'},
43 {'level': 5, 'name': 'spam', 'color': '\x1b[90m'}
44]
45
46## Actual log level. It could be overridden by environment variable.
47# Default: 20 (name: 'info')
48LOG_LEVEL: int = 20
49
50## Width of the column, which shows the log level name.
51# Default: 0. It will be calculated automatically.
52LEVEL_COLUMN_WIDTH: int = 0
53
54# --- VARIABLES -------------------------------------------------------
55
56## Flag, which states, that the logging is initialized for this program.
57_is_initialized: bool = False
58
59# --- CLASSES ----------------------------------------------------------
60
61## Named tuple definition of unexpected exception.
62UnexpExcInfo = collections.namedtuple(
63 'ExceptionInfo',
64 ['typ', 'val', 'fil', 'lin', 'qnm', 'tbk']
65)
66
67
68# --- HELPER -----------------------------------------------------------
69
70## Initialize the logging.
72 # Define global variables
73 global LOG_LEVEL
74 global LEVEL_COLUMN_WIDTH
75 # Automatically calculate LEVEL_COLUMN_WIDTH
76 for item in LOG_LEVELS:
77 lln = len(item['name'])
78 if LEVEL_COLUMN_WIDTH < lln:
79 LEVEL_COLUMN_WIDTH = lln
80 # Override LOG_LEVEL by environment variable
81 if 'LOG_LEVEL' in os.environ:
82 LOG_LEVEL = int(os.environ['LOG_LEVEL'])
83 # Set logging is initialized
84 global _is_initialized
85 _is_initialized = True
86
87# Check if logging is initialized.
88#
89# return Flag, which states that logging is initialized.
90def isInitialized() -> bool:
91 return _is_initialized
92
93## Parse the exception data for human-readable information.
94# This allows the developer to identify and locate
95# the exception.
96#
97# @param exc_info Output of sys.exc_info().
98# @return Human-readable information or empty string if
99def getExcInfoStr(exc_info: tuple) -> str:
100 maj, mno, _ = platform.python_version_tuple()
101 maj = int(maj)
102 mno = int(mno)
103 ty, va, tb = exc_info
104 if (maj > 3) or ((maj == 3) and (mno >= 11)):
105 qnm = tb.tb_frame.f_code.co_qualname
106 else:
107 qnm = tb.tb_frame.f_code.co_name
108 i = UnexpExcInfo(
109 ty.__name__,
110 va,
111 tb.tb_frame.f_code.co_filename,
112 tb.tb_lineno,
113 qnm,
114 tb
115 )
116 tbs =''.join(traceback.extract_tb(i.tbk).format())
117 return (
118 'Unexpected {}, "{}"\n'.format(i.typ, i.val) +
119 '\x20\x20File: "{}:{}"\n'.format(i.fil, i.lin) +
120 '\x20\x20Pos.: {}, line {}\n'.format(i.qnm, i.lin) +
121 'Traceback (most recent call last):\n' +
122 '{}'.format(tbs)
123 )
124
125## Get text string from "msg" object argument.
126#
127# @param msg Message as str or result of "sys.exc_info()" as tuple.
128# @return Human-readable message.
129def getMsgText(msg: (str, tuple)) -> str:
130 if isinstance(msg, str):
131 return msg
132 elif isinstance(msg, tuple):
133 return getExcInfoStr(msg)
134 else:
135 raise NotImplementedError
136
137## Log leveled and colored message to console only.
138#
139# @param level ID of logging level.
140# @see LOG_LEVELS
141# @param msg Message as str or result of "sys.exc_info()" as tuple.
142def printLogToConsole(level: int, msg: (str, tuple)):
143 for item in LOG_LEVELS:
144 if (
145 (level == item['level'])
146 and
147 (level >= LOG_LEVEL)
148 ):
149 # Print colorized and immediately flush the output
150 print(
151 '{}{}{}{}\x1b[0m'.format(
152 item['color'],
153 item['name'].upper(),
154 ' ' * (
155 LEVEL_COLUMN_WIDTH
156 -
157 len(item['name'])
158 +
159 1
160 ),
161 getMsgText(msg)
162 ),
163 flush=True
164 )
165 return
166
167
168# --- LOGING FUNCTIONS -------------------------------------------------
169
170## Log critical error message colored to console only.
171#
172# @param msg Message as str or result of sys.exc_info().
173def critical(msg: (str, tuple)):
174 printLogToConsole(50, msg)
175
176## Log error message colored to console only.
177#
178# @param msg Message as str or result of sys.exc_info().
179def error(msg: (str, tuple)):
180 printLogToConsole(40, msg)
181
182## Log success message colored to console only.
183#
184# @param msg Message as str or result of sys.exc_info().
185def success(msg: (str, tuple)):
186 printLogToConsole(35, msg)
187
188## Log warning message colored to console only.
189#
190# @param msg Message as str or result of sys.exc_info().
191def warning(msg: (str, tuple)):
192 printLogToConsole(30, msg)
193
194## Log notice message colored to console only.
195#
196# @param msg Message as str or result of sys.exc_info().
197def notice(msg: (str, tuple)):
198 printLogToConsole(25, msg)
199
200## Log info message colored to console only.
201#
202# @param msg Message as str or result of sys.exc_info().
203def info(msg: (str, tuple)):
204 printLogToConsole(20, msg)
205
206## Log verbose message colored to console only.
207#
208# @param msg Message as str or result of sys.exc_info().
209def verbose(msg: (str, tuple)):
210 printLogToConsole(15, msg)
211
212## Log debug message colored to console only.
213#
214# @param msg Message as str or result of sys.exc_info().
215def debug(msg: (str, tuple)):
216 printLogToConsole(10, msg)
217
218## Log spam message colored to console only.
219#
220# @param msg Message as str or result of sys.exc_info().
221def spam(msg: (str, tuple)):
222 printLogToConsole(5, msg)
223
224
225# --- END OF CODE ------------------------------------------------------
226
debug((str, tuple) msg)
Log debug message colored to console only.
Definition log.py:215
spam((str, tuple) msg)
Log spam message colored to console only.
Definition log.py:221
warning((str, tuple) msg)
Log warning message colored to console only.
Definition log.py:191
notice((str, tuple) msg)
Log notice message colored to console only.
Definition log.py:197
verbose((str, tuple) msg)
Log verbose message colored to console only.
Definition log.py:209
str getMsgText((str, tuple) msg)
Get text string from "msg" object argument.
Definition log.py:129
critical((str, tuple) msg)
Log critical error message colored to console only.
Definition log.py:173
UnexpExcInfo
Named tuple definition of unexpected exception.
Definition log.py:62
printLogToConsole(int level,(str, tuple) msg)
Log leveled and colored message to console only.
Definition log.py:142
initLogging()
Initialize the logging.
Definition log.py:71
success((str, tuple) msg)
Log success message colored to console only.
Definition log.py:185
bool isInitialized()
Definition log.py:90
info((str, tuple) msg)
Log info message colored to console only.
Definition log.py:203
str getExcInfoStr(tuple exc_info)
Parse the exception data for human-readable information.
Definition log.py:99
error((str, tuple) msg)
Log error message colored to console only.
Definition log.py:179