2009-05-14 11:29:00 -05:00
|
|
|
# Authors:
|
|
|
|
# Pavel Zuna <pzuna@redhat.com>
|
|
|
|
#
|
|
|
|
# Copyright (C) 2009 Red Hat
|
|
|
|
# see file 'COPYING' for use and warranty information
|
|
|
|
#
|
|
|
|
# This program is free software; you can redistribute it and/or
|
|
|
|
# modify it under the terms of the GNU General Public License as
|
|
|
|
# published by the Free Software Foundation; version 2 only
|
|
|
|
#
|
|
|
|
# This program is distributed in the hope that it will be useful,
|
|
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
# GNU General Public License for more details.
|
|
|
|
#
|
|
|
|
# You should have received a copy of the GNU General Public License
|
|
|
|
# along with this program; if not, write to the Free Software
|
|
|
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
"""
|
2009-05-22 05:10:40 -05:00
|
|
|
Encoding capabilities.
|
2009-05-14 11:29:00 -05:00
|
|
|
"""
|
|
|
|
|
2009-05-22 05:10:40 -05:00
|
|
|
class EncoderSettings(object):
|
2009-05-14 11:29:00 -05:00
|
|
|
"""
|
2009-05-22 05:10:40 -05:00
|
|
|
Container for encoder settings.
|
2009-05-14 11:29:00 -05:00
|
|
|
"""
|
|
|
|
encode_to = 'utf-8'
|
|
|
|
encode_none = False
|
|
|
|
encode_dict_keys = False
|
|
|
|
encode_dict_keys_postprocess = True
|
|
|
|
encode_dict_vals = True
|
|
|
|
encode_dict_vals_postprocess = True
|
|
|
|
encode_postprocessor = staticmethod(lambda x: x)
|
|
|
|
|
|
|
|
decode_from = 'utf-8'
|
|
|
|
decode_none = False
|
|
|
|
decode_dict_keys = False
|
|
|
|
decode_dict_keys_postprocess = True
|
|
|
|
decode_dict_vals = True
|
|
|
|
decode_dict_vals_postprocess = True
|
|
|
|
decode_dict_vals_table = dict()
|
2009-05-25 03:12:40 -05:00
|
|
|
decode_dict_vals_table_keygen = staticmethod(lambda x, y: x)
|
2009-05-14 11:29:00 -05:00
|
|
|
decode_postprocessor = staticmethod(lambda x: x)
|
|
|
|
|
2009-05-22 05:10:40 -05:00
|
|
|
|
|
|
|
class Encoder(object):
|
|
|
|
"""
|
|
|
|
Base class implementing encoding of python scalar types to strings
|
|
|
|
and vise-versa.
|
|
|
|
"""
|
|
|
|
|
|
|
|
encoder_settings = EncoderSettings()
|
|
|
|
|
|
|
|
def __init__(self):
|
|
|
|
# each instance should have its own settings
|
|
|
|
self.encoder_settings = EncoderSettings()
|
|
|
|
|
2009-05-14 11:29:00 -05:00
|
|
|
def _decode_dict_val(self, key, val):
|
2009-05-22 05:10:40 -05:00
|
|
|
f = self.encoder_settings.decode_dict_vals_table.get(
|
|
|
|
self.encoder_settings.decode_dict_vals_table_keygen(key, val),
|
|
|
|
self.decode
|
2009-05-14 11:29:00 -05:00
|
|
|
)
|
|
|
|
return f(val)
|
|
|
|
|
|
|
|
def encode(self, var):
|
|
|
|
"""
|
|
|
|
Encode any python built-in python type variable into `self.encode_to`.
|
|
|
|
|
|
|
|
Compound types have their individual members encoded.
|
|
|
|
|
|
|
|
Returns an encoded copy of 'var'.
|
|
|
|
"""
|
|
|
|
if isinstance(var, basestring):
|
2009-05-22 05:10:40 -05:00
|
|
|
return self.encoder_settings.encode_postprocessor(
|
|
|
|
var.encode(self.encoder_settings.encode_to)
|
|
|
|
)
|
2009-05-14 11:29:00 -05:00
|
|
|
elif isinstance(var, (bool, float, int, long)):
|
2009-05-22 05:10:40 -05:00
|
|
|
return self.encoder_settings.encode_postprocessor(
|
|
|
|
str(var).encode(self.encoder_settings.encode_to)
|
|
|
|
)
|
2009-05-14 11:29:00 -05:00
|
|
|
elif isinstance(var, list):
|
|
|
|
return [self.encode(m) for m in var]
|
|
|
|
elif isinstance(var, tuple):
|
2009-05-25 03:12:40 -05:00
|
|
|
return tuple(self.encode(m) for m in var)
|
2009-05-14 11:29:00 -05:00
|
|
|
elif isinstance(var, dict):
|
2009-05-22 05:10:40 -05:00
|
|
|
if self.encoder_settings.encode_dict_keys:
|
2009-05-14 11:29:00 -05:00
|
|
|
dct = dict()
|
2009-05-22 05:10:40 -05:00
|
|
|
if not self.encoder_settings.encode_dict_keys_postprocess:
|
|
|
|
tmp = self.encoder_settings.encode_postprocessor
|
|
|
|
self.encoder_settings.encode_postprocessor = lambda x: x
|
2009-05-14 11:29:00 -05:00
|
|
|
for (k, v) in var.iteritems():
|
|
|
|
dct[self.encode(k)] = v
|
2009-05-22 05:10:40 -05:00
|
|
|
if not self.encoder_settings.encode_dict_keys_postprocess:
|
|
|
|
self.encoder_settings.encode_postprocessor = tmp
|
2009-05-14 11:29:00 -05:00
|
|
|
else:
|
|
|
|
dct = dict(var)
|
2009-05-22 05:10:40 -05:00
|
|
|
if self.encoder_settings.encode_dict_vals:
|
|
|
|
if not self.encoder_settings.encode_dict_vals_postprocess:
|
|
|
|
tmp = self.encoder_settings.encode_postprocessor
|
|
|
|
self.encoder_settings.encode_postprocessor = lambda x: x
|
2009-05-14 11:29:00 -05:00
|
|
|
for (k, v) in dct.iteritems():
|
|
|
|
dct[k] = self.encode(v)
|
2009-05-22 05:10:40 -05:00
|
|
|
if not self.encoder_settings.encode_dict_vals_postprocess:
|
|
|
|
self.encoder_settings.encode_postprocessor = tmp
|
2009-05-14 11:29:00 -05:00
|
|
|
return dct
|
|
|
|
elif var is None:
|
2009-05-22 05:10:40 -05:00
|
|
|
if self.encoder_settings.encode_none:
|
|
|
|
return self.encoder_settings.encode_postprocessor(
|
|
|
|
str(var).encode(self.encoder_settings.encode_to)
|
2009-05-14 11:29:00 -05:00
|
|
|
)
|
|
|
|
return None
|
|
|
|
raise TypeError('python built-in type expected, got \'%s\'', type(var))
|
|
|
|
|
|
|
|
def decode(self, var):
|
|
|
|
"""
|
|
|
|
Decode strings in `self.decode_from` into python strings.
|
|
|
|
|
|
|
|
Compound types have their individual members decoded.
|
|
|
|
|
|
|
|
Dictionaries can have their values decoded into other types
|
|
|
|
by looking up keys in `self.decode_dict_vals_table`.
|
|
|
|
|
|
|
|
Returns a decoded copy of 'var'.
|
|
|
|
"""
|
|
|
|
if isinstance(var, basestring):
|
2009-05-22 05:10:40 -05:00
|
|
|
return self.encoder_settings.decode_postprocessor(
|
|
|
|
var.decode(self.encoder_settings.decode_from)
|
|
|
|
)
|
2009-05-14 11:29:00 -05:00
|
|
|
elif isinstance(var, (bool, float, int, long)):
|
2009-06-15 08:50:50 -05:00
|
|
|
return var
|
2009-05-14 11:29:00 -05:00
|
|
|
elif isinstance(var, list):
|
|
|
|
return [self.decode(m) for m in var]
|
|
|
|
elif isinstance(var, tuple):
|
2009-05-25 03:12:40 -05:00
|
|
|
return tuple(self.decode(m) for m in var)
|
2009-05-14 11:29:00 -05:00
|
|
|
elif isinstance(var, dict):
|
2009-05-22 05:10:40 -05:00
|
|
|
if self.encoder_settings.decode_dict_keys:
|
2009-05-14 11:29:00 -05:00
|
|
|
dct = dict()
|
2009-05-22 05:10:40 -05:00
|
|
|
if not self.encoder_settings.decode_dict_keys_postprocess:
|
|
|
|
tmp = self.encoder_settings.decode_postprocessor
|
|
|
|
self.encoder_settings.decode_postprocessor = lambda x: x
|
2009-05-14 11:29:00 -05:00
|
|
|
for (k, v) in var.iteritems():
|
|
|
|
dct[self.decode(k)] = v
|
2009-05-22 05:10:40 -05:00
|
|
|
if not self.encoder_settings.decode_dict_keys_postprocess:
|
|
|
|
self.encoder_settings.decode_postprocessor = tmp
|
2009-05-14 11:29:00 -05:00
|
|
|
else:
|
|
|
|
dct = dict(var)
|
2009-05-22 05:10:40 -05:00
|
|
|
if self.encoder_settings.decode_dict_vals:
|
|
|
|
if not self.encoder_settings.decode_dict_vals_postprocess:
|
|
|
|
tmp = self.encoder_settings.decode_postprocessor
|
|
|
|
self.encoder_settings.decode_postprocessor = lambda x: x
|
2009-05-14 11:29:00 -05:00
|
|
|
for (k, v) in dct.iteritems():
|
|
|
|
dct[k] = self._decode_dict_val(k, v)
|
2009-05-22 05:10:40 -05:00
|
|
|
if not self.encoder_settings.decode_dict_vals_postprocess:
|
|
|
|
self.encoder_settings.decode_postprocessor = tmp
|
2009-05-14 11:29:00 -05:00
|
|
|
return dct
|
|
|
|
elif var is None:
|
2009-05-22 05:10:40 -05:00
|
|
|
if self.encoder_settings.decode_none:
|
|
|
|
return self.encoder_settings.decode_postprocessor(
|
|
|
|
str(var).decode(self.encoder_settings.decode_from)
|
2009-05-14 11:29:00 -05:00
|
|
|
)
|
|
|
|
return None
|
|
|
|
raise TypeError('python built-in type expected, got \'%s\'', type(var))
|
|
|
|
|
|
|
|
## ENCODER METHOD DECORATORS
|
|
|
|
|
|
|
|
def encode_args(*outer_args):
|
|
|
|
def decorate(f):
|
|
|
|
def new_f(*args, **kwargs):
|
|
|
|
assert isinstance(args[0], Encoder), \
|
|
|
|
'first argument not Encoder instance'
|
|
|
|
new_args = list(args)
|
|
|
|
for a in outer_args:
|
|
|
|
if isinstance(a, int):
|
2009-05-22 05:10:40 -05:00
|
|
|
if a < len(args):
|
|
|
|
new_args[a] = args[0].encode(args[a])
|
|
|
|
elif isinstance(a, basestring):
|
|
|
|
if a in kwargs:
|
|
|
|
kwargs[a] = args[0].encode(kwargs[a])
|
2009-05-14 11:29:00 -05:00
|
|
|
else:
|
|
|
|
raise TypeError(
|
|
|
|
'encode_args takes a list of ints and basestrings'
|
|
|
|
)
|
|
|
|
return f(*new_args, **kwargs)
|
|
|
|
new_f.func_name = f.func_name
|
|
|
|
return new_f
|
|
|
|
return decorate
|
|
|
|
|
|
|
|
|
|
|
|
def decode_retval():
|
|
|
|
def decorate(f):
|
|
|
|
def new_f(*args, **kwargs):
|
|
|
|
assert isinstance(args[0], Encoder), \
|
|
|
|
'first argument not Encoder instance'
|
|
|
|
return args[0].decode(f(*args, **kwargs))
|
|
|
|
new_f.func_name = f.func_name
|
|
|
|
return new_f
|
|
|
|
return decorate
|
|
|
|
|