Skip to content

Instantly share code, notes, and snippets.

@matthewstory
Created March 20, 2014 04:47
Show Gist options
  • Save matthewstory/9657448 to your computer and use it in GitHub Desktop.
Save matthewstory/9657448 to your computer and use it in GitHub Desktop.

Revisions

  1. matthewstory created this gist Mar 20, 2014.
    45 changes: 45 additions & 0 deletions unicodify.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,45 @@
    '''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']