Skip to content

Commit bb50151

Browse files
committed
mostly working
1 parent eb66704 commit bb50151

File tree

7 files changed

+404
-0
lines changed

7 files changed

+404
-0
lines changed

.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -158,3 +158,6 @@ cython_debug/
158158
# and can be added to the global gitignore or merged into this file. For a more nuclear
159159
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
160160
#.idea/
161+
162+
images/
163+
.DS_Store

config/logging.conf

+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
[loggers]
2+
keys=root
3+
4+
[handlers]
5+
keys=stdout, stderr, file
6+
7+
[formatters]
8+
keys=timestampedLog, levelLog, simpleLog, timestampedLogWithName
9+
10+
[logger_root]
11+
level=DEBUG
12+
handlers=stdout, stdout, file
13+
14+
[handler_stdout]
15+
class=StreamHandler
16+
level=DEBUG
17+
formatter=simpleLog
18+
stream=ext://sys.stdout
19+
20+
[handler_stderr]
21+
class=StreamHandler
22+
level=ERROR
23+
formatter=levelLog
24+
stream=ext://sys.stdout
25+
26+
[handler_file]
27+
class=handlers.TimedRotatingFileHandler
28+
level=DEBUG
29+
formatter=timestampedLogWithName
30+
args=('logs/latest.log', "D", 1, 0)
31+
32+
[formatter_timestampedLogWithName]
33+
format=[%(asctime)-15s] %(levelname)-10s : %(message)s (%(locationClickable)s)
34+
35+
[formatter_timestampedLog]
36+
format=%(asctime)-15s %(levelname)-10s: %(message)s
37+
38+
[formatter_levelLog]
39+
format=%(levelname)-8s: %(message)s
40+
41+
[formatter_simpleLog]
42+
class=utils.Logger.ColorFormatter
43+
format=%(message)s
44+
45+
[formatter_customLogging]
46+
class=utils.Logger.CustomFormatter
47+
format=%(message)s

config/settings.json

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"logToFile": true,
3+
"loggingLevel": "INFO"
4+
}

requirements.txt

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
pillow==10.0.0
2+
pillow-avif-plugin==1.3.1
3+
argparse==1.4.0
4+
colorama==0.4.6

utils/Logger.py

