55from platform import system
66from tempfile import gettempdir
77from datetime import datetime
8- from colorama import Fore , Style
98from .errors import *
109
1110
1211class Logger :
13- """Main logger object.
12+ """Logging handler.
13+
14+ Attributes:
15+ LEVELS (dict): Log levels value for fast filtering
16+ enabled (bool): If logging is enabled
17+ erase (bool): If preexisting file should be erased
18+ file (str): Log file path
19+ level (str): Minimum log level to be displayed
1420
1521 Raises:
1622 LogLevelDoesNotExist: If user provide an unknown log level
@@ -20,66 +26,57 @@ class Logger:
2026 write to output path
2127 """
2228
23- __instance = None
24- _LEVELS = {"ERROR" : 3 , "WARNING" : 2 , "INFO" : 1 , "DEBUG" : 0 }
25-
26- def __new__ (cls , * args , ** kwargs ):
27- is_singleton = (len (args ) == 6 and args [5 ] == True ) or kwargs .get ("singleton" )
28- if is_singleton and not Logger .__instance or not is_singleton :
29- Logger .__instance = object .__new__ (cls )
30- return Logger .__instance
29+ _LEVELS = {
30+ "ERROR" : 3 ,
31+ "WARNING" : 2 ,
32+ "INFO" : 1 ,
33+ "DEBUG" : 0 ,
34+ }
3135
3236 def __init__ (
3337 self ,
34- output_file : str = None ,
35- level : str = "INFO " ,
38+ file : str = None ,
39+ level : str = "DEBUG " ,
3640 enabled : bool = True ,
37- colors : bool = True ,
3841 erase : bool = True ,
39- singleton : bool = False ,
4042 ):
4143 """Logger initialization.
4244
4345 Args:
44- output_file (str, optional): Output file path. Defaults to None.
45- level (str, optional): Minimum log level. Defaults to "INFO ".
46+ file (str, optional): Output file path. Defaults to None.
47+ level (str, optional): Minimum log level. Defaults to "DEBUG ".
4648 enabled (bool, optional): Is log enabled ? Defaults to True.
47- colors (bool, optional): Are colors enabled ? Defaults to True.
4849 erase (bool, optional): Should preexisting file be erased ? Defaults to True.
49- singleton (bool, optional): Is singleton ? Defaults to False.
50-
51- Raises:
52- LogLevelDoesNotExist: [description]
5350 """
5451
5552 self ._enabled = enabled
56- self ._colors = colors
5753 self ._erase = erase
5854
59- if output_file is None :
60- self ._output_file = Path (
55+ if file is None :
56+ self ._file = Path (
6157 "/tmp/livelog.log"
6258 if system () == "Darwin"
6359 else Path (gettempdir ()) / "livelog.log"
6460 )
6561 else :
66- self ._output_file = Path (output_file )
67- self ._verify_file (self ._output_file )
62+ self ._file = Path (file )
63+
64+ self ._verify_file ()
6865
6966 level = level .upper ()
7067 if level not in self ._LEVELS :
7168 raise LogLevelDoesNotExist (level )
7269 self ._level = level
7370
7471 @property
75- def output_file (self ):
76- return self ._output_file
72+ def file (self ):
73+ return self ._file
7774
78- @output_file .setter
79- def set_output_file (self , value : str ):
75+ @file .setter
76+ def set_file (self , value : str ):
8077 path = Path (value )
8178 self ._verify_file (file = path )
82- self ._output_file = path
79+ self ._file = path
8380
8481 @property
8582 def level (self ):
@@ -92,16 +89,14 @@ def level(self, value: str):
9289 raise LogLevelDoesNotExist (level )
9390 self ._level = level
9491
95- def _verify_file (self , file : Path ):
96- """Verify if the file is a valid log file and clear its preexisting content.
97-
98- Args:
99- file (Path): File path to verify.
92+ def _verify_file (self ):
93+ """Verify if provided file path is a valid log file and clear its
94+ preexisting content.
10095 """
10196
102- dir = file .parent .resolve ()
103- if file .is_dir ():
104- raise LogFileIsADirectory (path = file )
97+ dir = self . _file .parent .resolve ()
98+ if self . _file .is_dir ():
99+ raise LogFileIsADirectory (path = self . _file )
105100 if not dir .is_dir ():
106101 raise LogPathDoesNotExist (path = dir )
107102 if not access (dir , X_OK ):
@@ -111,31 +106,26 @@ def _verify_file(self, file: Path):
111106 def _clear_file (self ):
112107 """Clear output file content."""
113108
114- if not self ._erase or not self ._output_file .is_file ():
109+ if not self ._erase or not self ._file .is_file ():
115110 return
116- with open (self ._output_file , "w" ) as f :
111+ with open (self ._file , "w" ) as f :
117112 pass
118113
119- def _write (self , content : str ):
114+ def _write (self , level : str , content : str ):
120115 """Write provided content to output file.
121116
122117 Args:
118+ level (str); Log level
123119 content (str): Content to be written
124120 """
125121
126122 if not self ._enabled :
127123 return
128124
129- if self ._colors :
130- time = Style .DIM + datetime .now ().strftime ("%H:%M:%S.%f" )[:- 3 ]
131- dash = Style .BRIGHT + " - "
132- content = f"{ Style .NORMAL } { content } { Style .RESET_ALL } "
133- else :
134- time = datetime .now ().strftime ("%H:%M:%S.%f" )[:- 3 ]
135- dash = " - "
125+ time = datetime .now ().strftime ("%H:%M:%S.%f" )[:- 3 ]
136126
137- with open (self ._output_file , "a" ) as f :
138- f .write (f"{ time } { dash } { content } \n " )
127+ with open (self ._file , "a" ) as f :
128+ f .write (f"{ level } | { time } - { content } \n " )
139129
140130 def _is_valid_level (self , level : str ):
141131 """Verify if the given log level should be written.
@@ -156,10 +146,7 @@ def error(self, message: str):
156146 message (str): Log message
157147 """
158148
159- if self ._colors :
160- self ._write (content = Fore .RED + message )
161- else :
162- self ._write (content = "error | " + message )
149+ self ._write (level = "ERR!" , content = message )
163150
164151 def warn (self , message : str ):
165152 """Write warning message.
@@ -170,10 +157,7 @@ def warn(self, message: str):
170157
171158 if not self ._is_valid_level ("WARNING" ):
172159 return
173- if self ._colors :
174- self ._write (content = Fore .YELLOW + message )
175- else :
176- self ._write (content = "warning | " + message )
160+ self ._write (level = "WARN" , content = message )
177161
178162 def info (self , message : str ):
179163 """Write info message.
@@ -184,10 +168,7 @@ def info(self, message: str):
184168
185169 if not self ._is_valid_level ("INFO" ):
186170 return
187- if self ._colors :
188- self ._write (content = Fore .BLUE + message )
189- else :
190- self ._write (content = "info | " + message )
171+ self ._write (level = "INFO" , content = message )
191172
192173 def debug (self , message : str ):
193174 """Write debug message.
@@ -198,7 +179,17 @@ def debug(self, message: str):
198179
199180 if not self ._is_valid_level ("DEBUG" ):
200181 return
201- if self ._colors :
202- self ._write (content = Fore .WHITE + message )
203- else :
204- self ._write (content = "debug | " + message )
182+ self ._write (level = "DBUG" , content = message )
183+
184+
185+ class Singleton (type ):
186+ _instances = {}
187+
188+ def __call__ (cls , * args , ** kwargs ):
189+ if cls not in cls ._instances :
190+ cls ._instances [cls ] = super (Singleton , cls ).__call__ (* args , ** kwargs )
191+ return cls ._instances [cls ]
192+
193+
194+ class LoggerSingleton (Logger , metaclass = Singleton ):
195+ pass
0 commit comments