inspy-logger 3.0.dev2__tar.gz → 3.0.dev3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {inspy_logger-3.0.dev2 → inspy_logger-3.0.dev3}/PKG-INFO +4 -4
- {inspy_logger-3.0.dev2 → inspy_logger-3.0.dev3}/inspy_logger/__init__.py +55 -101
- inspy_logger-3.0.dev3/inspy_logger/helpers/base_classes.py +136 -0
- {inspy_logger-3.0.dev2 → inspy_logger-3.0.dev3}/inspy_logger/version.py +1 -1
- {inspy_logger-3.0.dev2 → inspy_logger-3.0.dev3}/pyproject.toml +12 -5
- {inspy_logger-3.0.dev2 → inspy_logger-3.0.dev3}/LICENSE.md +0 -0
- {inspy_logger-3.0.dev2 → inspy_logger-3.0.dev3}/README.md +0 -0
- {inspy_logger-3.0.dev2 → inspy_logger-3.0.dev3}/inspy_logger/Scripts/main.py +0 -0
- {inspy_logger-3.0.dev2 → inspy_logger-3.0.dev3}/inspy_logger/__about__.py +0 -0
- {inspy_logger-3.0.dev2 → inspy_logger-3.0.dev3}/inspy_logger/errors/__init__.py +0 -0
- {inspy_logger-3.0.dev2 → inspy_logger-3.0.dev3}/inspy_logger/helpers/__init__.py +0 -0
- {inspy_logger-3.0.dev2 → inspy_logger-3.0.dev3}/inspy_logger/helpers/cache.py +0 -0
- {inspy_logger-3.0.dev2 → inspy_logger-3.0.dev3}/inspy_logger/helpers/network.py +0 -0
- {inspy_logger-3.0.dev2 → inspy_logger-3.0.dev3}/inspy_logger/manifest.py +0 -0
|
@@ -1,25 +1,25 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: inspy-logger
|
|
3
|
-
Version: 3.0.
|
|
3
|
+
Version: 3.0.dev3
|
|
4
4
|
Summary: Colorable, scalable logger for CLI
|
|
5
5
|
Home-page: https://github.com/Inspyre-Softworks/inSPy-Logger
|
|
6
6
|
License: MIT
|
|
7
7
|
Keywords: cli,color,logging,log,terminal,console,colorama,colorlog,rich
|
|
8
8
|
Author: Taylor-Jayde Blackstone
|
|
9
9
|
Author-email: tayjaybabee@gmail.com
|
|
10
|
-
Requires-Python: >=3.
|
|
10
|
+
Requires-Python: >=3.9,<4.0
|
|
11
11
|
Classifier: Development Status :: 5 - Production/Stable
|
|
12
12
|
Classifier: Intended Audience :: Developers
|
|
13
13
|
Classifier: License :: OSI Approved :: MIT License
|
|
14
14
|
Classifier: Natural Language :: English
|
|
15
15
|
Classifier: Operating System :: OS Independent
|
|
16
16
|
Classifier: Programming Language :: Python :: 3
|
|
17
|
-
Classifier: Programming Language :: Python :: 3.7
|
|
18
|
-
Classifier: Programming Language :: Python :: 3.8
|
|
19
17
|
Classifier: Programming Language :: Python :: 3.9
|
|
20
18
|
Classifier: Programming Language :: Python :: 3.10
|
|
21
19
|
Classifier: Programming Language :: Python :: 3.11
|
|
22
20
|
Classifier: Programming Language :: Python :: 3 :: Only
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.7
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
23
23
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
24
24
|
Classifier: Topic :: System :: Logging
|
|
25
25
|
Classifier: Topic :: Utilities
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
2
|
import inspect
|
|
3
|
+
import os
|
|
3
4
|
import logging
|
|
4
5
|
from rich.logging import RichHandler
|
|
5
6
|
from inspy_logger.__about__ import __prog__ as PROG_NAME
|
|
6
7
|
from inspy_logger.helpers import find_variable_in_call_stack
|
|
7
8
|
|
|
9
|
+
|
|
8
10
|
# Let's set up some constants.
|
|
9
11
|
LEVEL_MAP = [
|
|
10
12
|
('debug', logging.DEBUG),
|
|
@@ -144,8 +146,7 @@ class Logger:
|
|
|
144
146
|
child.set_level(file_level=file_level)
|
|
145
147
|
|
|
146
148
|
def get_child(self, name=None, console_level=None, file_level=None):
|
|
147
|
-
self.
|
|
148
|
-
console_level = console_level or DEFAULT_LOGGING_LEVEL
|
|
149
|
+
console_level = console_level or self.__console_level
|
|
149
150
|
caller_frame = inspect.stack()[1]
|
|
150
151
|
|
|
151
152
|
if name is None:
|
|
@@ -159,7 +160,7 @@ class Logger:
|
|
|
159
160
|
if child.logger.name == child_logger_name:
|
|
160
161
|
return child
|
|
161
162
|
|
|
162
|
-
child_logger = Logger(child_logger_name, console_level, file_level, parent=self)
|
|
163
|
+
child_logger = Logger(name=child_logger_name, console_level=console_level, file_level=file_level, parent=self)
|
|
163
164
|
self.children.append(child_logger)
|
|
164
165
|
return child_logger
|
|
165
166
|
|
|
@@ -195,6 +196,19 @@ class Logger:
|
|
|
195
196
|
|
|
196
197
|
return results
|
|
197
198
|
|
|
199
|
+
def debug(self, message):
|
|
200
|
+
self.logger.debug(message)
|
|
201
|
+
|
|
202
|
+
def info(self, message):
|
|
203
|
+
self.logger.info(message)
|
|
204
|
+
|
|
205
|
+
def warning(self, message):
|
|
206
|
+
self.logger.warning(message)
|
|
207
|
+
|
|
208
|
+
def error(self, message):
|
|
209
|
+
self.logger.error(message)
|
|
210
|
+
|
|
211
|
+
|
|
198
212
|
def __repr__(self):
|
|
199
213
|
name = self.name
|
|
200
214
|
hex_id = hex(id(self))
|
|
@@ -208,119 +222,59 @@ class Logger:
|
|
|
208
222
|
if parent_part.endswith('|'):
|
|
209
223
|
parent_part = str(parent_part[:-2])
|
|
210
224
|
|
|
211
|
-
return f'<Logger: {name} at {hex_id}{parent_part}>'
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
found_level = find_variable_in_call_stack('INSPY_LOG_LEVEL', DEFAULT_LOGGING_LEVEL)
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
LOG_DEVICE = Logger(PROG_NAME, found_level)
|
|
218
|
-
MOD_LOG_DEVICE = LOG_DEVICE.get_child("log_engine", found_level)
|
|
219
|
-
MOD_LOGGER = MOD_LOG_DEVICE.logger
|
|
220
|
-
MOD_LOGGER.debug(f"Started logger for {__name__}.")
|
|
221
|
-
|
|
222
|
-
add_child = LOG_DEVICE.get_child
|
|
223
|
-
|
|
224
|
-
InspyLogger = Logger
|
|
225
|
-
|
|
226
|
-
def _get_parent_logging_device():
|
|
227
|
-
"""
|
|
228
|
-
Determines the parent logging device by inspecting the caller's log_device or parent_log_device attribute.
|
|
229
|
-
|
|
230
|
-
Returns:
|
|
231
|
-
Logger: The parent logging device.
|
|
232
|
-
"""
|
|
233
|
-
MOD_LOGGER.debug("Determining parent logging device")
|
|
234
|
-
caller_frame = inspect.currentframe().f_back
|
|
235
|
-
caller_locals = caller_frame.f_locals
|
|
225
|
+
return f'<Logger: {name} w/ level {self.logger.level} at {hex_id}{parent_part}>'
|
|
236
226
|
|
|
237
|
-
if "logger" in caller_locals:
|
|
238
|
-
return caller_locals["logger"]
|
|
239
|
-
elif "parent_log_device" in caller_locals:
|
|
240
|
-
return caller_locals["parent_log_device"]
|
|
241
|
-
else:
|
|
242
|
-
raise ValueError("Unable to determine the parent logging device.")
|
|
243
227
|
|
|
228
|
+
@classmethod
|
|
229
|
+
def create_logger_for_caller(cls):
|
|
230
|
+
"""
|
|
231
|
+
Creates a logger for the module that calls this method.
|
|
244
232
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
self.parent_log_device = parent_log_device
|
|
257
|
-
self.__log_name = self.__class__.__name__
|
|
258
|
-
if self.parent_log_device is not None:
|
|
259
|
-
self.__log_device = self.parent_log_device.get_child(
|
|
260
|
-
self.__class__.__name__
|
|
261
|
-
)
|
|
233
|
+
Returns:
|
|
234
|
+
Logger: An instance of the Logger class for the calling module.
|
|
235
|
+
"""
|
|
236
|
+
frame = inspect.currentframe().f_back
|
|
237
|
+
#print(frame)
|
|
238
|
+
#print(dir(frame))
|
|
239
|
+
#print(dir(inspect.getmodule(frame)))
|
|
240
|
+
#print(inspect.getmodule(frame).__name__)
|
|
241
|
+
module_path = cls._determine_module_path(frame)
|
|
242
|
+
if module_path:
|
|
243
|
+
return cls(module_path)
|
|
262
244
|
else:
|
|
263
|
-
|
|
264
|
-
self.__class__.__name__
|
|
265
|
-
)
|
|
266
|
-
|
|
267
|
-
@property
|
|
268
|
-
def log_device(self):
|
|
269
|
-
return self.__log_device
|
|
270
|
-
|
|
271
|
-
@log_device.setter
|
|
272
|
-
def log_device(self, new):
|
|
273
|
-
if not isinstance(new, Logger):
|
|
274
|
-
raise TypeError('log_device must be of type "Logger"')
|
|
275
|
-
|
|
276
|
-
self.__log_device = new
|
|
245
|
+
raise ValueError("Unable to determine module path for logger creation.")
|
|
277
246
|
|
|
278
|
-
|
|
247
|
+
@staticmethod
|
|
248
|
+
def _determine_module_path(frame):
|
|
279
249
|
"""
|
|
280
|
-
|
|
250
|
+
Determines the in-project path of the module from the call frame.
|
|
281
251
|
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
If not provided, the name of the calling function is used.
|
|
285
|
-
override (bool, optional): A flag to override the membership check. Defaults to False.
|
|
252
|
+
Args:
|
|
253
|
+
frame: The frame from which to determine the module path.
|
|
286
254
|
|
|
287
255
|
Returns:
|
|
288
|
-
|
|
256
|
+
str: The in-project path of the module.
|
|
289
257
|
"""
|
|
290
|
-
|
|
291
|
-
|
|
258
|
+
module = inspect.getmodule(frame)
|
|
259
|
+
if module:
|
|
260
|
+
base_path = os.path.dirname(os.path.abspath(module.__file__))
|
|
261
|
+
relative_path = os.path.relpath(frame.f_code.co_filename, base_path)
|
|
262
|
+
module_path = relative_path.replace(os.path.sep, '.').rstrip('.py')
|
|
263
|
+
return module_path
|
|
264
|
+
return None
|
|
292
265
|
|
|
293
|
-
if name is None:
|
|
294
|
-
name = inspect.stack()[1][
|
|
295
|
-
3
|
|
296
|
-
] # Get the name of the calling function if no name is provided
|
|
297
|
-
|
|
298
|
-
return self.log_device.get_child(name)
|
|
299
266
|
|
|
300
|
-
def __is_member__(self):
|
|
301
|
-
"""
|
|
302
|
-
Checks whether the caller of this method is a member of the same class.
|
|
303
267
|
|
|
304
|
-
|
|
305
|
-
PermissionError: If the caller of this method is not a member of the same class.
|
|
306
|
-
"""
|
|
307
|
-
log_device = self.log_device.get_child("__is_member__")
|
|
308
|
-
log = log_device.logger
|
|
268
|
+
found_level = find_variable_in_call_stack('INSPY_LOG_LEVEL', DEFAULT_LOGGING_LEVEL)
|
|
309
269
|
|
|
310
|
-
current_frame = inspect.currentframe()
|
|
311
|
-
log.debug(f"Current frame: {current_frame}")
|
|
312
270
|
|
|
313
|
-
|
|
314
|
-
|
|
271
|
+
LOG_DEVICE = Logger(PROG_NAME, found_level)
|
|
272
|
+
MOD_LOG_DEVICE = LOG_DEVICE.get_child("log_engine", found_level)
|
|
273
|
+
MOD_LOGGER = MOD_LOG_DEVICE.logger
|
|
274
|
+
MOD_LOGGER.debug(f"Started logger for {__name__}.")
|
|
315
275
|
|
|
316
|
-
|
|
317
|
-
log.debug(f"Caller self: {caller_self}")
|
|
276
|
+
add_child = LOG_DEVICE.get_child
|
|
318
277
|
|
|
319
|
-
|
|
320
|
-
if not isinstance(caller_self, self.__class__):
|
|
321
|
-
raise PermissionError(
|
|
322
|
-
"Access denied.\n"
|
|
323
|
-
f"Method can only be accessed by members of the same class. {caller_self.__class__.__name__} is not such a member"
|
|
324
|
-
)
|
|
278
|
+
InspyLogger = Logger
|
|
325
279
|
|
|
326
|
-
|
|
280
|
+
from inspy_logger.helpers.base_classes import Loggable
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import inspect
|
|
2
|
+
from inspy_logger import MOD_LOGGER, MOD_LOG_DEVICE, Logger
|
|
3
|
+
|
|
4
|
+
import inspect
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class LoggableDescriptor:
|
|
8
|
+
"""
|
|
9
|
+
Descriptor for accessing a logger specific to a class method.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
def __get__(self, instance, owner):
|
|
13
|
+
if instance is None:
|
|
14
|
+
# Accessing through the class, not an instance
|
|
15
|
+
return owner.class_logger
|
|
16
|
+
|
|
17
|
+
# Determine the calling method's name
|
|
18
|
+
stack = inspect.stack()
|
|
19
|
+
# Start from 1 to skip the current __get__ frame
|
|
20
|
+
for frame_record in stack[1:]:
|
|
21
|
+
if 'self' in frame_record.frame.f_locals:
|
|
22
|
+
if frame_record.frame.f_locals['self'] is instance:
|
|
23
|
+
method_name = frame_record.function
|
|
24
|
+
break
|
|
25
|
+
else:
|
|
26
|
+
raise Exception("Could not determine the calling method's name.")
|
|
27
|
+
|
|
28
|
+
# Get a child logger named after the class and method
|
|
29
|
+
return instance.log_device.get_child()
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def _get_parent_logging_device():
|
|
33
|
+
"""
|
|
34
|
+
Determines the parent logging device by inspecting the caller's log_device or parent_log_device attribute.
|
|
35
|
+
|
|
36
|
+
Returns:
|
|
37
|
+
Logger: The parent logging device.
|
|
38
|
+
"""
|
|
39
|
+
MOD_LOGGER.debug("Determining parent logging device")
|
|
40
|
+
caller_frame = inspect.currentframe().f_back
|
|
41
|
+
caller_locals = caller_frame.f_locals
|
|
42
|
+
|
|
43
|
+
if "logger" in caller_locals:
|
|
44
|
+
return caller_locals["logger"]
|
|
45
|
+
elif "parent_log_device" in caller_locals:
|
|
46
|
+
return caller_locals["parent_log_device"]
|
|
47
|
+
else:
|
|
48
|
+
raise ValueError("Unable to determine the parent logging device.")
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
class Loggable:
|
|
52
|
+
"""
|
|
53
|
+
A metaclass to enhance classes with logging capabilities. Classes that inherit from
|
|
54
|
+
'Loggable' can instantly access a logger without manually setting it up. This logger
|
|
55
|
+
is derived from a parent logger, ensuring consistent logging behavior and hierarchy.
|
|
56
|
+
|
|
57
|
+
Attributes:
|
|
58
|
+
- log_device: The logger device associated with the instance of the class.
|
|
59
|
+
"""
|
|
60
|
+
method_logger = LoggableDescriptor()
|
|
61
|
+
class_logger = None
|
|
62
|
+
|
|
63
|
+
def __init__(self, parent_log_device=None, **kwargs):
|
|
64
|
+
self.parent_log_device = parent_log_device
|
|
65
|
+
self.__log_name = self.__class__.__name__
|
|
66
|
+
if self.parent_log_device is not None:
|
|
67
|
+
self.__log_device = self.parent_log_device.get_child(self.__log_name)
|
|
68
|
+
else:
|
|
69
|
+
self.__log_device = _get_parent_logging_device().get_child()
|
|
70
|
+
|
|
71
|
+
# Set up class-level logger if it's not already set
|
|
72
|
+
if self.__class__.class_logger is None:
|
|
73
|
+
self.__class__.class_logger = self.__log_device
|
|
74
|
+
|
|
75
|
+
self.method_logger = self.__class__.method_logger.logger
|
|
76
|
+
|
|
77
|
+
@property
|
|
78
|
+
def log_device(self):
|
|
79
|
+
return self.__log_device
|
|
80
|
+
|
|
81
|
+
@log_device.setter
|
|
82
|
+
def log_device(self, new):
|
|
83
|
+
if not isinstance(new, Logger):
|
|
84
|
+
raise TypeError('log_device must be of type "Logger"')
|
|
85
|
+
|
|
86
|
+
self.__log_device = new
|
|
87
|
+
|
|
88
|
+
def create_child_logger(self, name=None, override=False):
|
|
89
|
+
"""
|
|
90
|
+
Creates and returns a child logger of this object's logger.
|
|
91
|
+
|
|
92
|
+
Parameters:
|
|
93
|
+
name (str, optional): The name of the child logger.
|
|
94
|
+
If not provided, the name of the calling function is used.
|
|
95
|
+
override (bool, optional): A flag to override the membership check. Defaults to False.
|
|
96
|
+
|
|
97
|
+
Returns:
|
|
98
|
+
Logger: An instance of the Logger class that represents the child logger.
|
|
99
|
+
"""
|
|
100
|
+
if not override:
|
|
101
|
+
self.__is_member__()
|
|
102
|
+
|
|
103
|
+
if name is None:
|
|
104
|
+
name = inspect.stack()[1][
|
|
105
|
+
3
|
|
106
|
+
] # Get the name of the calling function if no name is provided
|
|
107
|
+
#print(inspect.stack()[1])
|
|
108
|
+
return self.log_device.get_child(name)
|
|
109
|
+
|
|
110
|
+
def __is_member__(self):
|
|
111
|
+
"""
|
|
112
|
+
Checks whether the caller of this method is a member of the same class.
|
|
113
|
+
|
|
114
|
+
Raises:
|
|
115
|
+
PermissionError: If the caller of this method is not a member of the same class.
|
|
116
|
+
"""
|
|
117
|
+
log_device = self.log_device.get_child("__is_member__")
|
|
118
|
+
log = log_device.logger
|
|
119
|
+
|
|
120
|
+
current_frame = inspect.currentframe()
|
|
121
|
+
log.debug(f"Current frame: {current_frame}")
|
|
122
|
+
|
|
123
|
+
caller_frame = current_frame.f_back
|
|
124
|
+
log.debug(f"Caller frame: {caller_frame}")
|
|
125
|
+
|
|
126
|
+
caller_self = caller_frame.f_locals.get("self", None)
|
|
127
|
+
log.debug(f"Caller self: {caller_self}")
|
|
128
|
+
|
|
129
|
+
log.debug("Checking if caller is a member of this class...")
|
|
130
|
+
if not isinstance(caller_self, self.__class__):
|
|
131
|
+
raise PermissionError(
|
|
132
|
+
"Access denied.\n"
|
|
133
|
+
f"Method can only be accessed by members of the same class. {caller_self.__class__.__name__} is not such a member"
|
|
134
|
+
)
|
|
135
|
+
|
|
136
|
+
log.debug(f"Access granted to {caller_self.__class__.__name__}")
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "inspy-logger"
|
|
3
|
-
version = "3.0-dev.
|
|
3
|
+
version = "3.0-dev.3"
|
|
4
4
|
description = "Colorable, scalable logger for CLI"
|
|
5
5
|
authors = ["Taylor-Jayde Blackstone <tayjaybabee@gmail.com>"]
|
|
6
6
|
homepage = 'https://github.com/Inspyre-Softworks/inSPy-Logger'
|
|
@@ -28,7 +28,7 @@ classifiers = [
|
|
|
28
28
|
]
|
|
29
29
|
|
|
30
30
|
[tool.poetry.dependencies]
|
|
31
|
-
python = "
|
|
31
|
+
python = ">=3.9,<4.0"
|
|
32
32
|
colorlog = "^6.7"
|
|
33
33
|
setuptools-autover = "^1.0.2"
|
|
34
34
|
luddite = "^1.0.1"
|
|
@@ -42,15 +42,22 @@ rich = "^13.5.2"
|
|
|
42
42
|
|
|
43
43
|
[tool.poetry.dev-dependencies]
|
|
44
44
|
ptipython = "^1.0.1"
|
|
45
|
-
Sphinx = "^5.3.0"
|
|
46
|
-
sphinxcontrib-napoleon = "^0.7"
|
|
47
|
-
sphinx-rtd-theme = "^1.0.0"
|
|
48
45
|
asciinema = "^2.2.0"
|
|
49
46
|
bpython = "^0.23"
|
|
50
47
|
|
|
51
48
|
[tool.poetry.scripts]
|
|
52
49
|
inspy-logger-tool = "inspy_logger.Scripts.main:main"
|
|
53
50
|
|
|
51
|
+
[tool.poetry.group.docs.dependencies]
|
|
52
|
+
sphinx = "^7.2.6"
|
|
53
|
+
sphinx-autodoc-typehints = "^1.25.2"
|
|
54
|
+
sphinxcontrib-napoleon = "^0.7"
|
|
55
|
+
sphinx-rtd-theme = "^2.0.0"
|
|
56
|
+
sphinxcontrib-argdoc = "^0.1.3"
|
|
57
|
+
autoclasstoc = "^1.6.0"
|
|
58
|
+
sphinx-autodoc-annotation = "^1.0.post1"
|
|
59
|
+
sphinxcontrib-autoprogram = "^0.1.8"
|
|
60
|
+
|
|
54
61
|
[build-system]
|
|
55
62
|
requires = ["poetry-core>=1.0.0"]
|
|
56
63
|
build-backend = "poetry.core.masonry.api"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|