Skip to content

Commit 58ffca3

Browse files
committed
-
1 parent f01c757 commit 58ffca3

File tree

3 files changed

+135
-2361
lines changed

3 files changed

+135
-2361
lines changed

source_py2/python_toolbox/third_party/decorator.py

Lines changed: 65 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -32,28 +32,15 @@
3232
for the documentation.
3333
"""
3434

35-
__version__ = '3.3.3'
35+
__version__ = '3.4.0'
3636

37-
__all__ = ["decorator", "FunctionMaker", "partial"]
37+
__all__ = ["decorator", "FunctionMaker", "contextmanager"]
3838

3939
import sys, re, inspect
40-
41-
try:
42-
from functools import partial
43-
except ImportError: # for Python version < 2.5
44-
class partial(object):
45-
"A simple replacement of functools.partial"
46-
def __init__(self, func, *args, **kw):
47-
self.func = func
48-
self.args = args
49-
self.keywords = kw
50-
def __call__(self, *otherargs, **otherkw):
51-
kw = self.keywords.copy()
52-
kw.update(otherkw)
53-
return self.func(*(self.args + otherargs), **kw)
54-
5540
if sys.version >= '3':
5641
from inspect import getfullargspec
42+
def get_init(cls):
43+
return cls.__init__
5744
else:
5845
class getfullargspec(object):
5946
"A quick and dirty replacement for getfullargspec for Python 2.X"
@@ -67,6 +54,8 @@ def __iter__(self):
6754
yield self.varargs
6855
yield self.varkw
6956
yield self.defaults
57+
def get_init(cls):
58+
return cls.__init__.im_func
7059

7160
DEF = re.compile('\s*def\s*([_\w][_\w\d]*)\s*\(')
7261

@@ -100,17 +89,21 @@ def __init__(self, func=None, name=None, signature=None,
10089
inspect.formatargspec(
10190
formatvalue=lambda val: "", *argspec)[1:-1]
10291
else: # Python 3 way
103-
self.signature = self.shortsignature = ', '.join(self.args)
92+
allargs = list(self.args)
93+
allshortargs = list(self.args)
10494
if self.varargs:
105-
self.signature += ', *' + self.varargs
106-
self.shortsignature += ', *' + self.varargs
107-
if self.kwonlyargs:
108-
for a in self.kwonlyargs:
109-
self.signature += ', %s=None' % a
110-
self.shortsignature += ', %s=%s' % (a, a)
95+
allargs.append('*' + self.varargs)
96+
allshortargs.append('*' + self.varargs)
97+
elif self.kwonlyargs:
98+
allargs.append('*') # single star syntax
99+
for a in self.kwonlyargs:
100+
allargs.append('%s=None' % a)
101+
allshortargs.append('%s=%s' % (a, a))
111102
if self.varkw:
112-
self.signature += ', **' + self.varkw
113-
self.shortsignature += ', **' + self.varkw
103+
allargs.append('**' + self.varkw)
104+
allshortargs.append('**' + self.varkw)
105+
self.signature = ', '.join(allargs)
106+
self.shortsignature = ', '.join(allshortargs)
114107
self.dict = func.__dict__.copy()
115108
# func=None happens when decorating a caller
116109
if name:
@@ -206,15 +199,53 @@ def decorator(caller, func=None):
206199
func, "return _call_(_func_, %(shortsignature)s)",
207200
evaldict, undecorated=func, __wrapped__=func)
208201
else: # returns a decorator
209-
if isinstance(caller, partial):
210-
return partial(decorator, caller)
211-
# otherwise assume caller is a function
212-
first = inspect.getargspec(caller)[0][0] # first arg
213-
evaldict = caller.func_globals.copy()
202+
if inspect.isclass(caller):
203+
name = caller.__name__.lower()
204+
callerfunc = get_init(caller)
205+
doc = 'decorator(%s) converts functions/generators into ' \
206+
'factories of %s objects' % (caller.__name__, caller.__name__)
207+
fun = getfullargspec(callerfunc).args[1] # second arg
208+
elif inspect.isfunction(caller):
209+
name = '_lambda_' if caller.__name__ == '<lambda>' \
210+
else caller.__name__
211+
callerfunc = caller
212+
doc = caller.__doc__
213+
fun = getfullargspec(callerfunc).args[0] # first arg
214+
else: # assume caller is an object with a __call__ method
215+
name = caller.__class__.__name__.lower()
216+
callerfunc = caller.__call__.im_func
217+
doc = caller.__call__.__doc__
218+
fun = getfullargspec(callerfunc).args[1] # second arg
219+
evaldict = callerfunc.func_globals.copy()
214220
evaldict['_call_'] = caller
215221
evaldict['decorator'] = decorator
216222
return FunctionMaker.create(
217-
'%s(%s)' % (caller.__name__, first),
218-
'return decorator(_call_, %s)' % first,
223+
'%s(%s)' % (name, fun),
224+
'return decorator(_call_, %s)' % fun,
219225
evaldict, undecorated=caller, __wrapped__=caller,
220-
doc=caller.__doc__, module=caller.__module__)
226+
doc=doc, module=caller.__module__)
227+
228+
######################### contextmanager ########################
229+
230+
def __call__(self, func):
231+
'Context manager decorator'
232+
return FunctionMaker.create(
233+
func, "with _self_: return _func_(%(shortsignature)s)",
234+
dict(_self_=self, _func_=func), __wrapped__=func)
235+
236+
try: # Python >= 3.2
237+
238+
from contextlib import _GeneratorContextManager
239+
ContextManager = type(
240+
'ContextManager', (_GeneratorContextManager,), dict(__call__=__call__))
241+
242+
except ImportError: # Python >= 2.5
243+
244+
from contextlib import GeneratorContextManager
245+
def __init__(self, f, *a, **k):
246+
return GeneratorContextManager.__init__(self, f(*a, **k))
247+
ContextManager = type(
248+
'ContextManager', (GeneratorContextManager,),
249+
dict(__call__=__call__, __init__=__init__))
250+
251+
contextmanager = decorator(ContextManager)

source_py3/python_toolbox/third_party/decorator.py

Lines changed: 70 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -32,28 +32,15 @@
3232
for the documentation.
3333
"""
3434

