Skip to content

Commit b035686

Browse files
committed
ADDED: logging, logo, rlc l00 and l03
1 parent 00babaa commit b035686

8 files changed

Lines changed: 404 additions & 209 deletions

File tree

requirements.txt

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
pypdf
1+
PyPDF2
22
pandas
33
openpyxl
4-
5-
Office365-REST-Python-Client
4+
PyCryptodome
5+
Office365-REST-Python-Client
6+
pyfiglet

src/NAF.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import pandas as pd
44

55
from defines import NAF_DATA_PATH
6+
from custom_except import ArgumentNafInvalid, ArgumentNafNotPresent
67

78

89
class NAF:
@@ -46,15 +47,20 @@ def is_naf_correct(naf):
4647
return True
4748

4849

49-
def validate_naf(value, valid_nafs):
50+
def validate_parse_naf(value, valid_nafs):
5051
if not is_naf_correct(value):
51-
raise ValueError("Naf " + value + " is not valid.")
52+
raise ArgumentNafInvalid("Naf " + value + " is not valid.")
5253
elif NAF(value) not in valid_nafs:
53-
raise ValueError("NAF value " + value + " is not in our NAF database (input/NAF_DNI.xlsx)")
54+
raise ArgumentNafNotPresent("NAF value " + value + " is not in our NAF database (input/NAF_DNI.xlsx)")
5455
else:
5556
return NAF(value)
5657

5758

59+
def clean_naf(naf):
60+
"Removes symbols that are not numbers in a SS number"
61+
return naf.replace("/", "").replace("-", "")
62+
63+
5864
def build_naf_to_dni(path):
5965
# Read the Excel file, skipping the first 3 rows
6066
df = pd.read_excel(path, skiprows=3, header=None)

src/arguments.py

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
import argparse
22
import datetime
3+
import sys
34
from functools import partial
45

5-
from NAF import NAF_TO_DNI, validate_naf
6+
from NAF import NAF_TO_DNI, validate_parse_naf
67
from custom_except import *
8+
from defines import NAF_DATA_PATH
79

810

911
def parse_date(value, formatting="%Y_%m"):
@@ -25,9 +27,9 @@ def parse_author(author):
2527

2628
def parse_naf(value):
2729
try:
28-
return validate_naf(value, NAF_TO_DNI.keys())
30+
return validate_parse_naf(value, NAF_TO_DNI.keys())
2931
except ValueError as e:
30-
raise ArgumentNafError("NAF is not valid" + e.__str__())
32+
raise ArgumentNafNotPresent("NAF is not valid" + e.__str__())
3133

3234

3335
def parse_arguments(valid_nafs):
@@ -43,3 +45,36 @@ def parse_arguments(valid_nafs):
4345
args = parser.parse_args()
4446

4547
return args
48+
49+
50+
def process_arguments():
51+
common = ("Error parsing arguments. Program aborting. The arguments are: "
52+
+ str(sys.argv) + "The program is in a uninitialized state and cannot proceed. This error will be "
53+
"notified to the admin via log file. We can't create log file in user author folder "
54+
"because user author could not be parsed.")
55+
try:
56+
args = parse_arguments(NAF_TO_DNI.keys())
57+
58+
except ArgumentNafNotPresent as e:
59+
print("The NAF provided is valid but is not present in " + NAF_DATA_PATH + ". Internal error is " + e.__str__())
60+
print(common)
61+
exit(1)
62+
except ArgumentNafInvalid as e:
63+
print("The NAF provided is invalid. Internal error is " + e.__str__())
64+
print(common)
65+
exit(2)
66+
except ArgumentDateError as e:
67+
print("The dates provided are invalid. Internal error is " + e.__str__())
68+
print(common)
69+
exit(3)
70+
except ArgumentAuthorError as e:
71+
print("The author is not present in the accepted user list. Internal error is " + e.__str__())
72+
print(common)
73+
exit(4)
74+
except argparse.ArgumentTypeError as e:
75+
print("Arguments could not have been parsed. Internal error is " + e.__str__())
76+
print(common)
77+
exit(5)
78+
return args
79+
80+

src/custom_except.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,13 @@ class ArgumentDateError(Exception):
33
pass
44

55

6-
class ArgumentNafError(Exception):
6+
class ArgumentNafNotPresent(Exception):
77
pass
88

99

1010
class ArgumentAuthorError(Exception):
1111
pass
12+
13+
14+
class ArgumentNafInvalid(Exception):
15+
pass

