Edit File by line
/home/barbar84/www/wp-conte.../plugins/sujqvwi/AnonR/anonr.TX.../usr/lib64/python3..../logging
File: config.py
# Copyright 2001-2014 by Vinay Sajip. All Rights Reserved.
[0] Fix | Delete
#
[1] Fix | Delete
# Permission to use, copy, modify, and distribute this software and its
[2] Fix | Delete
# documentation for any purpose and without fee is hereby granted,
[3] Fix | Delete
# provided that the above copyright notice appear in all copies and that
[4] Fix | Delete
# both that copyright notice and this permission notice appear in
[5] Fix | Delete
# supporting documentation, and that the name of Vinay Sajip
[6] Fix | Delete
# not be used in advertising or publicity pertaining to distribution
[7] Fix | Delete
# of the software without specific, written prior permission.
[8] Fix | Delete
# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
[9] Fix | Delete
# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
[10] Fix | Delete
# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
[11] Fix | Delete
# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
[12] Fix | Delete
# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
[13] Fix | Delete
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
[14] Fix | Delete
[15] Fix | Delete
"""
[16] Fix | Delete
Configuration functions for the logging package for Python. The core package
[17] Fix | Delete
is based on PEP 282 and comments thereto in comp.lang.python, and influenced
[18] Fix | Delete
by Apache's log4j system.
[19] Fix | Delete
[20] Fix | Delete
Copyright (C) 2001-2014 Vinay Sajip. All Rights Reserved.
[21] Fix | Delete
[22] Fix | Delete
To use, simply 'import logging' and log away!
[23] Fix | Delete
"""
[24] Fix | Delete
[25] Fix | Delete
import errno
[26] Fix | Delete
import io
[27] Fix | Delete
import logging
[28] Fix | Delete
import logging.handlers
[29] Fix | Delete
import re
[30] Fix | Delete
import struct
[31] Fix | Delete
import sys
[32] Fix | Delete
import traceback
[33] Fix | Delete
[34] Fix | Delete
try:
[35] Fix | Delete
import _thread as thread
[36] Fix | Delete
import threading
[37] Fix | Delete
except ImportError: #pragma: no cover
[38] Fix | Delete
thread = None
[39] Fix | Delete
[40] Fix | Delete
from socketserver import ThreadingTCPServer, StreamRequestHandler
[41] Fix | Delete
[42] Fix | Delete
[43] Fix | Delete
DEFAULT_LOGGING_CONFIG_PORT = 9030
[44] Fix | Delete
[45] Fix | Delete
RESET_ERROR = errno.ECONNRESET
[46] Fix | Delete
[47] Fix | Delete
#
[48] Fix | Delete
# The following code implements a socket listener for on-the-fly
[49] Fix | Delete
# reconfiguration of logging.
[50] Fix | Delete
#
[51] Fix | Delete
# _listener holds the server object doing the listening
[52] Fix | Delete
_listener = None
[53] Fix | Delete
[54] Fix | Delete
def fileConfig(fname, defaults=None, disable_existing_loggers=True):
[55] Fix | Delete
"""
[56] Fix | Delete
Read the logging configuration from a ConfigParser-format file.
[57] Fix | Delete
[58] Fix | Delete
This can be called several times from an application, allowing an end user
[59] Fix | Delete
the ability to select from various pre-canned configurations (if the
[60] Fix | Delete
developer provides a mechanism to present the choices and load the chosen
[61] Fix | Delete
configuration).
[62] Fix | Delete
"""
[63] Fix | Delete
import configparser
[64] Fix | Delete
[65] Fix | Delete
if isinstance(fname, configparser.RawConfigParser):
[66] Fix | Delete
cp = fname
[67] Fix | Delete
else:
[68] Fix | Delete
cp = configparser.ConfigParser(defaults)
[69] Fix | Delete
if hasattr(fname, 'readline'):
[70] Fix | Delete
cp.read_file(fname)
[71] Fix | Delete
else:
[72] Fix | Delete
cp.read(fname)
[73] Fix | Delete
[74] Fix | Delete
formatters = _create_formatters(cp)
[75] Fix | Delete
[76] Fix | Delete
# critical section
[77] Fix | Delete
logging._acquireLock()
[78] Fix | Delete
try:
[79] Fix | Delete
_clearExistingHandlers()
[80] Fix | Delete
[81] Fix | Delete
# Handlers add themselves to logging._handlers
[82] Fix | Delete
handlers = _install_handlers(cp, formatters)
[83] Fix | Delete
_install_loggers(cp, handlers, disable_existing_loggers)
[84] Fix | Delete
finally:
[85] Fix | Delete
logging._releaseLock()
[86] Fix | Delete
[87] Fix | Delete
[88] Fix | Delete
def _resolve(name):
[89] Fix | Delete
"""Resolve a dotted name to a global object."""
[90] Fix | Delete
name = name.split('.')
[91] Fix | Delete
used = name.pop(0)
[92] Fix | Delete
found = __import__(used)
[93] Fix | Delete
for n in name:
[94] Fix | Delete
used = used + '.' + n
[95] Fix | Delete
try:
[96] Fix | Delete
found = getattr(found, n)
[97] Fix | Delete
except AttributeError:
[98] Fix | Delete
__import__(used)
[99] Fix | Delete
found = getattr(found, n)
[100] Fix | Delete
return found
[101] Fix | Delete
[102] Fix | Delete
def _strip_spaces(alist):
[103] Fix | Delete
return map(lambda x: x.strip(), alist)
[104] Fix | Delete
[105] Fix | Delete
def _create_formatters(cp):
[106] Fix | Delete
"""Create and return formatters"""
[107] Fix | Delete
flist = cp["formatters"]["keys"]
[108] Fix | Delete
if not len(flist):
[109] Fix | Delete
return {}
[110] Fix | Delete
flist = flist.split(",")
[111] Fix | Delete
flist = _strip_spaces(flist)
[112] Fix | Delete
formatters = {}
[113] Fix | Delete
for form in flist:
[114] Fix | Delete
sectname = "formatter_%s" % form
[115] Fix | Delete
fs = cp.get(sectname, "format", raw=True, fallback=None)
[116] Fix | Delete
dfs = cp.get(sectname, "datefmt", raw=True, fallback=None)
[117] Fix | Delete
stl = cp.get(sectname, "style", raw=True, fallback='%')
[118] Fix | Delete
c = logging.Formatter
[119] Fix | Delete
class_name = cp[sectname].get("class")
[120] Fix | Delete
if class_name:
[121] Fix | Delete
c = _resolve(class_name)
[122] Fix | Delete
f = c(fs, dfs, stl)
[123] Fix | Delete
formatters[form] = f
[124] Fix | Delete
return formatters
[125] Fix | Delete
[126] Fix | Delete
[127] Fix | Delete
def _install_handlers(cp, formatters):
[128] Fix | Delete
"""Install and return handlers"""
[129] Fix | Delete
hlist = cp["handlers"]["keys"]
[130] Fix | Delete
if not len(hlist):
[131] Fix | Delete
return {}
[132] Fix | Delete
hlist = hlist.split(",")
[133] Fix | Delete
hlist = _strip_spaces(hlist)
[134] Fix | Delete
handlers = {}
[135] Fix | Delete
fixups = [] #for inter-handler references
[136] Fix | Delete
for hand in hlist:
[137] Fix | Delete
section = cp["handler_%s" % hand]
[138] Fix | Delete
klass = section["class"]
[139] Fix | Delete
fmt = section.get("formatter", "")
[140] Fix | Delete
try:
[141] Fix | Delete
klass = eval(klass, vars(logging))
[142] Fix | Delete
except (AttributeError, NameError):
[143] Fix | Delete
klass = _resolve(klass)
[144] Fix | Delete
args = section["args"]
[145] Fix | Delete
args = eval(args, vars(logging))
[146] Fix | Delete
h = klass(*args)
[147] Fix | Delete
if "level" in section:
[148] Fix | Delete
level = section["level"]
[149] Fix | Delete
h.setLevel(level)
[150] Fix | Delete
if len(fmt):
[151] Fix | Delete
h.setFormatter(formatters[fmt])
[152] Fix | Delete
if issubclass(klass, logging.handlers.MemoryHandler):
[153] Fix | Delete
target = section.get("target", "")
[154] Fix | Delete
if len(target): #the target handler may not be loaded yet, so keep for later...
[155] Fix | Delete
fixups.append((h, target))
[156] Fix | Delete
handlers[hand] = h
[157] Fix | Delete
#now all handlers are loaded, fixup inter-handler references...
[158] Fix | Delete
for h, t in fixups:
[159] Fix | Delete
h.setTarget(handlers[t])
[160] Fix | Delete
return handlers
[161] Fix | Delete
[162] Fix | Delete
def _handle_existing_loggers(existing, child_loggers, disable_existing):
[163] Fix | Delete
"""
[164] Fix | Delete
When (re)configuring logging, handle loggers which were in the previous
[165] Fix | Delete
configuration but are not in the new configuration. There's no point
[166] Fix | Delete
deleting them as other threads may continue to hold references to them;
[167] Fix | Delete
and by disabling them, you stop them doing any logging.
[168] Fix | Delete
[169] Fix | Delete
However, don't disable children of named loggers, as that's probably not
[170] Fix | Delete
what was intended by the user. Also, allow existing loggers to NOT be
[171] Fix | Delete
disabled if disable_existing is false.
[172] Fix | Delete
"""
[173] Fix | Delete
root = logging.root
[174] Fix | Delete
for log in existing:
[175] Fix | Delete
logger = root.manager.loggerDict[log]
[176] Fix | Delete
if log in child_loggers:
[177] Fix | Delete
logger.level = logging.NOTSET
[178] Fix | Delete
logger.handlers = []
[179] Fix | Delete
logger.propagate = True
[180] Fix | Delete
else:
[181] Fix | Delete
logger.disabled = disable_existing
[182] Fix | Delete
[183] Fix | Delete
def _install_loggers(cp, handlers, disable_existing):
[184] Fix | Delete
"""Create and install loggers"""
[185] Fix | Delete
[186] Fix | Delete
# configure the root first
[187] Fix | Delete
llist = cp["loggers"]["keys"]
[188] Fix | Delete
llist = llist.split(",")
[189] Fix | Delete
llist = list(map(lambda x: x.strip(), llist))
[190] Fix | Delete
llist.remove("root")
[191] Fix | Delete
section = cp["logger_root"]
[192] Fix | Delete
root = logging.root
[193] Fix | Delete
log = root
[194] Fix | Delete
if "level" in section:
[195] Fix | Delete
level = section["level"]
[196] Fix | Delete
log.setLevel(level)
[197] Fix | Delete
for h in root.handlers[:]:
[198] Fix | Delete
root.removeHandler(h)
[199] Fix | Delete
hlist = section["handlers"]
[200] Fix | Delete
if len(hlist):
[201] Fix | Delete
hlist = hlist.split(",")
[202] Fix | Delete
hlist = _strip_spaces(hlist)
[203] Fix | Delete
for hand in hlist:
[204] Fix | Delete
log.addHandler(handlers[hand])
[205] Fix | Delete
[206] Fix | Delete
#and now the others...
[207] Fix | Delete
#we don't want to lose the existing loggers,
[208] Fix | Delete
#since other threads may have pointers to them.
[209] Fix | Delete
#existing is set to contain all existing loggers,
[210] Fix | Delete
#and as we go through the new configuration we
[211] Fix | Delete
#remove any which are configured. At the end,
[212] Fix | Delete
#what's left in existing is the set of loggers
[213] Fix | Delete
#which were in the previous configuration but
[214] Fix | Delete
#which are not in the new configuration.
[215] Fix | Delete
existing = list(root.manager.loggerDict.keys())
[216] Fix | Delete
#The list needs to be sorted so that we can
[217] Fix | Delete
#avoid disabling child loggers of explicitly
[218] Fix | Delete
#named loggers. With a sorted list it is easier
[219] Fix | Delete
#to find the child loggers.
[220] Fix | Delete
existing.sort()
[221] Fix | Delete
#We'll keep the list of existing loggers
[222] Fix | Delete
#which are children of named loggers here...
[223] Fix | Delete
child_loggers = []
[224] Fix | Delete
#now set up the new ones...
[225] Fix | Delete
for log in llist:
[226] Fix | Delete
section = cp["logger_%s" % log]
[227] Fix | Delete
qn = section["qualname"]
[228] Fix | Delete
propagate = section.getint("propagate", fallback=1)
[229] Fix | Delete
logger = logging.getLogger(qn)
[230] Fix | Delete
if qn in existing:
[231] Fix | Delete
i = existing.index(qn) + 1 # start with the entry after qn
[232] Fix | Delete
prefixed = qn + "."
[233] Fix | Delete
pflen = len(prefixed)
[234] Fix | Delete
num_existing = len(existing)
[235] Fix | Delete
while i < num_existing:
[236] Fix | Delete
if existing[i][:pflen] == prefixed:
[237] Fix | Delete
child_loggers.append(existing[i])
[238] Fix | Delete
i += 1
[239] Fix | Delete
existing.remove(qn)
[240] Fix | Delete
if "level" in section:
[241] Fix | Delete
level = section["level"]
[242] Fix | Delete
logger.setLevel(level)
[243] Fix | Delete
for h in logger.handlers[:]:
[244] Fix | Delete
logger.removeHandler(h)
[245] Fix | Delete
logger.propagate = propagate
[246] Fix | Delete
logger.disabled = 0
[247] Fix | Delete
hlist = section["handlers"]
[248] Fix | Delete
if len(hlist):
[249] Fix | Delete
hlist = hlist.split(",")
[250] Fix | Delete
hlist = _strip_spaces(hlist)
[251] Fix | Delete
for hand in hlist:
[252] Fix | Delete
logger.addHandler(handlers[hand])
[253] Fix | Delete
[254] Fix | Delete
#Disable any old loggers. There's no point deleting
[255] Fix | Delete
#them as other threads may continue to hold references
[256] Fix | Delete
#and by disabling them, you stop them doing any logging.
[257] Fix | Delete
#However, don't disable children of named loggers, as that's
[258] Fix | Delete
#probably not what was intended by the user.
[259] Fix | Delete
#for log in existing:
[260] Fix | Delete
# logger = root.manager.loggerDict[log]
[261] Fix | Delete
# if log in child_loggers:
[262] Fix | Delete
# logger.level = logging.NOTSET
[263] Fix | Delete
# logger.handlers = []
[264] Fix | Delete
# logger.propagate = 1
[265] Fix | Delete
# elif disable_existing_loggers:
[266] Fix | Delete
# logger.disabled = 1
[267] Fix | Delete
_handle_existing_loggers(existing, child_loggers, disable_existing)
[268] Fix | Delete
[269] Fix | Delete
[270] Fix | Delete
def _clearExistingHandlers():
[271] Fix | Delete
"""Clear and close existing handlers"""
[272] Fix | Delete
logging._handlers.clear()
[273] Fix | Delete
logging.shutdown(logging._handlerList[:])
[274] Fix | Delete
del logging._handlerList[:]
[275] Fix | Delete
[276] Fix | Delete
[277] Fix | Delete
IDENTIFIER = re.compile('^[a-z_][a-z0-9_]*$', re.I)
[278] Fix | Delete
[279] Fix | Delete
[280] Fix | Delete
def valid_ident(s):
[281] Fix | Delete
m = IDENTIFIER.match(s)
[282] Fix | Delete
if not m:
[283] Fix | Delete
raise ValueError('Not a valid Python identifier: %r' % s)
[284] Fix | Delete
return True
[285] Fix | Delete
[286] Fix | Delete
[287] Fix | Delete
class ConvertingMixin(object):
[288] Fix | Delete
"""For ConvertingXXX's, this mixin class provides common functions"""
[289] Fix | Delete
[290] Fix | Delete
def convert_with_key(self, key, value, replace=True):
[291] Fix | Delete
result = self.configurator.convert(value)
[292] Fix | Delete
#If the converted value is different, save for next time
[293] Fix | Delete
if value is not result:
[294] Fix | Delete
if replace:
[295] Fix | Delete
self[key] = result
[296] Fix | Delete
if type(result) in (ConvertingDict, ConvertingList,
[297] Fix | Delete
ConvertingTuple):
[298] Fix | Delete
result.parent = self
[299] Fix | Delete
result.key = key
[300] Fix | Delete
return result
[301] Fix | Delete
[302] Fix | Delete
def convert(self, value):
[303] Fix | Delete
result = self.configurator.convert(value)
[304] Fix | Delete
if value is not result:
[305] Fix | Delete
if type(result) in (ConvertingDict, ConvertingList,
[306] Fix | Delete
ConvertingTuple):
[307] Fix | Delete
result.parent = self
[308] Fix | Delete
return result
[309] Fix | Delete
[310] Fix | Delete
[311] Fix | Delete
# The ConvertingXXX classes are wrappers around standard Python containers,
[312] Fix | Delete
# and they serve to convert any suitable values in the container. The
[313] Fix | Delete
# conversion converts base dicts, lists and tuples to their wrapped
[314] Fix | Delete
# equivalents, whereas strings which match a conversion format are converted
[315] Fix | Delete
# appropriately.
[316] Fix | Delete
#
[317] Fix | Delete
# Each wrapper should have a configurator attribute holding the actual
[318] Fix | Delete
# configurator to use for conversion.
[319] Fix | Delete
[320] Fix | Delete
class ConvertingDict(dict, ConvertingMixin):
[321] Fix | Delete
"""A converting dictionary wrapper."""
[322] Fix | Delete
[323] Fix | Delete
def __getitem__(self, key):
[324] Fix | Delete
value = dict.__getitem__(self, key)
[325] Fix | Delete
return self.convert_with_key(key, value)
[326] Fix | Delete
[327] Fix | Delete
def get(self, key, default=None):
[328] Fix | Delete
value = dict.get(self, key, default)
[329] Fix | Delete
return self.convert_with_key(key, value)
[330] Fix | Delete
[331] Fix | Delete
def pop(self, key, default=None):
[332] Fix | Delete
value = dict.pop(self, key, default)
[333] Fix | Delete
return self.convert_with_key(key, value, replace=False)
[334] Fix | Delete
[335] Fix | Delete
class ConvertingList(list, ConvertingMixin):
[336] Fix | Delete
"""A converting list wrapper."""
[337] Fix | Delete
def __getitem__(self, key):
[338] Fix | Delete
value = list.__getitem__(self, key)
[339] Fix | Delete
return self.convert_with_key(key, value)
[340] Fix | Delete
[341] Fix | Delete
def pop(self, idx=-1):
[342] Fix | Delete
value = list.pop(self, idx)
[343] Fix | Delete
return self.convert(value)
[344] Fix | Delete
[345] Fix | Delete
class ConvertingTuple(tuple, ConvertingMixin):
[346] Fix | Delete
"""A converting tuple wrapper."""
[347] Fix | Delete
def __getitem__(self, key):
[348] Fix | Delete
value = tuple.__getitem__(self, key)
[349] Fix | Delete
# Can't replace a tuple entry.
[350] Fix | Delete
return self.convert_with_key(key, value, replace=False)
[351] Fix | Delete
[352] Fix | Delete
class BaseConfigurator(object):
[353] Fix | Delete
"""
[354] Fix | Delete
The configurator base class which defines some useful defaults.
[355] Fix | Delete
"""
[356] Fix | Delete
[357] Fix | Delete
CONVERT_PATTERN = re.compile(r'^(?P<prefix>[a-z]+)://(?P<suffix>.*)$')
[358] Fix | Delete
[359] Fix | Delete
WORD_PATTERN = re.compile(r'^\s*(\w+)\s*')
[360] Fix | Delete
DOT_PATTERN = re.compile(r'^\.\s*(\w+)\s*')
[361] Fix | Delete
INDEX_PATTERN = re.compile(r'^\[\s*(\w+)\s*\]\s*')
[362] Fix | Delete
DIGIT_PATTERN = re.compile(r'^\d+$')
[363] Fix | Delete
[364] Fix | Delete
value_converters = {
[365] Fix | Delete
'ext' : 'ext_convert',
[366] Fix | Delete
'cfg' : 'cfg_convert',
[367] Fix | Delete
}
[368] Fix | Delete
[369] Fix | Delete
# We might want to use a different one, e.g. importlib
[370] Fix | Delete
importer = staticmethod(__import__)
[371] Fix | Delete
[372] Fix | Delete
def __init__(self, config):
[373] Fix | Delete
self.config = ConvertingDict(config)
[374] Fix | Delete
self.config.configurator = self
[375] Fix | Delete
[376] Fix | Delete
def resolve(self, s):
[377] Fix | Delete
"""
[378] Fix | Delete
Resolve strings to objects using standard import and attribute
[379] Fix | Delete
syntax.
[380] Fix | Delete
"""
[381] Fix | Delete
name = s.split('.')
[382] Fix | Delete
used = name.pop(0)
[383] Fix | Delete
try:
[384] Fix | Delete
found = self.importer(used)
[385] Fix | Delete
for frag in name:
[386] Fix | Delete
used += '.' + frag
[387] Fix | Delete
try:
[388] Fix | Delete
found = getattr(found, frag)
[389] Fix | Delete
except AttributeError:
[390] Fix | Delete
self.importer(used)
[391] Fix | Delete
found = getattr(found, frag)
[392] Fix | Delete
return found
[393] Fix | Delete
except ImportError:
[394] Fix | Delete
e, tb = sys.exc_info()[1:]
[395] Fix | Delete
v = ValueError('Cannot resolve %r: %s' % (s, e))
[396] Fix | Delete
v.__cause__, v.__traceback__ = e, tb
[397] Fix | Delete
raise v
[398] Fix | Delete
[399] Fix | Delete
def ext_convert(self, value):
[400] Fix | Delete
"""Default converter for the ext:// protocol."""
[401] Fix | Delete
return self.resolve(value)
[402] Fix | Delete
[403] Fix | Delete
def cfg_convert(self, value):
[404] Fix | Delete
"""Default converter for the cfg:// protocol."""
[405] Fix | Delete
rest = value
[406] Fix | Delete
m = self.WORD_PATTERN.match(rest)
[407] Fix | Delete
if m is None:
[408] Fix | Delete
raise ValueError("Unable to convert %r" % value)
[409] Fix | Delete
else:
[410] Fix | Delete
rest = rest[m.end():]
[411] Fix | Delete
d = self.config[m.groups()[0]]
[412] Fix | Delete
#print d, rest
[413] Fix | Delete
while rest:
[414] Fix | Delete
m = self.DOT_PATTERN.match(rest)
[415] Fix | Delete
if m:
[416] Fix | Delete
d = d[m.groups()[0]]
[417] Fix | Delete
else:
[418] Fix | Delete
m = self.INDEX_PATTERN.match(rest)
[419] Fix | Delete
if m:
[420] Fix | Delete
idx = m.groups()[0]
[421] Fix | Delete
if not self.DIGIT_PATTERN.match(idx):
[422] Fix | Delete
d = d[idx]
[423] Fix | Delete
else:
[424] Fix | Delete
try:
[425] Fix | Delete
n = int(idx) # try as number first (most likely)
[426] Fix | Delete
d = d[n]
[427] Fix | Delete
except TypeError:
[428] Fix | Delete
d = d[idx]
[429] Fix | Delete
if m:
[430] Fix | Delete
rest = rest[m.end():]
[431] Fix | Delete
else:
[432] Fix | Delete
raise ValueError('Unable to convert '
[433] Fix | Delete
'%r at %r' % (value, rest))
[434] Fix | Delete
#rest should be empty
[435] Fix | Delete
return d
[436] Fix | Delete
[437] Fix | Delete
def convert(self, value):
[438] Fix | Delete
"""
[439] Fix | Delete
Convert values to an appropriate type. dicts, lists and tuples are
[440] Fix | Delete
replaced by their converting alternatives. Strings are checked to
[441] Fix | Delete
see if they have a conversion format and are converted if they do.
[442] Fix | Delete
"""
[443] Fix | Delete
if not isinstance(value, ConvertingDict) and isinstance(value, dict):
[444] Fix | Delete
value = ConvertingDict(value)
[445] Fix | Delete
value.configurator = self
[446] Fix | Delete
elif not isinstance(value, ConvertingList) and isinstance(value, list):
[447] Fix | Delete
value = ConvertingList(value)
[448] Fix | Delete
value.configurator = self
[449] Fix | Delete
elif not isinstance(value, ConvertingTuple) and\
[450] Fix | Delete
isinstance(value, tuple):
[451] Fix | Delete
value = ConvertingTuple(value)
[452] Fix | Delete
value.configurator = self
[453] Fix | Delete
elif isinstance(value, str): # str for py3k
[454] Fix | Delete
m = self.CONVERT_PATTERN.match(value)
[455] Fix | Delete
if m:
[456] Fix | Delete
d = m.groupdict()
[457] Fix | Delete
prefix = d['prefix']
[458] Fix | Delete
converter = self.value_converters.get(prefix, None)
[459] Fix | Delete
if converter:
[460] Fix | Delete
suffix = d['suffix']
[461] Fix | Delete
converter = getattr(self, converter)
[462] Fix | Delete
value = converter(suffix)
[463] Fix | Delete
return value
[464] Fix | Delete
[465] Fix | Delete
def configure_custom(self, config):
[466] Fix | Delete
"""Configure an object with a user-supplied factory."""
[467] Fix | Delete
c = config.pop('()')
[468] Fix | Delete
if not callable(c):
[469] Fix | Delete
c = self.resolve(c)
[470] Fix | Delete
props = config.pop('.', None)
[471] Fix | Delete
# Check for valid identifiers
[472] Fix | Delete
kwargs = dict([(k, config[k]) for k in config if valid_ident(k)])
[473] Fix | Delete
result = c(**kwargs)
[474] Fix | Delete
if props:
[475] Fix | Delete
for name, value in props.items():
[476] Fix | Delete
setattr(result, name, value)
[477] Fix | Delete
return result
[478] Fix | Delete
[479] Fix | Delete
def as_tuple(self, value):
[480] Fix | Delete
"""Utility function which converts lists to tuples."""
[481] Fix | Delete
if isinstance(value, list):
[482] Fix | Delete
value = tuple(value)
[483] Fix | Delete
return value
[484] Fix | Delete
[485] Fix | Delete
class DictConfigurator(BaseConfigurator):
[486] Fix | Delete
"""
[487] Fix | Delete
Configure logging using a dictionary-like object to describe the
[488] Fix | Delete
configuration.
[489] Fix | Delete
"""
[490] Fix | Delete
[491] Fix | Delete
def configure(self):
[492] Fix | Delete
"""Do the configuration."""
[493] Fix | Delete
[494] Fix | Delete
config = self.config
[495] Fix | Delete
if 'version' not in config:
[496] Fix | Delete
raise ValueError("dictionary doesn't specify a version")
[497] Fix | Delete
if config['version'] != 1:
[498] Fix | Delete
raise ValueError("Unsupported version: %s" % config['version'])
[499] Fix | Delete
12
It is recommended that you Edit text format, this type of Fix handles quite a lot in one request
Function