mirror of
https://github.com/SickGear/SickGear.git
synced 2024-12-01 00:43:37 +00:00
0d9fbc1ad7
This version of SickBeard uses both TVDB and TVRage to search and gather it's series data from allowing you to now have access to and download shows that you couldn't before because of being locked into only what TheTVDB had to offer. Also this edition is based off the code we used in our XEM editon so it does come with scene numbering support as well as all the other features our XEM edition has to offer. Please before using this with your existing database (sickbeard.db) please make a backup copy of it and delete any other database files such as cache.db and failed.db if present, we HIGHLY recommend starting out with no database files at all to make this a fresh start but the choice is at your own risk! Enjoy!
250 lines
9 KiB
Python
250 lines
9 KiB
Python
"""CherryPy logging."""
|
|
|
|
import datetime
|
|
import logging
|
|
# Silence the no-handlers "warning" (stderr write!) in stdlib logging
|
|
logging.Logger.manager.emittedNoHandlerWarning = 1
|
|
logfmt = logging.Formatter("%(message)s")
|
|
import os
|
|
import sys
|
|
|
|
import cherrypy
|
|
from cherrypy import _cperror
|
|
|
|
|
|
class LogManager(object):
|
|
|
|
appid = None
|
|
error_log = None
|
|
access_log = None
|
|
access_log_format = \
|
|
'%(h)s %(l)s %(u)s %(t)s "%(r)s" %(s)s %(b)s "%(f)s" "%(a)s"'
|
|
|
|
def __init__(self, appid=None, logger_root="cherrypy"):
|
|
self.logger_root = logger_root
|
|
self.appid = appid
|
|
if appid is None:
|
|
self.error_log = logging.getLogger("%s.error" % logger_root)
|
|
self.access_log = logging.getLogger("%s.access" % logger_root)
|
|
else:
|
|
self.error_log = logging.getLogger("%s.error.%s" % (logger_root, appid))
|
|
self.access_log = logging.getLogger("%s.access.%s" % (logger_root, appid))
|
|
self.error_log.setLevel(logging.INFO)
|
|
self.access_log.setLevel(logging.INFO)
|
|
cherrypy.engine.subscribe('graceful', self.reopen_files)
|
|
|
|
def reopen_files(self):
|
|
"""Close and reopen all file handlers."""
|
|
for log in (self.error_log, self.access_log):
|
|
for h in log.handlers:
|
|
if isinstance(h, logging.FileHandler):
|
|
h.acquire()
|
|
h.stream.close()
|
|
h.stream = open(h.baseFilename, h.mode)
|
|
h.release()
|
|
|
|
def error(self, msg='', context='', severity=logging.INFO, traceback=False):
|
|
"""Write to the error log.
|
|
|
|
This is not just for errors! Applications may call this at any time
|
|
to log application-specific information.
|
|
"""
|
|
if traceback:
|
|
msg += _cperror.format_exc()
|
|
self.error_log.log(severity, ' '.join((self.time(), context, msg)))
|
|
|
|
def __call__(self, *args, **kwargs):
|
|
"""Write to the error log.
|
|
|
|
This is not just for errors! Applications may call this at any time
|
|
to log application-specific information.
|
|
"""
|
|
return self.error(*args, **kwargs)
|
|
|
|
def access(self):
|
|
"""Write to the access log (in Apache/NCSA Combined Log format).
|
|
|
|
Like Apache started doing in 2.0.46, non-printable and other special
|
|
characters in %r (and we expand that to all parts) are escaped using
|
|
\\xhh sequences, where hh stands for the hexadecimal representation
|
|
of the raw byte. Exceptions from this rule are " and \\, which are
|
|
escaped by prepending a backslash, and all whitespace characters,
|
|
which are written in their C-style notation (\\n, \\t, etc).
|
|
"""
|
|
request = cherrypy.serving.request
|
|
remote = request.remote
|
|
response = cherrypy.serving.response
|
|
outheaders = response.headers
|
|
inheaders = request.headers
|
|
if response.output_status is None:
|
|
status = "-"
|
|
else:
|
|
status = response.output_status.split(" ", 1)[0]
|
|
|
|
atoms = {'h': remote.name or remote.ip,
|
|
'l': '-',
|
|
'u': getattr(request, "login", None) or "-",
|
|
't': self.time(),
|
|
'r': request.request_line,
|
|
's': status,
|
|
'b': dict.get(outheaders, 'Content-Length', '') or "-",
|
|
'f': dict.get(inheaders, 'Referer', ''),
|
|
'a': dict.get(inheaders, 'User-Agent', ''),
|
|
}
|
|
for k, v in atoms.items():
|
|
if isinstance(v, unicode):
|
|
v = v.encode('utf8')
|
|
elif not isinstance(v, str):
|
|
v = str(v)
|
|
# Fortunately, repr(str) escapes unprintable chars, \n, \t, etc
|
|
# and backslash for us. All we have to do is strip the quotes.
|
|
v = repr(v)[1:-1]
|
|
# Escape double-quote.
|
|
atoms[k] = v.replace('"', '\\"')
|
|
|
|
try:
|
|
self.access_log.log(logging.INFO, self.access_log_format % atoms)
|
|
except:
|
|
self(traceback=True)
|
|
|
|
def time(self):
|
|
"""Return now() in Apache Common Log Format (no timezone)."""
|
|
now = datetime.datetime.now()
|
|
monthnames = ['jan', 'feb', 'mar', 'apr', 'may', 'jun',
|
|
'jul', 'aug', 'sep', 'oct', 'nov', 'dec']
|
|
month = monthnames[now.month - 1].capitalize()
|
|
return ('[%02d/%s/%04d:%02d:%02d:%02d]' %
|
|
(now.day, month, now.year, now.hour, now.minute, now.second))
|
|
|
|
def _get_builtin_handler(self, log, key):
|
|
for h in log.handlers:
|
|
if getattr(h, "_cpbuiltin", None) == key:
|
|
return h
|
|
|
|
|
|
# ------------------------- Screen handlers ------------------------- #
|
|
|
|
def _set_screen_handler(self, log, enable, stream=None):
|
|
h = self._get_builtin_handler(log, "screen")
|
|
if enable:
|
|
if not h:
|
|
if stream is None:
|
|
stream = sys.stderr
|
|
h = logging.StreamHandler(stream)
|
|
h.setFormatter(logfmt)
|
|
h._cpbuiltin = "screen"
|
|
log.addHandler(h)
|
|
elif h:
|
|
log.handlers.remove(h)
|
|
|
|
def _get_screen(self):
|
|
h = self._get_builtin_handler
|
|
has_h = h(self.error_log, "screen") or h(self.access_log, "screen")
|
|
return bool(has_h)
|
|
|
|
def _set_screen(self, newvalue):
|
|
self._set_screen_handler(self.error_log, newvalue, stream=sys.stderr)
|
|
self._set_screen_handler(self.access_log, newvalue, stream=sys.stdout)
|
|
screen = property(_get_screen, _set_screen,
|
|
doc="If True, error and access will print to stderr.")
|
|
|
|
|
|
# -------------------------- File handlers -------------------------- #
|
|
|
|
def _add_builtin_file_handler(self, log, fname):
|
|
h = logging.FileHandler(fname)
|
|
h.setFormatter(logfmt)
|
|
h._cpbuiltin = "file"
|
|
log.addHandler(h)
|
|
|
|
def _set_file_handler(self, log, filename):
|
|
h = self._get_builtin_handler(log, "file")
|
|
if filename:
|
|
if h:
|
|
if h.baseFilename != os.path.abspath(filename):
|
|
h.close()
|
|
log.handlers.remove(h)
|
|
self._add_builtin_file_handler(log, filename)
|
|
else:
|
|
self._add_builtin_file_handler(log, filename)
|
|
else:
|
|
if h:
|
|
h.close()
|
|
log.handlers.remove(h)
|
|
|
|
def _get_error_file(self):
|
|
h = self._get_builtin_handler(self.error_log, "file")
|
|
if h:
|
|
return h.baseFilename
|
|
return ''
|
|
def _set_error_file(self, newvalue):
|
|
self._set_file_handler(self.error_log, newvalue)
|
|
error_file = property(_get_error_file, _set_error_file,
|
|
doc="The filename for self.error_log.")
|
|
|
|
def _get_access_file(self):
|
|
h = self._get_builtin_handler(self.access_log, "file")
|
|
if h:
|
|
return h.baseFilename
|
|
return ''
|
|
def _set_access_file(self, newvalue):
|
|
self._set_file_handler(self.access_log, newvalue)
|
|
access_file = property(_get_access_file, _set_access_file,
|
|
doc="The filename for self.access_log.")
|
|
|
|
|
|
# ------------------------- WSGI handlers ------------------------- #
|
|
|
|
def _set_wsgi_handler(self, log, enable):
|
|
h = self._get_builtin_handler(log, "wsgi")
|
|
if enable:
|
|
if not h:
|
|
h = WSGIErrorHandler()
|
|
h.setFormatter(logfmt)
|
|
h._cpbuiltin = "wsgi"
|
|
log.addHandler(h)
|
|
elif h:
|
|
log.handlers.remove(h)
|
|
|
|
def _get_wsgi(self):
|
|
return bool(self._get_builtin_handler(self.error_log, "wsgi"))
|
|
|
|
def _set_wsgi(self, newvalue):
|
|
self._set_wsgi_handler(self.error_log, newvalue)
|
|
wsgi = property(_get_wsgi, _set_wsgi,
|
|
doc="If True, error messages will be sent to wsgi.errors.")
|
|
|
|
|
|
class WSGIErrorHandler(logging.Handler):
|
|
"A handler class which writes logging records to environ['wsgi.errors']."
|
|
|
|
def flush(self):
|
|
"""Flushes the stream."""
|
|
try:
|
|
stream = cherrypy.serving.request.wsgi_environ.get('wsgi.errors')
|
|
except (AttributeError, KeyError):
|
|
pass
|
|
else:
|
|
stream.flush()
|
|
|
|
def emit(self, record):
|
|
"""Emit a record."""
|
|
try:
|
|
stream = cherrypy.serving.request.wsgi_environ.get('wsgi.errors')
|
|
except (AttributeError, KeyError):
|
|
pass
|
|
else:
|
|
try:
|
|
msg = self.format(record)
|
|
fs = "%s\n"
|
|
import types
|
|
if not hasattr(types, "UnicodeType"): #if no unicode support...
|
|
stream.write(fs % msg)
|
|
else:
|
|
try:
|
|
stream.write(fs % msg)
|
|
except UnicodeError:
|
|
stream.write(fs % msg.encode("UTF-8"))
|
|
self.flush()
|
|
except:
|
|
self.handleError(record)
|