35-
__version__ = '3.3.3'
35+
__version__ = '3.4.0'
3636

37-
__all__ = ["decorator", "FunctionMaker", "partial"]
37+
__all__ = ["decorator", "FunctionMaker", "contextmanager"]
3838

3939
import sys, re, inspect
40-
41-
try:
42-
from functools import partial
43-
except ImportError: # for Python version < 2.5
44-
class partial(object):
45-
"A simple replacement of functools.partial"
46-
def __init__(self, func, *args, **kw):
47-
self.func = func
48-
self.args = args
49-
self.keywords = kw
50-
def __call__(self, *otherargs, **otherkw):
51-
kw = self.keywords.copy()
52-
kw.update(otherkw)
53-
return self.func(*(self.args + otherargs), **kw)
54-
5540
if sys.version >= '3':
5641
from inspect import getfullargspec
42+
def get_init(cls):
43+
return cls.__init__
5744
else:
5845
class getfullargspec(object):
5946
"A quick and dirty replacement for getfullargspec for Python 2.X"
@@ -67,6 +54,8 @@ def __iter__(self):
6754
yield self.varargs
6855
yield self.varkw
6956
yield self.defaults
57+
def get_init(cls):
58+
return cls.__init__.__func__
7059

7160
DEF = re.compile('\s*def\s*([_\w][_\w\d]*)\s*\(')
7261