+111
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
from colorama import Fore, Back
2+
import logging
3+
import logging.config
4+
from logging.handlers import TimedRotatingFileHandler
5+
import os
6+
import pathlib
7+
from utils.Settings import Setting as st
8+
Setting = st()
9+
10+
RESET_SEQ = "\033[0m"
11+
COLOR_SEQ = "\033[1;%dm"
12+
BOLD_SEQ = "\033[1m"
13+
14+
SECTION_LEVEL_NUM = 9
15+
16+
17+
class ColorFormatter(logging.Formatter):
18+
19+
def __init__(self, *args, **kwargs):
20+
# can't do super(...) here because Formatter is an old school class
21+
logging.Formatter.__init__(self, *args, **kwargs)
22+
23+
def format(self, record):
24+
if record.levelno == logging.DEBUG:
25+
self._style._fmt = Fore.LIGHTBLACK_EX + "%(message)s" + RESET_SEQ
26+
elif record.levelno == logging.ERROR:
27+
self._style._fmt = Fore.RED + \
28+
"%(levelname)s: %(message)s" + RESET_SEQ
29+
elif record.levelno == logging.CRITICAL:
30+
self._style._fmt = Back.WHITE + Fore.RED + \
31+
"%(levelname)s: %(message)s" + RESET_SEQ
32+
elif record.levelno == logging.WARNING:
33+
self._style._fmt = Fore.YELLOW + \
34+
"%(levelname)s: %(message)s" + RESET_SEQ
35+
elif record.levelno == logging.HEADER:
36+
self._style._fmt = Fore.LIGHTBLUE_EX + \
37+
"\n--- %(message)s ---" + RESET_SEQ
38+
elif record.levelno == logging.COMPLETION:
39+
self._style._fmt = Fore.GREEN + \
40+
"\n--- %(message)s ---" + RESET_SEQ
41+
elif record.levelno == logging.NOTE:
42+
self._style._fmt = Fore.LIGHTBLUE_EX + \
43+
"Note: " + RESET_SEQ + "%(message)s" + RESET_SEQ
44+
else:
45+
self._style._fmt = "%(message)s"
46+
return super().format(record)
47+
48+
49+
def combining_filter(record):
50+
record.location = '%s:%s:%s' % (
51+
record.module, record.funcName, record.lineno)
52+
record.locationClickable = '%s:%s' % (record.filename, record.lineno)
53+
return True
54+
55+
56+
def setup_logging(
57+
default_config='./config/logging.conf',
58+
default_level=Setting.loggingLevel
59+
):
60+
"""
61+
Setup logging configuration
62+
"""
63+
triedToCreateFile = False
64+
for i in range(0, 2):
65+
try:
66+
if os.path.exists(default_config):
67+
logging.config.fileConfig(
68+
default_config, disable_existing_loggers=False)
69+
else:
70+
logging.basicConfig(level=default_level)
71+
except (FileNotFoundError, OSError) as fnfe:
72+
try:
73+
loggingFilePath = pathlib.Path(fnfe.filename).parent
74+
loggingFilePath.mkdir(parents=True, exist_ok=True)
75+
except Exception as e:
76+
pass
77+
if triedToCreateFile:
78+
print(
79+
f"{Back.WHITE}{Fore.RED}CRITICAL: Cannot find or create the logging directory or file, exiting{Back.RESET}{Fore.RESET}")
80+
raise SystemExit(1)
81+
else:
82+
print(
83+
f"{Fore.RED}ERROR: Cannot find or create the logging directory or file {loggingFilePath}, creating one..{Fore.RESET}")
84+
triedToCreateFile = True
85+
continue
86+
87+
# logging level of notes should be just higher than info
88+
logging.NOTE = 21
89+
logging.addLevelName(logging.NOTE, "NOTE")
90+
91+
# logging level of header should be just higher than info
92+
logging.HEADER = 22
93+
logging.addLevelName(logging.HEADER, "HEADER")
94+
95+
# logging level of notes should be just higher than info
96+
logging.COMPLETION = 31
97+
logging.addLevelName(logging.COMPLETION, "COMPLETION")
98+
99+
for h in logging.root.handlers:
100+
if type(h) == logging.StreamHandler:
101+
h.setLevel(Setting.loggingLevel)
102+
if type(h) == TimedRotatingFileHandler:
103+
if not Setting.logToFile:
104+
logging.root.removeHandler(h)
105+
continue
106+
h.addFilter(combining_filter)
107+
h.namer = lambda name: str.replace(
108+
name, "latest.log.", "") + ".log"
109+
h.setLevel(logging.DEBUG)
110+
111+
logging.getLogger("PIL").setLevel(logging.DEBUG)

utils/Settings.py

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import json
2+
import logging
3+
import os
4+
5+
6+
class Setting():
7+
def __init__(self):
8+
settingsFileLocation = "./config/settings.json"
9+
settingsDictionary = {}
10+
LOGGING_LEVEL_MAPPER = {
11+
"INFO": logging.INFO,
12+
"WARNING": logging.WARNING,
13+
"WARN": logging.WARNING,
14+
"DEBUG": logging.DEBUG,
15+
"ERROR": logging.ERROR,
16+
"CRITICAL": logging.CRITICAL,
17+
}
18+
if os.path.exists(settingsFileLocation):
19+
with open(settingsFileLocation, "r") as f:
20+
settingsDictionary = json.load(f)
21+
22+
self._loggingLevel = LOGGING_LEVEL_MAPPER[settingsDictionary["loggingLevel"]
23+
] if "loggingLevel" in settingsDictionary.keys() else logging.INFO
24+
self._logToFile = settingsDictionary["logToFile"] if "logToFile" in settingsDictionary.keys(
25+
) else True
26+
27+
def alwaysTrue():
28+
return True
29+
30+
@property
31+
def loggingLevel(self):
32+
return int(self._loggingLevel)
33+
34+
@property
35+
def logToFile(self):
36+
return self._logToFile

0 commit comments

Comments
 (0)