src/defines.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@
1111
INPUT_FOLDER = os.path.join(ROOT_FOLDER, "input")
1212

1313
# Admin logs
14-
ADMIN_LOG_FOLDER = os.path.join(GENERAL_OUTPUT_FOLDER, "_logs")
14+
ADMIN_LOG_FOLDER = os.path.join(GENERAL_OUTPUT_FOLDER, "_admin_logs")
15+
SUPERVISOR_LOG_FOLDER = os.path.join(GENERAL_OUTPUT_FOLDER, "_supervisor_logs")
1516

1617
# Obtain absolute paths for each input directory
1718
SALARIES_FOLDER = os.path.join(INPUT_FOLDER, "_salaries")

src/filesystem.py

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,17 @@
11
import os
2+
from datetime import datetime
3+
4+
from NAF import NAF_TO_NAME
5+
from defines import GENERAL_OUTPUT_FOLDER, ADMIN_LOG_FOLDER, SUPERVISOR_LOG_FOLDER, SALARIES_OUTPUT_NAME, \
6+
PROOFS_OUTPUT_NAME, CONTRACTS_OUTPUT_NAME, RNTS_OUTPUT_NAME, RLCS_OUTPUT_NAME
7+
8+
9+
def ensure_output_gitignore():
10+
# Ensure existence of .gitignore
11+
gitignore_path = os.path.join(GENERAL_OUTPUT_FOLDER, '.gitignore')
12+
gitignore_content = "*\n!.gitignore\n"
13+
with open(gitignore_path, 'w+') as f:
14+
f.write(gitignore_content)
215

316

417
def list_dir(input_folder):
@@ -11,3 +24,46 @@ def list_dir(input_folder):
1124
file_names = [os.path.basename(file) for file in os.listdir(input_folder)]
1225

1326
return file_names
27+
28+
29+
def compute_paths(args):
30+
NOW = datetime.now().strftime("%Y-%m-%d_%H:%M:%S")
31+
32+
id_str = (NOW + "_" + args.author + "_" + args.naf.__str__() + "_" + NAF_TO_NAME[args.naf] + "_" +
33+
args.begin.strftime("%Y-%m") + "-" + args.end.strftime("%Y-%m") + ".log.txt")
34+
# Admin logs
35+
ADMIN_LOG_PATH = os.path.join(ADMIN_LOG_FOLDER, id_str)
36+
SUPERVISOR_LOG_PATH = os.path.join(SUPERVISOR_LOG_FOLDER, id_str)
37+
38+
# Home folder of the user
39+
CURRENT_USER_FOLDER: str = os.path.join(GENERAL_OUTPUT_FOLDER, args.author)
40+
41+
# Folder for the current justification
42+
justification_name = (NOW + " " + str(args.naf) + " " + NAF_TO_NAME[args.naf] + " from " +
43+
str(args.begin.strftime("%Y-%m")) + " to " +
44+
str(args.end.strftime("%Y-%m")))
45+
CURRENT_JUSTIFICATION_FOLDER = os.path.join(CURRENT_USER_FOLDER, justification_name)
46+
47+
USER_REPORT_FILE = os.path.join(CURRENT_JUSTIFICATION_FOLDER, NOW + "_" +
48+
args.naf.__str__()
49+
+ "_" + NAF_TO_NAME[args.naf] + "_" +
50+
args.begin.strftime("%Y-%m") + "-" + args.end.strftime("%Y-%m") + ".log.txt")
51+
return CURRENT_USER_FOLDER, CURRENT_JUSTIFICATION_FOLDER, USER_REPORT_FILE, ADMIN_LOG_PATH, SUPERVISOR_LOG_PATH
52+
53+
54+
def ensure_file_structure(CURRENT_USER_FOLDER, CURRENT_JUSTIFICATION_FOLDER):
55+
os.makedirs(GENERAL_OUTPUT_FOLDER, exist_ok=True)
56+
ensure_output_gitignore()
57+
58+
os.makedirs(ADMIN_LOG_FOLDER, exist_ok=True)
59+
os.makedirs(SUPERVISOR_LOG_FOLDER, exist_ok=True)
60+
os.makedirs(CURRENT_USER_FOLDER, exist_ok=True)
61+
62+
os.makedirs(CURRENT_JUSTIFICATION_FOLDER, exist_ok=True)
63+
64+
os.makedirs(os.path.join(CURRENT_JUSTIFICATION_FOLDER, SALARIES_OUTPUT_NAME), exist_ok=True)
65+
os.makedirs(os.path.join(CURRENT_JUSTIFICATION_FOLDER, PROOFS_OUTPUT_NAME), exist_ok=True)
66+
os.makedirs(os.path.join(CURRENT_JUSTIFICATION_FOLDER, CONTRACTS_OUTPUT_NAME), exist_ok=True)
67+
os.makedirs(os.path.join(CURRENT_JUSTIFICATION_FOLDER, RNTS_OUTPUT_NAME), exist_ok=True)
68+
os.makedirs(os.path.join(CURRENT_JUSTIFICATION_FOLDER, RLCS_OUTPUT_NAME), exist_ok=True)
69+

