Sat, 04 Jun 2011 06:59:00 in Tech stuff | permalink
MaskedString still holds the actuall string data which is
accessible via __getitem__ but overrides __str__ and
__repr__ so that the string is presented in blinded form. This is
useful for preventing leakage of sensitive data (card numbers, passwords etc.)
to log files.
class MaskedString(str):
'''
>>> ms = MaskedString('foobar')
>>> ms
'******'
>>> str(ms)
'******'
>>> ms[:]
'foobar'
>>> ms = MaskedString('foobar', show_last=4)
>>> str(ms)
'**obar'
>>> ms == 'foobar'
True
'''
def __new__(cls, arg, symbol='*', show_last=None):
return super(MaskedString, cls).__new__(cls, arg)
def __init__(self, arg, symbol='*', show_last=None):
super(MaskedString, self).__init__()
self.symbol = symbol
self.show_last = show_last or 0
def __str__(self):
l = len(self) - self.show_last
last = ''
if self.show_last > 0:
last = self[-self.show_last:]
return self.symbol * l + last
def __repr__(self):
return repr(self.__str__())
import logging
logging.basicConfig(level=logging.INFO)
request = dict(
user='timur',
password=MaskedString('secret'),
card_number=MaskedString('0000000000000000000', show_last=4),
)
logging.info('request: %r', request)
Output:
INFO:root:request: {'password': '******', 'card_number': '***************0000', 'user': 'timur'}