Skip to content

Instantly share code, notes, and snippets.

@matthewstory
Created March 20, 2014 04:47
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save matthewstory/9657448 to your computer and use it in GitHub Desktop.
Save matthewstory/9657448 to your computer and use it in GitHub Desktop.
unicodify and stringify decorators
'''Decorators to convert all arguments passed to a function or method to
unicode or str, including default arguments'''
import sys
import functools
import inspect
def _convert_arg(arg, from_, conv, enc):
'''Safely convert unicode to string or string to unicode'''
return getattr(arg, conv)(encoding=enc) if isinstance(arg, from_) else arg
def _wrap_convert(from_type, fn, encoding=None):
'''Decorate a function converting all str arguments to unicode or
vice-versa'''
conv = 'decode' if from_type is str else 'encode'
encoding = encoding or sys.getdefaultencoding()
# override string defaults using partial
aspec, dflts = inspect.getargspec(fn), {}
if aspec.defaults:
for k,v in zip(aspec.args[-len(aspec.defaults):],aspec.defaults):
dflts[k] = _convert_arg(v, from_type, conv, encoding)
fn = functools.partial(fn, **dflts)
@functools.wraps(fn.func if isinstance(fn, functools.partial) else fn)
def converted(*args, **kwargs):
args = [_convert_arg(a, from_type, conv, encoding) for a in args]
for k,v in kwargs.iteritems():
kwargs[k] = _convert_arg(v, from_type, conv, encoding)
return fn(*args, **kwargs)
return converted
def unicodify(fn=None, encoding=None):
'''Convert all str arguments to unicode'''
if fn is None:
return functools.partial(unicodify, encoding=encoding)
return _wrap_convert(str, fn, encoding=encoding)
def stringify(fn=None, encoding=None):
'''Convert all unicode arguments to str'''
if fn is None:
return functools.partial(stringify, encoding=encoding)
return _wrap_convert(unicode, fn, encoding=encoding)
__all__ = ['unicodify', 'stringify']
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment