Closes #20444: Merged fix from 3.4.

This commit is contained in:
Vinay Sajip 2014-03-20 13:15:23 +00:00
commit ab405d5575
1 changed files with 34 additions and 50 deletions

View File

@ -277,6 +277,30 @@ def valid_ident(s):
return True return True
class ConvertingMixin(object):
"""For ConvertingXXX's, this mixin class provides common functions"""
def convert_with_key(self, key, value, replace=True):
result = self.configurator.convert(value)
#If the converted value is different, save for next time
if value is not result:
if replace:
self[key] = result
if type(result) in (ConvertingDict, ConvertingList,
ConvertingTuple):
result.parent = self
result.key = key
return result
def convert(self, value):
result = self.configurator.convert(value)
if value is not result:
if type(result) in (ConvertingDict, ConvertingList,
ConvertingTuple):
result.parent = self
return result
# The ConvertingXXX classes are wrappers around standard Python containers, # The ConvertingXXX classes are wrappers around standard Python containers,
# and they serve to convert any suitable values in the container. The # and they serve to convert any suitable values in the container. The
# conversion converts base dicts, lists and tuples to their wrapped # conversion converts base dicts, lists and tuples to their wrapped
@ -286,77 +310,37 @@ def valid_ident(s):
# Each wrapper should have a configurator attribute holding the actual # Each wrapper should have a configurator attribute holding the actual
# configurator to use for conversion. # configurator to use for conversion.
class ConvertingDict(dict): class ConvertingDict(dict, ConvertingMixin):
"""A converting dictionary wrapper.""" """A converting dictionary wrapper."""
def __getitem__(self, key): def __getitem__(self, key):
value = dict.__getitem__(self, key) value = dict.__getitem__(self, key)
result = self.configurator.convert(value) return self.convert_with_key(key, value)
#If the converted value is different, save for next time
if value is not result:
self[key] = result
if type(result) in (ConvertingDict, ConvertingList,
ConvertingTuple):
result.parent = self
result.key = key
return result
def get(self, key, default=None): def get(self, key, default=None):
value = dict.get(self, key, default) value = dict.get(self, key, default)
result = self.configurator.convert(value) return self.convert_with_key(key, value)
#If the converted value is different, save for next time
if value is not result:
self[key] = result
if type(result) in (ConvertingDict, ConvertingList,
ConvertingTuple):
result.parent = self
result.key = key
return result
def pop(self, key, default=None): def pop(self, key, default=None):
value = dict.pop(self, key, default) value = dict.pop(self, key, default)
result = self.configurator.convert(value) return self.convert_with_key(key, value, replace=False)
if value is not result:
if type(result) in (ConvertingDict, ConvertingList,
ConvertingTuple):
result.parent = self
result.key = key
return result
class ConvertingList(list): class ConvertingList(list, ConvertingMixin):
"""A converting list wrapper.""" """A converting list wrapper."""
def __getitem__(self, key): def __getitem__(self, key):
value = list.__getitem__(self, key) value = list.__getitem__(self, key)
result = self.configurator.convert(value) return self.convert_with_key(key, value)
#If the converted value is different, save for next time
if value is not result:
self[key] = result
if type(result) in (ConvertingDict, ConvertingList,
ConvertingTuple):
result.parent = self
result.key = key
return result
def pop(self, idx=-1): def pop(self, idx=-1):
value = list.pop(self, idx) value = list.pop(self, idx)
result = self.configurator.convert(value) return self.convert(value)
if value is not result:
if type(result) in (ConvertingDict, ConvertingList,
ConvertingTuple):
result.parent = self
return result
class ConvertingTuple(tuple): class ConvertingTuple(tuple, ConvertingMixin):
"""A converting tuple wrapper.""" """A converting tuple wrapper."""
def __getitem__(self, key): def __getitem__(self, key):
value = tuple.__getitem__(self, key) value = tuple.__getitem__(self, key)
result = self.configurator.convert(value) # Can't replace a tuple entry.
if value is not result: return self.convert_with_key(key, value, replace=False)
if type(result) in (ConvertingDict, ConvertingList,
ConvertingTuple):
result.parent = self
result.key = key
return result
class BaseConfigurator(object): class BaseConfigurator(object):
""" """