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