src/logger.py

Lines changed: 55 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import logging
22
import os
33
import sys
4+
from contextlib import contextmanager
45

56
# ANSI escape codes for colors
67
COLOR_CODES = {
@@ -20,19 +21,16 @@ def format(self, record):
2021
return f"{color}{message}{RESET_CODE}"
2122

2223

23-
def get_logger(user_report_file, admin_log_file, name="justicier", debug_mode=False):
24-
os.makedirs(os.path.dirname(user_report_file), exist_ok=True)
25-
os.makedirs(os.path.dirname(admin_log_file), exist_ok=True)
26-
24+
def get_logger(user_report_file, admin_log_file, supervisor_log_file, name="justicier", debug_mode=False):
2725
logger = logging.getLogger(name)
2826
logger.setLevel(logging.DEBUG)
2927

3028
if logger.handlers:
3129
return logger # Prevent re-adding handlers
3230

3331
# Formatters
34-
plain_formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
35-
color_formatter = ColorFormatter('%(asctime)s - %(levelname)s - %(message)s')
32+
plain_formatter = logging.Formatter('%(asctime)s - %(process_name)s - %(levelname)s - %(message)s')
33+
color_formatter = ColorFormatter('%(asctime)s - %(process_name)s - %(levelname)s - %(message)s')
3634

3735
# User log (INFO+)
3836
user_handler = logging.FileHandler(user_report_file)
@@ -49,7 +47,57 @@ def get_logger(user_report_file, admin_log_file, name="justicier", debug_mode=Fa
4947
console_handler.setLevel(logging.DEBUG if debug_mode else logging.WARNING)
5048
console_handler.setFormatter(color_formatter)
5149

52-
for handler in [user_handler, admin_handler, console_handler]:
50+
# Supervisor log
51+
supervisor_handler = logging.FileHandler(supervisor_log_file)
52+
supervisor_handler.setLevel(logging.INFO)
53+
supervisor_handler.setFormatter(color_formatter)
54+
55+
for handler in [user_handler, admin_handler, console_handler, supervisor_handler]:
5356
logger.addHandler(handler)
5457

5558
return logger
59+
60+
61+
def get_raw_logger(user_report_file, admin_log_file, supervisor_log_file, name="raw", debug_mode=False):
62+
logger = logging.getLogger(name)
63+
logger.setLevel(logging.DEBUG)
64+
65+
if logger.handlers:
66+
return logger # Prevent re-adding handlers
67+
68+
# User log (INFO+)
69+
user_handler = logging.FileHandler(user_report_file)
70+
user_handler.setLevel(logging.INFO)
71+
user_handler.setFormatter(None)
72+
73+
# Admin/system log (DEBUG+ if debug_mode, else ERROR+)
74+
admin_handler = logging.FileHandler(admin_log_file)
75+
admin_handler.setLevel(logging.DEBUG if debug_mode else logging.ERROR)
76+
admin_handler.setFormatter(None)
77+
78+
# Console log (DEBUG+ if debug_mode, else WARNING+), with colors
79+
console_handler = logging.StreamHandler(sys.stdout)
80+
console_handler.setLevel(logging.DEBUG if debug_mode else logging.WARNING)
81+
console_handler.setFormatter(None)
82+
83+
# Supervisor log
84+
supervisor_handler = logging.FileHandler(supervisor_log_file)
85+
supervisor_handler.setLevel(logging.INFO)
86+
supervisor_handler.setFormatter(None)
87+
88+
for handler in [user_handler, admin_handler, console_handler, supervisor_handler]:
89+
logger.addHandler(handler)
90+
91+
return logger
92+
93+
94+
def get_process_logger(base_logger, process_name):
95+
return logging.LoggerAdapter(base_logger, {'process_name': process_name})
96+
97+
98+
def unformatted_logger(logger):
99+
for h in logger.handlers:
100+
h.setFormatter(None)
101+
return logger
102+
103+

0 commit comments

Comments
 (0)