11import  sys 
2+ import  time 
3+ 
4+ if  hasattr (time , "strftime" ):
5+  from  time  import  strftime 
26
37CRITICAL  =  50 
48ERROR  =  40 
812NOTSET  =  0 
913
1014_level_dict  =  {
11-  CRITICAL : "CRIT " ,
15+  CRITICAL : "CRITICAL " ,
1216 ERROR : "ERROR" ,
13-  WARNING : "WARN " ,
17+  WARNING : "WARNING " ,
1418 INFO : "INFO" ,
1519 DEBUG : "DEBUG" ,
20+  NOTSET : "NOTSET" ,
1621}
1722
23+ _loggers  =  {}
1824_stream  =  sys .stderr 
25+ _level  =  INFO 
26+ _default_fmt  =  "%(levelname)s:%(name)s:%(message)s" 
27+ _default_datefmt  =  "%Y-%m-%d %H:%M:%S" 
1928
2029
2130class  LogRecord :
22-  def  __init__ (self ):
23-  self .__dict__  =  {}
24- 
25-  def  __getattr__ (self , key ):
26-  return  self .__dict__ [key ]
31+  def  set (self , name , level , message ):
32+  self .name  =  name 
33+  self .levelno  =  level 
34+  self .levelname  =  _level_dict [level ]
35+  self .message  =  message 
36+  self .ct  =  time .time ()
37+  self .msecs  =  int ((self .ct  -  int (self .ct )) *  1000 )
38+  self .asctime  =  None 
2739
2840
2941class  Handler :
30-  def  __init__ (self ):
31-  pass 
42+  def  __init__ (self , level = NOTSET ):
43+  self .level  =  level 
44+  self .formatter  =  None 
3245
33-  def  setFormatter (self ,  fmtr ):
46+  def  close (self ):
3447 pass 
3548
49+  def  setLevel (self , level ):
50+  self .level  =  level 
3651
37- class  Logger :
52+  def  setFormatter (self , formatter ):
53+  self .formatter  =  formatter 
3854
39-  level  =  NOTSET 
40-  handlers  =  []
41-  record  =  LogRecord ()
55+  def  format (self , record ):
56+  return  self .formatter .format (record )
4257
43-  def  __init__ (self , name ):
44-  self .name  =  name 
4558
46-  def  _level_str (self , level ):
47-  l  =  _level_dict .get (level )
48-  if  l  is  not   None :
49-  return  l 
50-  return  "LVL%s"  %  level 
59+ class  StreamHandler (Handler ):
60+  def  __init__ (self , stream = None ):
61+  self .stream  =  _stream  if  stream  is  None  else  stream 
62+  self .terminator  =  "\n " 
63+ 
64+  def  close (self ):
65+  if  hasattr (self .stream , "flush" ):
66+  self .stream .flush ()
67+ 
68+  def  emit (self , record ):
69+  if  record .levelno  >=  self .level :
70+  self .stream .write (self .format (record ) +  self .terminator )
71+ 
72+ 
73+ class  FileHandler (StreamHandler ):
74+  def  __init__ (self , filename , mode = "a" , encoding = "UTF-8" ):
75+  super ().__init__ (stream = open (filename , mode = mode , encoding = encoding ))
76+ 
77+  def  close (self ):
78+  super ().close ()
79+  self .stream .close ()
80+ 
81+ 
82+ class  Formatter :
83+  def  __init__ (self , fmt = None , datefmt = None ):
84+  self .fmt  =  _default_fmt  if  fmt  is  None  else  fmt 
85+  self .datefmt  =  _default_datefmt  if  datefmt  is  None  else  datefmt 
86+ 
87+  def  usesTime (self ):
88+  return  "asctime"  in  self .fmt 
89+ 
90+  def  formatTime (self , datefmt , record ):
91+  if  hasattr (time , "strftime" ):
92+  return  strftime (datefmt , time .localtime (record .ct ))
93+  return  None 
94+ 
95+  def  format (self , record ):
96+  if  self .usesTime ():
97+  record .asctime  =  self .formatTime (self .datefmt , record )
98+  return  self .fmt  %  {
99+  "name" : record .name ,
100+  "message" : record .message ,
101+  "msecs" : record .msecs ,
102+  "asctime" : record .asctime ,
103+  "levelname" : record .levelname ,
104+  }
105+ 
106+ 
107+ class  Logger :
108+  def  __init__ (self , name , level = NOTSET ):
109+  self .name  =  name 
110+  self .level  =  level 
111+  self .handlers  =  []
112+  self .record  =  LogRecord ()
51113
52114 def  setLevel (self , level ):
53115 self .level  =  level 
@@ -57,19 +119,16 @@ def isEnabledFor(self, level):
57119
58120 def  log (self , level , msg , * args ):
59121 if  self .isEnabledFor (level ):
60-  levelname  =  self ._level_str (level )
61122 if  args :
123+  if  isinstance (args [0 ], dict ):
124+  args  =  args [0 ]
62125 msg  =  msg  %  args 
63-  if  self .handlers :
64-  d  =  self .record .__dict__ 
65-  d ["levelname" ] =  levelname 
66-  d ["levelno" ] =  level 
67-  d ["message" ] =  msg 
68-  d ["name" ] =  self .name 
69-  for  h  in  self .handlers :
70-  h .emit (self .record )
71-  else :
72-  print (levelname , ":" , self .name , ":" , msg , sep = "" , file = _stream )
126+  self .record .set (self .name , level , msg )
127+  handlers  =  self .handlers 
128+  if  not  handlers :
129+  handlers  =  getLogger ().handlers 
130+  for  h  in  handlers :
131+  h .emit (self .record )
73132
74133 def  debug (self , msg , * args ):
75134 self .log (DEBUG , msg , * args )
@@ -86,43 +145,98 @@ def error(self, msg, *args):
86145 def  critical (self , msg , * args ):
87146 self .log (CRITICAL , msg , * args )
88147
89-  def  exc (self ,  e , msg , * args ):
148+  def  exception (self , msg , * args ):
90149 self .log (ERROR , msg , * args )
91-  sys .print_exception (e , _stream )
150+  if  hasattr (sys , "exc_info" ):
151+  sys .print_exception (sys .exc_info ()[1 ], _stream )
92152
93-  def  exception (self , msg ,  * args ):
94-  self .exc ( sys . exc_info ()[ 1 ],  msg ,  * args )
153+  def  addHandler (self , handler ):
154+  self .handlers . append ( handler )
95155
96-  def  addHandler (self ,  hndlr ):
97-  self .handlers . append ( hndlr ) 
156+  def  hasHandlers (self ):
157+  return   len ( self .handlers )  >   0 
98158
99159
100- _level  =  INFO 
101- _loggers  =  {}
160+ def  getLogger (name = None ):
161+  if  name  is  None :
162+  name  =  "root" 
163+  if  name  not  in   _loggers :
164+  _loggers [name ] =  Logger (name )
165+  if  name  ==  "root" :
166+  basicConfig ()
167+  return  _loggers [name ]
168+ 
102169
170+ def  log (level , msg , * args ):
171+  getLogger ().log (level , msg , * args )
103172
104- def  getLogger (name = "root" ):
105-  if  name  in  _loggers :
106-  return  _loggers [name ]
107-  l  =  Logger (name )
108-  _loggers [name ] =  l 
109-  return  l 
173+ 
174+ def  debug (msg , * args ):
175+  getLogger ().debug (msg , * args )
110176
111177
112178def  info (msg , * args ):
113179 getLogger ().info (msg , * args )
114180
115181
116- def  debug (msg , * args ):
117-  getLogger ().debug (msg , * args )
182+ def  warning (msg , * args ):
183+  getLogger ().warning (msg , * args )
184+ 
185+ 
186+ def  error (msg , * args ):
187+  getLogger ().error (msg , * args )
188+ 
189+ 
190+ def  critical (msg , * args ):
191+  getLogger ().critical (msg , * args )
192+ 
193+ 
194+ def  exception (msg , * args ):
195+  getLogger ().exception (msg , * args )
196+ 
197+ 
198+ def  shutdown ():
199+  for  k , logger  in  _loggers .items ():
200+  for  h  in  logger .handlers :
201+  h .close ()
202+  _loggers .pop (logger , None )
203+ 
204+ 
205+ def  addLevelName (level , name ):
206+  _level_dict [level ] =  name 
207+ 
208+ 
209+ def  basicConfig (
210+  filename = None ,
211+  filemode = "a" ,
212+  format = None ,
213+  datefmt = None ,
214+  level = WARNING ,
215+  stream = None ,
216+  encoding = "UTF-8" ,
217+  force = False ,
218+ ):
219+  if  "root"  not  in   _loggers :
220+  _loggers ["root" ] =  Logger ("root" )
221+ 
222+  logger  =  _loggers ["root" ]
223+ 
224+  if  force  or  not  logger .handlers :
225+  for  h  in  logger .handlers :
226+  h .close ()
227+  logger .handlers  =  []
228+ 
229+  if  filename  is  None :
230+  handler  =  StreamHandler (stream )
231+  else :
232+  handler  =  FileHandler (filename , filemode , encoding )
233+ 
234+  handler .setLevel (level )
235+  handler .setFormatter (Formatter (format , datefmt ))
236+ 
237+  logger .setLevel (level )
238+  logger .addHandler (handler )
118239
119240
120- def  basicConfig (level = INFO , filename = None , stream = None , format = None ):
121-  global  _level , _stream 
122-  _level  =  level 
123-  if  stream :
124-  _stream  =  stream 
125-  if  filename  is  not   None :
126-  print ("logging.basicConfig: filename arg is not supported" )
127-  if  format  is  not   None :
128-  print ("logging.basicConfig: format arg is not supported" )
241+ if  hasattr (sys , "atexit" ):
242+  sys .atexit (shutdown )
0 commit comments