mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2024-12-30 10:47:08 -06:00
d9d1967989
Move the code for encoding boolean values to LDAP boolean syntax from the Parameter class to the Encoder class, where the rest of LDAP encoding takes place. Remove encoding code from the Parameter class altogether, as all LDAP encoding should be done in the Encoder class.
214 lines
8.0 KiB
Python
214 lines
8.0 KiB
Python
# 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, either version 3 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# 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, see <http://www.gnu.org/licenses/>.
|
|
"""
|
|
Encoding capabilities.
|
|
"""
|
|
|
|
from decimal import Decimal
|
|
|
|
class EncoderSettings(object):
|
|
"""
|
|
Container for encoder settings.
|
|
"""
|
|
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()
|
|
decode_dict_vals_table_keygen = staticmethod(lambda x, y: x)
|
|
decode_postprocessor = staticmethod(lambda x: x)
|
|
|
|
|
|
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()
|
|
|
|
def _decode_dict_val(self, key, val):
|
|
f = self.encoder_settings.decode_dict_vals_table.get(
|
|
self.encoder_settings.decode_dict_vals_table_keygen(key, val)
|
|
)
|
|
if f:
|
|
return val
|
|
return self.decode(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, str):
|
|
return var
|
|
elif isinstance(var, unicode):
|
|
return self.encoder_settings.encode_postprocessor(
|
|
var.encode(self.encoder_settings.encode_to)
|
|
)
|
|
elif isinstance(var, bool):
|
|
if var:
|
|
var = 'TRUE'
|
|
else:
|
|
var = 'FALSE'
|
|
return self.encoder_settings.encode_postprocessor(
|
|
var.encode(self.encoder_settings.encode_to)
|
|
)
|
|
elif isinstance(var, (float, Decimal, int, long)):
|
|
return self.encoder_settings.encode_postprocessor(
|
|
str(var).encode(self.encoder_settings.encode_to)
|
|
)
|
|
elif isinstance(var, list):
|
|
return [self.encode(m) for m in var]
|
|
elif isinstance(var, tuple):
|
|
return tuple(self.encode(m) for m in var)
|
|
elif isinstance(var, dict):
|
|
if self.encoder_settings.encode_dict_keys:
|
|
dct = dict()
|
|
if not self.encoder_settings.encode_dict_keys_postprocess:
|
|
tmp = self.encoder_settings.encode_postprocessor
|
|
self.encoder_settings.encode_postprocessor = lambda x: x
|
|
for (k, v) in var.iteritems():
|
|
dct[self.encode(k)] = v
|
|
if not self.encoder_settings.encode_dict_keys_postprocess:
|
|
self.encoder_settings.encode_postprocessor = tmp
|
|
else:
|
|
dct = dict(var)
|
|
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
|
|
for (k, v) in dct.iteritems():
|
|
dct[k] = self.encode(v)
|
|
if not self.encoder_settings.encode_dict_vals_postprocess:
|
|
self.encoder_settings.encode_postprocessor = tmp
|
|
return dct
|
|
elif var is None:
|
|
if self.encoder_settings.encode_none:
|
|
return self.encoder_settings.encode_postprocessor(
|
|
str(var).encode(self.encoder_settings.encode_to)
|
|
)
|
|
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, unicode):
|
|
return var
|
|
elif isinstance(var, str):
|
|
return self.encoder_settings.decode_postprocessor(
|
|
var.decode(self.encoder_settings.decode_from)
|
|
)
|
|
elif isinstance(var, (bool, float, Decimal, int, long)):
|
|
return var
|
|
elif isinstance(var, list):
|
|
return [self.decode(m) for m in var]
|
|
elif isinstance(var, tuple):
|
|
return tuple(self.decode(m) for m in var)
|
|
elif isinstance(var, dict):
|
|
if self.encoder_settings.decode_dict_keys:
|
|
dct = dict()
|
|
if not self.encoder_settings.decode_dict_keys_postprocess:
|
|
tmp = self.encoder_settings.decode_postprocessor
|
|
self.encoder_settings.decode_postprocessor = lambda x: x
|
|
for (k, v) in var.iteritems():
|
|
dct[self.decode(k)] = v
|
|
if not self.encoder_settings.decode_dict_keys_postprocess:
|
|
self.encoder_settings.decode_postprocessor = tmp
|
|
else:
|
|
dct = dict(var)
|
|
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
|
|
for (k, v) in dct.iteritems():
|
|
dct[k] = self._decode_dict_val(k, v)
|
|
if not self.encoder_settings.decode_dict_vals_postprocess:
|
|
self.encoder_settings.decode_postprocessor = tmp
|
|
return dct
|
|
elif var is None:
|
|
if self.encoder_settings.decode_none:
|
|
return self.encoder_settings.decode_postprocessor(
|
|
str(var).decode(self.encoder_settings.decode_from)
|
|
)
|
|
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):
|
|
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])
|
|
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
|
|
|