From 114b6b8577ca9585efe8914d5fdd739f208d6ba8 Mon Sep 17 00:00:00 2001 From: Jason Gerard DeRose Date: Fri, 23 Jan 2009 12:20:32 -0700 Subject: Added some missing parameter unit tests; added docstring about Command._repr_iter() and Param.safe_value() --- ipalib/frontend.py | 24 +++++++++++++++++++++--- ipalib/parameters.py | 20 ++++++++++++++++++++ 2 files changed, 41 insertions(+), 3 deletions(-) (limited to 'ipalib') diff --git a/ipalib/frontend.py b/ipalib/frontend.py index 565060b5..3665cc0e 100644 --- a/ipalib/frontend.py +++ b/ipalib/frontend.py @@ -98,7 +98,7 @@ class Command(plugable.Plugin): """ params = self.args_options_2_params(*args, **options) self.info( - '%s(%s)', self.name, ', '.join(self.__repr_iter(params)) + '%s(%s)', self.name, ', '.join(self._repr_iter(**params)) ) params = self.normalize(**params) params = self.convert(**params) @@ -109,10 +109,28 @@ class Command(plugable.Plugin): self.debug('result from %s(): %r', self.name, result) return result - def __repr_iter(self, params): + def _repr_iter(self, **params): + """ + Iterate through ``repr()`` of *safe* values of args and options. + + This method uses `parameters.Param.safe_value()` to mask passwords when + logging. Logging the exact call is extremely useful, but we obviously + don't want to log the cleartext password. + + For example: + + >>> class my_cmd(Command): + ... takes_args = ('login',) + ... takes_options=(Password('passwd'),) + ... + >>> c = my_cmd() + >>> c.finalize() + >>> list(c._repr_iter(login=u'Okay.', passwd=u'Private!')) + ["u'Okay.'", "passwd=u'********'"] + """ for arg in self.args(): value = params.get(arg.name, None) - yield '%r' % (arg.safe_value(value),) + yield repr(arg.safe_value(value)) for option in self.options(): if option.name not in params: continue diff --git a/ipalib/parameters.py b/ipalib/parameters.py index 6ce0ad80..fe32c92f 100644 --- a/ipalib/parameters.py +++ b/ipalib/parameters.py @@ -359,6 +359,26 @@ class Param(ReadOnly): return value def safe_value(self, value): + """ + Return a value safe for logging. + + This is used so that passwords don't get logged. If this is a + `Password` instance and ``value`` is not ``None``, a constant + ``u'********'`` is returned. For example: + + >>> p = Password('my_password') + >>> p.safe_value(u'This is my password') + u'********' + >>> p.safe_value(None) is None + True + + If this is not a `Password` instance, ``value`` is returned unchanged. + For example: + + >>> s = Str('my_str') + >>> s.safe_value(u'Some arbitrary value') + u'Some arbitrary value' + """ if self.password and value is not None: return u'********' return value -- cgit