1
1
import logging
2
+ import os
2
3
import re
3
4
import sys
4
- import os
5
- from difflib import get_close_matches
6
- from enum import IntEnum
7
- from logging .handlers import RotatingFileHandler
8
- from string import Formatter
9
5
10
- import discord
11
- from discord .ext import commands
6
+ from logging import FileHandler , StreamHandler
7
+ from logging .handlers import RotatingFileHandler
8
+ from typing import Optional , Union
12
9
13
- import _string
14
10
15
11
try :
16
- from colorama import Fore , Style
12
+ from colorama import Fore , Style , init as color_init
17
13
except ImportError :
18
14
Fore = Style = type ("Dummy" , (object ,), {"__getattr__" : lambda self , item : "" })()
15
+ else :
16
+ color_init ()
19
17
20
18
21
19
if ".heroku" in os .environ .get ("PYTHONHOME" , "" ):
22
20
# heroku
23
21
Fore = Style = type ("Dummy" , (object ,), {"__getattr__" : lambda self , item : "" })()
24
22
25
23
26
- class PermissionLevel (IntEnum ):
27
- OWNER = 5
28
- ADMINISTRATOR = 4
29
- ADMIN = 4
30
- MODERATOR = 3
31
- MOD = 3
32
- SUPPORTER = 2
33
- RESPONDER = 2
34
- REGULAR = 1
35
- INVALID = - 1
36
-
37
-
38
- class InvalidConfigError (commands .BadArgument ):
39
- def __init__ (self , msg , * args ):
40
- super ().__init__ (msg , * args )
41
- self .msg = msg
42
-
43
- @property
44
- def embed (self ):
45
- # Single reference of Color.red()
46
- return discord .Embed (title = "Error" , description = self .msg , color = discord .Color .red ())
47
-
48
-
49
24
class ModmailLogger (logging .Logger ):
50
25
@staticmethod
51
26
def _debug_ (* msgs ):
@@ -94,18 +69,87 @@ def line(self, level="info"):
94
69
)
95
70
96
71
97
- logging .setLoggerClass (ModmailLogger )
98
- log_level = logging .INFO
99
- loggers = set ()
72
+ class FileFormatter (logging .Formatter ):
73
+ ansi_escape = re .compile (r"\x1B\[[0-?]*[ -/]*[@-~]" )
74
+
75
+ def format (self , record ):
76
+ record .msg = self .ansi_escape .sub ("" , record .msg )
77
+ return super ().format (record )
100
78
101
- ch = logging .StreamHandler (stream = sys .stdout )
102
- ch .setLevel (log_level )
103
- formatter = logging .Formatter (
79
+
80
+ log_stream_formatter = logging .Formatter (
104
81
"%(asctime)s %(name)s[%(lineno)d] - %(levelname)s: %(message)s" , datefmt = "%m/%d/%y %H:%M:%S"
105
82
)
106
- ch .setFormatter (formatter )
83
+ log_file_formatter = FileFormatter (
84
+ "%(asctime)s %(name)s[%(lineno)d] - %(levelname)s: %(message)s" ,
85
+ datefmt = "%Y-%m-%d %H:%M:%S" ,
86
+ )
87
+
88
+
89
+ def create_log_handler (
90
+ filename : Optional [str ] = None ,
91
+ * ,
92
+ rotating : bool = False ,
93
+ level : int = logging .DEBUG ,
94
+ mode : str = "a+" ,
95
+ encoding : str = "utf-8" ,
96
+ maxBytes : int = 48000 ,
97
+ backupCount : int = 1 ,
98
+ ** kwargs ,
99
+ ) -> Union [FileHandler , RotatingFileHandler , StreamHandler ]:
100
+ """
101
+ Return a pre-configured log handler. This function is made for consistency sake with
102
+ pre-defined default values for parameters and formatters to pass to handler class.
103
+ Additional keyword arguments also can be specified, just in case.
104
+
105
+ Plugin developers should not use this and only use the `getLogger` instead to instantiate the ModmailLogger object.
106
+
107
+ Parameters
108
+ -----------
109
+ filename : Optional[Path]
110
+ Specifies that a `FileHandler` or `RotatingFileHandler` be created, using the specified filename,
111
+ rather than a `StreamHandler`. Defaults to `None`.
112
+ rotating : bool
113
+ Whether the file handler should be the `RotatingFileHandler`. Defaults to `False`. Note, this
114
+ argument only compatible if the `filename` is specified, otherwise `ValueError` will be raised.
115
+ level : int
116
+ The root logger level for the handler. Defaults to `logging.DEBUG`.
117
+ mode : str
118
+ If filename is specified, open the file in this mode. Defaults to 'a+'.
119
+ encoding : str
120
+ If this keyword argument is specified along with filename, its value is used when the `FileHandler` is created,
121
+ and thus used when opening the output file. Defaults to 'utf-8'.
122
+ maxBytes : int
123
+ The max file size before the rollover occurs. Defaults to 48000. Rollover occurs whenever the current log file
124
+ is nearly `maxBytes` in length; but if either of `maxBytes` or `backupCount` is zero, rollover never occurs, so you
125
+ generally want to set `backupCount` to at least 1.
126
+ backupCount : int
127
+ Max number of backup files. Defaults to 1. If this is set to zero, rollover will never occur.
128
+ """
129
+ if filename is None and rotating :
130
+ raise ValueError ("`filename` must be set to instantiate a `RotatingFileHandler`." )
131
+
132
+ if filename is None :
133
+ handler = StreamHandler (stream = sys .stdout , ** kwargs )
134
+ handler .setFormatter (log_stream_formatter )
135
+ elif not rotating :
136
+ handler = FileHandler (filename , mode = mode , encoding = encoding , ** kwargs )
137
+ handler .setFormatter (log_file_formatter )
138
+ else :
139
+ handler = RotatingFileHandler (
140
+ filename , mode = mode , encoding = encoding , maxBytes = maxBytes , backupCount = backupCount , ** kwargs
141
+ )
142
+ handler .setFormatter (log_file_formatter )
143
+
144
+ handler .setLevel (level )
145
+ return handler
107
146
108
- ch_debug = None
147
+
148
+ logging .setLoggerClass (ModmailLogger )
149
+ log_level = logging .INFO
150
+ loggers = set ()
151
+ ch : StreamHandler = create_log_handler (level = log_level )
152
+ ch_debug : Optional [RotatingFileHandler ] = None
109
153
110
154
111
155
def getLogger (name = None ) -> ModmailLogger :
@@ -118,24 +162,9 @@ def getLogger(name=None) -> ModmailLogger:
118
162
return logger
119
163
120
164
121
- class FileFormatter (logging .Formatter ):
122
- ansi_escape = re .compile (r"\x1B\[[0-?]*[ -/]*[@-~]" )
123
-
124
- def format (self , record ):
125
- record .msg = self .ansi_escape .sub ("" , record .msg )
126
- return super ().format (record )
127
-
128
-
129
- def configure_logging (name , level = None ):
165
+ def configure_logging (name , level : Optional [int ] = None ):
130
166
global ch_debug , log_level
131
- ch_debug = RotatingFileHandler (name , mode = "a+" , maxBytes = 48000 , backupCount = 1 , encoding = "utf-8" )
132
-
133
- formatter_debug = FileFormatter (
134
- "%(asctime)s %(name)s[%(lineno)d] - %(levelname)s: %(message)s" ,
135
- datefmt = "%Y-%m-%d %H:%M:%S" ,
136
- )
137
- ch_debug .setFormatter (formatter_debug )
138
- ch_debug .setLevel (logging .DEBUG )
167
+ ch_debug = create_log_handler (name , rotating = True )
139
168
140
169
if level is not None :
141
170
log_level = level
@@ -147,6 +176,25 @@ def configure_logging(name, level=None):
147
176
logger .addHandler (ch_debug )
148
177
149
178
179
+ from string import Formatter
180
+ from difflib import get_close_matches
181
+ from enum import IntEnum
182
+ import _string
183
+ import discord
184
+ from discord .ext import commands
185
+
186
+
187
+ class InvalidConfigError (commands .BadArgument ):
188
+ def __init__ (self , msg , * args ):
189
+ super ().__init__ (msg , * args )
190
+ self .msg = msg
191
+
192
+ @property
193
+ def embed (self ):
194
+ # Single reference of Color.red()
195
+ return discord .Embed (title = "Error" , description = self .msg , color = discord .Color .red ())
196
+
197
+
150
198
class _Default :
151
199
pass
152
200
@@ -271,6 +319,18 @@ async def ack(self):
271
319
return
272
320
273
321
322
+ class PermissionLevel (IntEnum ):
323
+ OWNER = 5
324
+ ADMINISTRATOR = 4
325
+ ADMIN = 4
326
+ MODERATOR = 3
327
+ MOD = 3
328
+ SUPPORTER = 2
329
+ RESPONDER = 2
330
+ REGULAR = 1
331
+ INVALID = - 1
332
+
333
+
274
334
class DMDisabled (IntEnum ):
275
335
NONE = 0
276
336
NEW_THREADS = 1
0 commit comments