1+ #!/usr/bin/env python
2+
3+ '''
4+ Decorators to convert all arguments passed to a function or method to
5+ unicode or str, including default arguments
6+
7+ From: http://axialcorps.com/2014/03/20/unicode-str/
8+
9+ '''
10+
11+
12+ import sys
13+ import functools
14+ import inspect
15+
16+ def _convert_arg (arg , from_ , conv , enc ):
17+ '''Safely convert unicode to string or string to unicode'''
18+ return getattr (arg , conv )(encoding = enc ) if isinstance (arg , from_ ) else arg
19+
20+ def _wrap_convert (from_type , fn , encoding = None ):
21+ '''Decorate a function converting all str arguments to unicode or
22+ vice-versa'''
23+ conv = 'decode' if from_type is str else 'encode'
24+ encoding = encoding or sys .getdefaultencoding ()
25+
26+ # override string defaults using partial
27+ aspec , dflts = inspect .getargspec (fn ), {}
28+ if aspec .defaults :
29+ for k ,v in zip (aspec .args [- len (aspec .defaults ):],aspec .defaults ):
30+ dflts [k ] = _convert_arg (v , from_type , conv , encoding )
31+ fn = functools .partial (fn , ** dflts )
32+
33+ @functools .wraps (fn .func if isinstance (fn , functools .partial ) else fn )
34+ def converted (* args , ** kwargs ):
35+ args = [_convert_arg (a , from_type , conv , encoding ) for a in args ]
36+ for k ,v in kwargs .iteritems ():
37+ kwargs [k ] = _convert_arg (v , from_type , conv , encoding )
38+ return fn (* args , ** kwargs )
39+
40+ return converted
41+
42+ def unicodify (fn = None , encoding = None ):
43+ '''Convert all str arguments to unicode'''
44+ if fn is None :
45+ return functools .partial (unicodify , encoding = encoding )
46+ return _wrap_convert (str , fn , encoding = encoding )
47+
48+ def stringify (fn = None , encoding = None ):
49+ '''Convert all unicode arguments to str'''
50+ if fn is None :
51+ return functools .partial (stringify , encoding = encoding )
52+ return _wrap_convert (unicode , fn , encoding = encoding )
53+
54+ __all__ = ['unicodify' , 'stringify' ]
0 commit comments