@@ -100,17 +89,21 @@ def __init__(self, func=None, name=None, signature=None,
10089
inspect.formatargspec(
10190
formatvalue=lambda val: "", *argspec)[1:-1]
10291
else: # Python 3 way
103-
self.signature = self.shortsignature = ', '.join(self.args)
92+
allargs = list(self.args)
93+
allshortargs = list(self.args)
10494
if self.varargs:
105-
self.signature += ', *' + self.varargs
106-
self.shortsignature += ', *' + self.varargs
107-
if self.kwonlyargs:
108-
for a in self.kwonlyargs:
109-
self.signature += ', %s=None' % a
110-
self.shortsignature += ', %s=%s' % (a, a)
95+
allargs.append('*' + self.varargs)
96+
allshortargs.append('*' + self.varargs)
97+
elif self.kwonlyargs:
98+
allargs.append('*') # single star syntax
99+
for a in self.kwonlyargs:
100+
allargs.append('%s=None' % a)
101+
allshortargs.append('%s=%s' % (a, a))
111102
if self.varkw:
112-
self.signature += ', **' + self.varkw
113-
self.shortsignature += ', **' + self.varkw
103+
allargs.append('**' + self.varkw)
104+
allshortargs.append('**' + self.varkw)
105+
self.signature = ', '.join(allargs)
106+
self.shortsignature = ', '.join(allshortargs)
114107
self.dict = func.__dict__.copy()
115108
# func=None happens when decorating a caller
116109
if name:
@@ -135,7 +128,7 @@ def update(self, func, **kw):
135128
func.__name__ = self.name
136129
func.__doc__ = getattr(self, 'doc', None)
137130
func.__dict__ = getattr(self, 'dict', {})
138-
func.func_defaults = getattr(self, 'defaults', ())
131+
func.__defaults__ = getattr(self, 'defaults', ())
139132
func.__kwdefaults__ = getattr(self, 'kwonlydefaults', None)
140133
func.__annotations__ = getattr(self, 'annotations', None)
141134
callermodule = sys._getframe(3).f_globals.get('__name__', '?')
@@ -160,10 +153,10 @@ def make(self, src_templ, evaldict=None, addsource=False, **attrs):
160153
try:
161154
code = compile(src, '<string>', 'single')
162155
# print >> sys.stderr, 'Compiling %s' % src
163-
exec code in evaldict
156+
exec(code, evaldict)
164157
except:
165-
print >> sys.stderr, 'Error in generated code:'
166-
print >> sys.stderr, src
158+
print('Error in generated code:', file=sys.stderr)
159+
print(src, file=sys.stderr)
167160
raise
168161
func = evaldict[name]
169162
if addsource:
@@ -199,22 +192,60 @@ def decorator(caller, func=None):
199192
decorator(caller, func) decorates a function using a caller.
200193
"""
201194
if func is not None: # returns a decorated function
202-
evaldict = func.func_globals.copy()
195+
evaldict = func.__globals__.copy()
203196
evaldict['_call_'] = caller
204197
evaldict['_func_'] = func
205198
return FunctionMaker.create(
206199
func, "return _call_(_func_, %(shortsignature)s)",
207200
evaldict, undecorated=func, __wrapped__=func)
208201
else: # returns a decorator
209-
if isinstance(caller, partial):
210-
return partial(decorator, caller)
211-
# otherwise assume caller is a function
212-
first = inspect.getargspec(caller)[0][0] # first arg
213-
evaldict = caller.func_globals.copy()
202+
if inspect.isclass(caller):
203+
name = caller.__name__.lower()
204+
callerfunc = get_init(caller)
205+
doc = 'decorator(%s) converts functions/generators into ' \
206+
'factories of %s objects' % (caller.__name__, caller.__name__)
207+
fun = getfullargspec(callerfunc).args[1] # second arg
208+
elif inspect.isfunction(caller):
209+
name = '_lambda_' if caller.__name__ == '<lambda>' \
210+
else caller.__name__
211+
callerfunc = caller
212+
doc = caller.__doc__
213+
fun = getfullargspec(callerfunc).args[0] # first arg
214+
else: # assume caller is an object with a __call__ method
215+
name = caller.__class__.__name__.lower()
216+
callerfunc = caller.__call__.__func__
217+
doc = caller.__call__.__doc__
218+
fun = getfullargspec(callerfunc).args[1] # second arg
219+
evaldict = callerfunc.__globals__.copy()
214220
evaldict['_call_'] = caller
215221
evaldict['decorator'] = decorator
216222
return FunctionMaker.create(
217-
'%s(%s)' % (caller.__name__, first),
218-
'return decorator(_call_, %s)' % first,
223+
'%s(%s)' % (name, fun),
224+
'return decorator(_call_, %s)' % fun,
219225
evaldict, undecorated=caller, __wrapped__=caller,
220-
doc=caller.__doc__, module=caller.__module__)
226+
doc=doc, module=caller.__module__)
227+
228+
######################### contextmanager ########################
229+
230+
def __call__(self, func):
231+
'Context manager decorator'
232+
return FunctionMaker.create(
233+
func, "with _self_: return _func_(%(shortsignature)s)",
234+
dict(_self_=self, _func_=func), __wrapped__=func)
235+
236+
try: # Python >= 3.2
237+
238+
from contextlib import _GeneratorContextManager
239+
ContextManager = type(
240+
'ContextManager', (_GeneratorContextManager,), dict(__call__=__call__))
241+
242+
except ImportError: # Python >= 2.5
243+
244+
from contextlib import GeneratorContextManager
245+
def __init__(self, f, *a, **k):
246+
return GeneratorContextManager.__init__(self, f(*a, **k))
247+
ContextManager = type(
248+
'ContextManager', (GeneratorContextManager,),
249+
dict(__call__=__call__, __init__=__init__))
250+
251+
contextmanager = decorator(ContextManager)

0 commit comments

Comments
 (0)