MapleX 3.0.1__tar.gz → 3.1.0.dev1__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.
- {maplex-3.0.1/src/MapleX.egg-info → maplex-3.1.0.dev1}/PKG-INFO +1 -1
- {maplex-3.0.1 → maplex-3.1.0.dev1}/pyproject.toml +1 -1
- {maplex-3.0.1 → maplex-3.1.0.dev1/src/MapleX.egg-info}/PKG-INFO +1 -1
- {maplex-3.0.1 → maplex-3.1.0.dev1}/src/MapleX.egg-info/SOURCES.txt +7 -0
- {maplex-3.0.1 → maplex-3.1.0.dev1}/src/maplex/__init__.py +14 -2
- {maplex-3.0.1 → maplex-3.1.0.dev1}/src/maplex/json.py +91 -6
- maplex-3.1.0.dev1/src/maplex/library/logger/__init__.py +16 -0
- maplex-3.1.0.dev1/src/maplex/library/logger/config.py +344 -0
- maplex-3.1.0.dev1/src/maplex/library/logger/consts.py +17 -0
- maplex-3.1.0.dev1/src/maplex/library/logger/file_handler.py +3 -0
- maplex-3.1.0.dev1/src/maplex/library/logger/formatter.py +4 -0
- maplex-3.1.0.dev1/src/maplex/library/logger/log_levels.py +15 -0
- maplex-3.1.0.dev1/src/maplex/library/logger/utilities.py +114 -0
- {maplex-3.0.1 → maplex-3.1.0.dev1}/src/maplex/mapleColors.py +16 -1
- maplex-3.1.0.dev1/src/maplex/mapleLogger.py +450 -0
- maplex-3.0.1/src/maplex/mapleLogger.py +0 -848
- {maplex-3.0.1 → maplex-3.1.0.dev1}/LICENSE +0 -0
- {maplex-3.0.1 → maplex-3.1.0.dev1}/MANIFEST.in +0 -0
- {maplex-3.0.1 → maplex-3.1.0.dev1}/README.md +0 -0
- {maplex-3.0.1 → maplex-3.1.0.dev1}/logErrorOutputSample.png +0 -0
- {maplex-3.0.1 → maplex-3.1.0.dev1}/logOutputSample.png +0 -0
- {maplex-3.0.1 → maplex-3.1.0.dev1}/readmes/LoggingBestPractice.md +0 -0
- {maplex-3.0.1 → maplex-3.1.0.dev1}/readmes/README_ConsoleColors.md +0 -0
- {maplex-3.0.1 → maplex-3.1.0.dev1}/readmes/README_Exceptions.md +0 -0
- {maplex-3.0.1 → maplex-3.1.0.dev1}/readmes/README_Json.md +0 -0
- {maplex-3.0.1 → maplex-3.1.0.dev1}/readmes/README_Logger.md +0 -0
- {maplex-3.0.1 → maplex-3.1.0.dev1}/readmes/README_MapleTree.md +0 -0
- {maplex-3.0.1 → maplex-3.1.0.dev1}/setup.cfg +0 -0
- {maplex-3.0.1 → maplex-3.1.0.dev1}/src/MapleX.egg-info/dependency_links.txt +0 -0
- {maplex-3.0.1 → maplex-3.1.0.dev1}/src/MapleX.egg-info/requires.txt +0 -0
- {maplex-3.0.1 → maplex-3.1.0.dev1}/src/MapleX.egg-info/top_level.txt +0 -0
- {maplex-3.0.1 → maplex-3.1.0.dev1}/src/maplex/mapleExceptions.py +0 -0
- {maplex-3.0.1 → maplex-3.1.0.dev1}/src/maplex/mapleTreeEditor.py +0 -0
- {maplex-3.0.1 → maplex-3.1.0.dev1}/src/maplex/utils.py +0 -0
- {maplex-3.0.1 → maplex-3.1.0.dev1}/tests/test_logger_unittest.py +0 -0
- {maplex-3.0.1 → maplex-3.1.0.dev1}/tests/test_maplejson_unittest.py +0 -0
- {maplex-3.0.1 → maplex-3.1.0.dev1}/tests/test_mapletree_unittest.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: MapleX
|
|
3
|
-
Version: 3.0.
|
|
3
|
+
Version: 3.1.0.dev1
|
|
4
4
|
Summary: A Python library for simple logging, json file operations, Maple file format operations, and console color utilities.
|
|
5
5
|
Author: Ryuji Hazama
|
|
6
6
|
Project-URL: PyPI, https://pypi.org/project/MapleX/
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "MapleX"
|
|
7
|
-
version = "3.0.
|
|
7
|
+
version = "3.1.0.dev1"
|
|
8
8
|
description = """A Python library for simple logging, json file operations, Maple file format operations, and console color utilities."""
|
|
9
9
|
keywords = ["logging", "logger", "json", "file operations", "maple file format", "console colors"]
|
|
10
10
|
readme = "README.md"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: MapleX
|
|
3
|
-
Version: 3.0.
|
|
3
|
+
Version: 3.1.0.dev1
|
|
4
4
|
Summary: A Python library for simple logging, json file operations, Maple file format operations, and console color utilities.
|
|
5
5
|
Author: Ryuji Hazama
|
|
6
6
|
Project-URL: PyPI, https://pypi.org/project/MapleX/
|
|
@@ -22,6 +22,13 @@ src/maplex/mapleExceptions.py
|
|
|
22
22
|
src/maplex/mapleLogger.py
|
|
23
23
|
src/maplex/mapleTreeEditor.py
|
|
24
24
|
src/maplex/utils.py
|
|
25
|
+
src/maplex/library/logger/__init__.py
|
|
26
|
+
src/maplex/library/logger/config.py
|
|
27
|
+
src/maplex/library/logger/consts.py
|
|
28
|
+
src/maplex/library/logger/file_handler.py
|
|
29
|
+
src/maplex/library/logger/formatter.py
|
|
30
|
+
src/maplex/library/logger/log_levels.py
|
|
31
|
+
src/maplex/library/logger/utilities.py
|
|
25
32
|
tests/test_logger_unittest.py
|
|
26
33
|
tests/test_maplejson_unittest.py
|
|
27
34
|
tests/test_mapletree_unittest.py
|
|
@@ -49,6 +49,18 @@ __all__ = [
|
|
|
49
49
|
'winUnHide'
|
|
50
50
|
]
|
|
51
51
|
|
|
52
|
-
__version__ = "3.0.
|
|
52
|
+
__version__ = "3.1.0.dev1"
|
|
53
53
|
__author__ = "Ryuji Hazama"
|
|
54
|
-
__license__ = "MIT"
|
|
54
|
+
__license__ = "MIT"
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
""" * * * * * * * * * * * * * """
|
|
58
|
+
"""
|
|
59
|
+
ToDo list:
|
|
60
|
+
|
|
61
|
+
* MapleX *
|
|
62
|
+
|
|
63
|
+
- Restructure MapleX to be more modular and maintainable
|
|
64
|
+
|
|
65
|
+
"""
|
|
66
|
+
""" * * * * * * * * * * * * * """
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import datetime
|
|
1
2
|
import json
|
|
2
3
|
import os
|
|
3
4
|
import base64
|
|
@@ -6,6 +7,10 @@ from . import mapleExceptions as mExc
|
|
|
6
7
|
|
|
7
8
|
class MapleJson:
|
|
8
9
|
|
|
10
|
+
"""
|
|
11
|
+
MapleJson is a utility class for handling JSON files with optional encryption support. It provides methods to read and write JSON data, as well as manage encryption keys.
|
|
12
|
+
"""
|
|
13
|
+
|
|
9
14
|
def __init__(self,
|
|
10
15
|
filePath: str,
|
|
11
16
|
fileEncoding: str = 'utf-8',
|
|
@@ -15,6 +20,17 @@ class MapleJson:
|
|
|
15
20
|
key: bytes = None
|
|
16
21
|
) -> None:
|
|
17
22
|
|
|
23
|
+
"""
|
|
24
|
+
Initialize a MapleJson instance.
|
|
25
|
+
|
|
26
|
+
:param filePath: Path to the JSON file.
|
|
27
|
+
:param fileEncoding: Encoding of the JSON file.
|
|
28
|
+
:param indent: Indentation level for JSON formatting.
|
|
29
|
+
:param ensureAscii: Whether to ensure ASCII characters in JSON.
|
|
30
|
+
:param encrypt: Whether to encrypt the JSON file.
|
|
31
|
+
:param key: Encryption key for the JSON file.
|
|
32
|
+
"""
|
|
33
|
+
|
|
18
34
|
self.filePath = filePath
|
|
19
35
|
self.fileEncoding = fileEncoding
|
|
20
36
|
self.indent = indent
|
|
@@ -87,7 +103,7 @@ class MapleJson:
|
|
|
87
103
|
#####################
|
|
88
104
|
# Basic File Operations
|
|
89
105
|
|
|
90
|
-
def read(self, *keys: str) ->
|
|
106
|
+
def read(self, *keys: str) -> object | None:
|
|
91
107
|
|
|
92
108
|
try:
|
|
93
109
|
|
|
@@ -125,16 +141,52 @@ class MapleJson:
|
|
|
125
141
|
except Exception as e:
|
|
126
142
|
|
|
127
143
|
raise mExc.MapleException(f"Error reading JSON file: {e}")
|
|
144
|
+
|
|
145
|
+
def readOrDefault(self, default: object, *keys: str) -> object:
|
|
146
|
+
|
|
147
|
+
result = self.read(*keys)
|
|
148
|
+
return result if result is not None else default
|
|
128
149
|
|
|
129
|
-
def write(self, data:
|
|
150
|
+
def write(self, data: object, *keys: str) -> None:
|
|
130
151
|
|
|
131
152
|
try:
|
|
132
153
|
|
|
133
|
-
if
|
|
154
|
+
if len(keys) > 0:
|
|
155
|
+
|
|
156
|
+
# Read existing data to preserve other keys
|
|
157
|
+
|
|
158
|
+
existingData = self.read() or {}
|
|
159
|
+
|
|
160
|
+
# Navigate to the correct location in the nested structure
|
|
161
|
+
|
|
162
|
+
currentLevel = existingData
|
|
163
|
+
|
|
164
|
+
for i, jsonKey in enumerate(keys):
|
|
165
|
+
|
|
166
|
+
if i == len(keys) - 1:
|
|
167
|
+
|
|
168
|
+
currentLevel[jsonKey] = data
|
|
169
|
+
|
|
170
|
+
else:
|
|
171
|
+
|
|
172
|
+
if jsonKey not in currentLevel or not isinstance(currentLevel[jsonKey], dict):
|
|
173
|
+
|
|
174
|
+
currentLevel[jsonKey] = {}
|
|
175
|
+
|
|
176
|
+
currentLevel = currentLevel[jsonKey]
|
|
177
|
+
|
|
178
|
+
dataToWrite = existingData
|
|
134
179
|
|
|
135
|
-
|
|
180
|
+
else:
|
|
181
|
+
|
|
182
|
+
dataToWrite = data
|
|
136
183
|
|
|
137
|
-
jsonData = json.dumps(
|
|
184
|
+
jsonData = json.dumps(
|
|
185
|
+
dataToWrite,
|
|
186
|
+
indent=self.indent,
|
|
187
|
+
ensure_ascii=self.ensureAscii,
|
|
188
|
+
default=self.datetimeSerializer
|
|
189
|
+
).encode(self.fileEncoding)
|
|
138
190
|
|
|
139
191
|
if self.encrypt and self.fernet:
|
|
140
192
|
|
|
@@ -181,6 +233,30 @@ class MapleJson:
|
|
|
181
233
|
|
|
182
234
|
return key
|
|
183
235
|
|
|
236
|
+
def datetimeSerializer(self, obj: object) -> str:
|
|
237
|
+
|
|
238
|
+
if isinstance(obj, (datetime.datetime, datetime.date)):
|
|
239
|
+
|
|
240
|
+
return obj.isoformat()
|
|
241
|
+
|
|
242
|
+
raise TypeError(f"Type {type(obj)} not serializable")
|
|
243
|
+
|
|
244
|
+
def datetimeDeserializer(self, obj: str) -> datetime.datetime | datetime.date | str:
|
|
245
|
+
|
|
246
|
+
try:
|
|
247
|
+
|
|
248
|
+
return datetime.datetime.fromisoformat(obj)
|
|
249
|
+
|
|
250
|
+
except ValueError:
|
|
251
|
+
|
|
252
|
+
try:
|
|
253
|
+
|
|
254
|
+
return datetime.date.fromisoformat(obj)
|
|
255
|
+
|
|
256
|
+
except ValueError:
|
|
257
|
+
|
|
258
|
+
return obj
|
|
259
|
+
|
|
184
260
|
_json: dict[str, MapleJson] = {}
|
|
185
261
|
|
|
186
262
|
# Get or create a MapleJson instance
|
|
@@ -202,4 +278,13 @@ def getMapleJson(filePath: str,
|
|
|
202
278
|
encrypt,
|
|
203
279
|
key)
|
|
204
280
|
|
|
205
|
-
return _json[filePath]
|
|
281
|
+
return _json[filePath]
|
|
282
|
+
|
|
283
|
+
""" * * * * * * * * * * * * * """
|
|
284
|
+
"""
|
|
285
|
+
ToDo list:
|
|
286
|
+
|
|
287
|
+
* Json *
|
|
288
|
+
|
|
289
|
+
"""
|
|
290
|
+
""" * * * * * * * * * * * * * """
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Split mapleLogger.py into multiple files for better organization and maintainability.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from .config import LoggerConfig
|
|
6
|
+
from .log_levels import LogLevel
|
|
7
|
+
from .utilities import *
|
|
8
|
+
|
|
9
|
+
__all__ = [
|
|
10
|
+
"LoggerConfig",
|
|
11
|
+
"LogLevel",
|
|
12
|
+
"getConsoleColors",
|
|
13
|
+
"toLogLevel",
|
|
14
|
+
"toLogSize",
|
|
15
|
+
"isLogLevel"
|
|
16
|
+
]
|
|
@@ -0,0 +1,344 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Move configu helper functions to a separate file to avoid circular imports and improve code organization
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from datetime import datetime
|
|
6
|
+
import inspect
|
|
7
|
+
from typing import Literal
|
|
8
|
+
import os
|
|
9
|
+
from os import path
|
|
10
|
+
from pydantic import BaseModel
|
|
11
|
+
|
|
12
|
+
from src.maplex.mapleColors import ConsoleColors
|
|
13
|
+
from src.maplex.mapleExceptions import *
|
|
14
|
+
from src.maplex.json import MapleJson
|
|
15
|
+
from .consts import *
|
|
16
|
+
from .utilities import *
|
|
17
|
+
from src.maplex.library.logger.log_levels import LogLevel
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class LoggerConfig(BaseModel):
|
|
21
|
+
|
|
22
|
+
func: str | None = None
|
|
23
|
+
callerName: str | None = None
|
|
24
|
+
workingDirectory: str | None = None
|
|
25
|
+
consoleLogLevel: Literal["TRACE", "DEBUG", "INFO", "WARN", "ERROR", "FATAL", "NONE"] | None = None
|
|
26
|
+
fileLogLevel: Literal["TRACE", "DEBUG", "INFO", "WARN", "ERROR", "FATAL", "NONE"] | None = None
|
|
27
|
+
maxLogSize: int | None = None
|
|
28
|
+
fileMode: Literal["append", "overwrite", "daily"] | None = None
|
|
29
|
+
configFile: str = "config.json"
|
|
30
|
+
encoding: str | None = None
|
|
31
|
+
timestampFormat: str | None = None
|
|
32
|
+
getLogger: bool | None = None
|
|
33
|
+
consoleAlignWidth: int | None = None
|
|
34
|
+
fileAlignWidth: int | None = None
|
|
35
|
+
|
|
36
|
+
logConfInstance: None = None
|
|
37
|
+
logConf: dict[str, object] | None = None
|
|
38
|
+
logfile: str | None = None
|
|
39
|
+
pid: int = os.getpid()
|
|
40
|
+
|
|
41
|
+
consoleColors: ConsoleColors | None = None
|
|
42
|
+
|
|
43
|
+
def __init__(self, config: dict[str, object]) -> None:
|
|
44
|
+
|
|
45
|
+
try:
|
|
46
|
+
|
|
47
|
+
super().__init__(**config)
|
|
48
|
+
self.consoleColors = getConsoleColors()
|
|
49
|
+
|
|
50
|
+
self.logConfInstance = self.checkConfigFile(config.get(CONFIG_FILE, self.configFile))
|
|
51
|
+
self.checkOutputDirectory(config.get(WORKING_DIRECTORY, None))
|
|
52
|
+
self.setLogFileName(config.get(FILE_MODE, "append"))
|
|
53
|
+
self.setFuncName(config.get(GET_LOGGER, False), config.get(FUNC, None))
|
|
54
|
+
self.setAlignWidth(config.get(CONSOLE_ALIGN_WIDTH, None), config.get(FILE_ALIGN_WIDTH, None))
|
|
55
|
+
self.setLogFileSize(config.get(MAX_LOG_SIZE, None))
|
|
56
|
+
self.setOutputLogLevels(config.get(CONSOLE_LOG_LEVEL, None), config.get(FILE_LOG_LEVEL, None))
|
|
57
|
+
self.setFileEncoding(config.get(FILE_ENCODING, None))
|
|
58
|
+
self.setTimestampFormat(config.get(TIMESTAMP_FORMAT, None))
|
|
59
|
+
self.saveLogSettings(self.logConfInstance)
|
|
60
|
+
|
|
61
|
+
except Exception as ex:
|
|
62
|
+
|
|
63
|
+
print(f"{self.consoleColors.Red}Error: Failed to initialize logger config: {ex}{self.consoleColors.Reset}")
|
|
64
|
+
raise ex
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def checkConfigFile(self, configFile: str) -> MapleJson | None:
|
|
68
|
+
|
|
69
|
+
# Set config file path
|
|
70
|
+
|
|
71
|
+
self.configFile = self.checkFilePath(configFile)
|
|
72
|
+
|
|
73
|
+
# Try to read config file
|
|
74
|
+
|
|
75
|
+
try:
|
|
76
|
+
|
|
77
|
+
logConfInstance = MapleJson(self.configFile)
|
|
78
|
+
|
|
79
|
+
if path.isfile(self.configFile):
|
|
80
|
+
|
|
81
|
+
confJson = logConfInstance.read()
|
|
82
|
+
|
|
83
|
+
else:
|
|
84
|
+
|
|
85
|
+
confJson = {}
|
|
86
|
+
|
|
87
|
+
except Exception as ex:
|
|
88
|
+
|
|
89
|
+
print(f"{self.consoleColors.Red}Warning: Failed to read logger config file: {ex}{self.consoleColors.Reset}")
|
|
90
|
+
confJson = {}
|
|
91
|
+
logConfInstance = None
|
|
92
|
+
|
|
93
|
+
# Read configuration
|
|
94
|
+
|
|
95
|
+
logConf = confJson.get(CONFIG_KEY, None)
|
|
96
|
+
|
|
97
|
+
if logConf is None:
|
|
98
|
+
|
|
99
|
+
logConf = {}
|
|
100
|
+
logConf[CONSOLE_LOG_LEVEL] = "INFO"
|
|
101
|
+
logConf[FILE_LOG_LEVEL] = "INFO"
|
|
102
|
+
logConf[MAX_LOG_SIZE] = 3
|
|
103
|
+
logConf[WORKING_DIRECTORY] = "logs"
|
|
104
|
+
|
|
105
|
+
self.logConf = logConf
|
|
106
|
+
return logConfInstance
|
|
107
|
+
|
|
108
|
+
def checkFilePath(self, filePath: str) -> str:
|
|
109
|
+
|
|
110
|
+
'''Check and return absolute file path'''
|
|
111
|
+
|
|
112
|
+
if path.isabs(filePath):
|
|
113
|
+
|
|
114
|
+
return filePath
|
|
115
|
+
|
|
116
|
+
else:
|
|
117
|
+
|
|
118
|
+
return path.join(os.getcwd(), filePath)
|
|
119
|
+
|
|
120
|
+
def checkOutputDirectory(self, outputDir: str) -> None:
|
|
121
|
+
|
|
122
|
+
'''Check and set output directory'''
|
|
123
|
+
|
|
124
|
+
# Check parameter and config file
|
|
125
|
+
|
|
126
|
+
if outputDir is not None:
|
|
127
|
+
|
|
128
|
+
self.workingDirectory = outputDir
|
|
129
|
+
|
|
130
|
+
else:
|
|
131
|
+
|
|
132
|
+
self.workingDirectory = self.logConf.get(WORKING_DIRECTORY, None)
|
|
133
|
+
|
|
134
|
+
# Set absolute path
|
|
135
|
+
|
|
136
|
+
if self.workingDirectory in {"", None}:
|
|
137
|
+
|
|
138
|
+
self.workingDirectory = path.join(os.getcwd(), "logs")
|
|
139
|
+
self.logConf[WORKING_DIRECTORY] = self.workingDirectory
|
|
140
|
+
|
|
141
|
+
elif not path.isabs(self.workingDirectory):
|
|
142
|
+
|
|
143
|
+
self.workingDirectory = path.join(os.getcwd(), self.workingDirectory)
|
|
144
|
+
|
|
145
|
+
# Check if directory exists
|
|
146
|
+
|
|
147
|
+
if not path.isdir(self.workingDirectory):
|
|
148
|
+
|
|
149
|
+
os.makedirs(self.workingDirectory)
|
|
150
|
+
|
|
151
|
+
def setLogFileName(self, fileMode: str) -> None:
|
|
152
|
+
|
|
153
|
+
'''Set log file name'''
|
|
154
|
+
|
|
155
|
+
if fileMode == "daily":
|
|
156
|
+
|
|
157
|
+
self.logfile = path.join(self.workingDirectory, f"log_{datetime.now():%Y%m%d}.log")
|
|
158
|
+
|
|
159
|
+
else:
|
|
160
|
+
|
|
161
|
+
self.logfile = path.join(self.workingDirectory, "AppLog.log")
|
|
162
|
+
|
|
163
|
+
def setFuncName(self, isGetLogger: bool, func: str | None = None) -> None:
|
|
164
|
+
|
|
165
|
+
if isGetLogger:
|
|
166
|
+
|
|
167
|
+
caller = inspect.stack()[3].frame.f_globals.get("__name__", "")
|
|
168
|
+
|
|
169
|
+
else:
|
|
170
|
+
|
|
171
|
+
caller = inspect.stack()[2].frame.f_globals.get("__name__", "")
|
|
172
|
+
|
|
173
|
+
if func in {None, ""}:
|
|
174
|
+
|
|
175
|
+
self.func = ""
|
|
176
|
+
self.callerName = ""
|
|
177
|
+
|
|
178
|
+
elif func != caller:
|
|
179
|
+
|
|
180
|
+
self.func = f"[{func}]"
|
|
181
|
+
self.callerName = ""
|
|
182
|
+
|
|
183
|
+
else:
|
|
184
|
+
|
|
185
|
+
self.func = ""
|
|
186
|
+
self.callerName = f"{caller}."
|
|
187
|
+
|
|
188
|
+
def setAlignWidth(self, consoleAlignWidth: int | None = None, fileAlignWidth: int | None = None) -> None:
|
|
189
|
+
|
|
190
|
+
'''Set function name alignment width'''
|
|
191
|
+
|
|
192
|
+
if consoleAlignWidth is not None and type(consoleAlignWidth) is int and consoleAlignWidth > 0:
|
|
193
|
+
|
|
194
|
+
self.consoleAlignWidth = consoleAlignWidth
|
|
195
|
+
|
|
196
|
+
else:
|
|
197
|
+
|
|
198
|
+
self.consoleAlignWidth = 16
|
|
199
|
+
|
|
200
|
+
if fileAlignWidth is not None and type(fileAlignWidth) is int and fileAlignWidth > 0:
|
|
201
|
+
|
|
202
|
+
self.fileAlignWidth = fileAlignWidth
|
|
203
|
+
|
|
204
|
+
else:
|
|
205
|
+
|
|
206
|
+
self.fileAlignWidth = 4
|
|
207
|
+
|
|
208
|
+
def setLogFileSize(self, maxLogSize: object) -> None:
|
|
209
|
+
|
|
210
|
+
self.maxLogSize = 0
|
|
211
|
+
|
|
212
|
+
if maxLogSize is not None:
|
|
213
|
+
|
|
214
|
+
self.setMaxLogSize(maxLogSize)
|
|
215
|
+
|
|
216
|
+
else:
|
|
217
|
+
|
|
218
|
+
try:
|
|
219
|
+
|
|
220
|
+
logSize = self.logConf.get(MAX_LOG_SIZE, None)
|
|
221
|
+
|
|
222
|
+
if logSize is not None:
|
|
223
|
+
|
|
224
|
+
self.setMaxLogSize(logSize)
|
|
225
|
+
|
|
226
|
+
else:
|
|
227
|
+
|
|
228
|
+
self.maxLogSize = 3000000
|
|
229
|
+
self.logConf[MAX_LOG_SIZE] = 3
|
|
230
|
+
|
|
231
|
+
except MapleLoggerException as ex:
|
|
232
|
+
|
|
233
|
+
print(f"{self.consoleColors.Red}Warning: Invalid MaxLogSize value provided. Using default value.{self.consoleColors.Reset}")
|
|
234
|
+
self.maxLogSize = 3000000
|
|
235
|
+
|
|
236
|
+
if self.maxLogSize == 0:
|
|
237
|
+
|
|
238
|
+
print(f"{self.consoleColors.Red}Warning: Infinite log file size is not recommended. Using default value.{self.consoleColors.Reset}")
|
|
239
|
+
self.maxLogSize = 3000000
|
|
240
|
+
|
|
241
|
+
def setOutputLogLevels(self, cmdLogLevel: object, fileLogLevel: object) -> None:
|
|
242
|
+
|
|
243
|
+
self.consoleLogLevel = self.__setLogLevel(CONSOLE_LOG_LEVEL, cmdLogLevel)
|
|
244
|
+
self.fileLogLevel = self.__setLogLevel(FILE_LOG_LEVEL, fileLogLevel)
|
|
245
|
+
|
|
246
|
+
def __setLogLevel(self, fileOrConsole, loglevel: object) -> LogLevel:
|
|
247
|
+
|
|
248
|
+
'''Set log level'''
|
|
249
|
+
|
|
250
|
+
if loglevel is not None:
|
|
251
|
+
|
|
252
|
+
tempLogLevel = loglevel
|
|
253
|
+
|
|
254
|
+
else:
|
|
255
|
+
|
|
256
|
+
tempLogLevel = self.logConf.get(fileOrConsole, "INFO")
|
|
257
|
+
|
|
258
|
+
if tempLogLevel is None:
|
|
259
|
+
|
|
260
|
+
tempLogLevel = "INFO"
|
|
261
|
+
self.logConf[fileOrConsole] = tempLogLevel
|
|
262
|
+
|
|
263
|
+
try:
|
|
264
|
+
|
|
265
|
+
return toLogLevel(tempLogLevel)
|
|
266
|
+
|
|
267
|
+
except MapleInvalidLoggerLevelException as ex:
|
|
268
|
+
|
|
269
|
+
print(f"{self.consoleColors.Red}Warning: Invalid {fileOrConsole} provided: [{tempLogLevel}]. Using default value.{self.consoleColors.Reset}")
|
|
270
|
+
return self.LogLevel.INFO
|
|
271
|
+
|
|
272
|
+
def setFileEncoding(self, encoding: str) -> None:
|
|
273
|
+
|
|
274
|
+
if encoding is not None:
|
|
275
|
+
|
|
276
|
+
self.encoding = encoding
|
|
277
|
+
|
|
278
|
+
else:
|
|
279
|
+
|
|
280
|
+
fileEncoding = self.logConf.get(FILE_ENCODING, None)
|
|
281
|
+
|
|
282
|
+
if fileEncoding is None:
|
|
283
|
+
|
|
284
|
+
fileEncoding = "utf-8"
|
|
285
|
+
self.logConf[FILE_ENCODING] = fileEncoding
|
|
286
|
+
|
|
287
|
+
self.encoding = fileEncoding
|
|
288
|
+
|
|
289
|
+
def setTimestampFormat(self, timestampFormat: str) -> None:
|
|
290
|
+
|
|
291
|
+
"""Set timestamp format for logs. Default is "%F %X.%f" (e.g. 2024-06-01 12:34:56.789). You can set this in config file with key "TimestampFormat"."""
|
|
292
|
+
|
|
293
|
+
if timestampFormat is not None:
|
|
294
|
+
|
|
295
|
+
self.timestampFormat = timestampFormat
|
|
296
|
+
|
|
297
|
+
else:
|
|
298
|
+
|
|
299
|
+
configTimestampFormat = self.logConf.get(TIMESTAMP_FORMAT, None)
|
|
300
|
+
|
|
301
|
+
if configTimestampFormat is None:
|
|
302
|
+
|
|
303
|
+
configTimestampFormat = "%F %X.%f"
|
|
304
|
+
self.logConf[TIMESTAMP_FORMAT] = configTimestampFormat
|
|
305
|
+
|
|
306
|
+
self.timestampFormat = configTimestampFormat
|
|
307
|
+
|
|
308
|
+
def saveLogSettings(self, logConfInstance: MapleJson | None) -> None:
|
|
309
|
+
|
|
310
|
+
""" Save current log settings to config file """
|
|
311
|
+
|
|
312
|
+
if logConfInstance is not None:
|
|
313
|
+
|
|
314
|
+
try:
|
|
315
|
+
|
|
316
|
+
confJson = logConfInstance.read()
|
|
317
|
+
|
|
318
|
+
except Exception:
|
|
319
|
+
|
|
320
|
+
confJson = {}
|
|
321
|
+
|
|
322
|
+
try:
|
|
323
|
+
|
|
324
|
+
confJson[CONFIG_KEY] = self.logConf
|
|
325
|
+
logConfInstance.write(confJson)
|
|
326
|
+
|
|
327
|
+
except Exception as ex:
|
|
328
|
+
|
|
329
|
+
print(f"{self.consoleColors.Red}Warning: Failed to write logger config file: {ex}{self.consoleColors.Reset}")
|
|
330
|
+
|
|
331
|
+
###########################
|
|
332
|
+
# Seters and getters
|
|
333
|
+
|
|
334
|
+
def setMaxLogSize(self, maxLogSize: object) -> None:
|
|
335
|
+
|
|
336
|
+
'''Set max log size'''
|
|
337
|
+
|
|
338
|
+
try:
|
|
339
|
+
|
|
340
|
+
self.maxLogSize = toLogSize(maxLogSize)
|
|
341
|
+
|
|
342
|
+
except MapleLoggerException as ex:
|
|
343
|
+
|
|
344
|
+
raise MapleLoggerException("Invalid max log size. Log size must be an integer, float or string.") from ex
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
|
|
2
|
+
CONFIG_KEY = "MapleLogger"
|
|
3
|
+
FUNC = "func"
|
|
4
|
+
CONSOLE = "Console"
|
|
5
|
+
FILE = "File"
|
|
6
|
+
CONSOLE_LOG_LEVEL = "ConsoleLogLevel"
|
|
7
|
+
FILE_LOG_LEVEL = "FileLogLevel"
|
|
8
|
+
MAX_LOG_SIZE = "MaxLogSize"
|
|
9
|
+
FILE_MODE = "FileMode"
|
|
10
|
+
CONFIG_FILE = "configFile"
|
|
11
|
+
WORKING_DIRECTORY = "WorkingDirectory"
|
|
12
|
+
FILE_ENCODING = "FileEncoding"
|
|
13
|
+
TIMESTAMP_FORMAT = "TimestampFormat"
|
|
14
|
+
ALIGN_WIDTH = "AlignWidth"
|
|
15
|
+
GET_LOGGER = "getLogger"
|
|
16
|
+
CONSOLE_ALIGN_WIDTH = "consoleAlignWidth"
|
|
17
|
+
FILE_ALIGN_WIDTH = "fileAlignWidth"
|