Clone of https://github.com/NixOS/nixpkgs.git (to stress-test knotserver)
at release-16.03 487 lines 20 kB view raw
1From 8d3cd578f9c0a36d29411c96fa70402a7a56d502 Mon Sep 17 00:00:00 2001 2From: Evgeni Burovski <evgeni@burovski.me> 3Date: Sun, 8 Nov 2015 15:27:22 +0000 4Subject: [PATCH] MAINT: update decorators.py module to version 4.0.5 5 6This is commit d6abda0 at 7https://github.com/micheles/decorator/tree/4.0.5 8--- 9 scipy/_lib/decorator.py | 380 +++++++++++++++++++++++++++++++++++++----------- 10 1 file changed, 293 insertions(+), 87 deletions(-) 11 12diff --git a/scipy/_lib/decorator.py b/scipy/_lib/decorator.py 13index 07d9d21..05f7056 100644 14--- a/scipy/_lib/decorator.py 15+++ b/scipy/_lib/decorator.py 16@@ -1,48 +1,52 @@ 17-########################## LICENCE ############################### 18-## 19-## Copyright (c) 2005-2011, Michele Simionato 20-## All rights reserved. 21-## 22-## Redistributions of source code must retain the above copyright 23-## notice, this list of conditions and the following disclaimer. 24-## Redistributions in bytecode form must reproduce the above copyright 25-## notice, this list of conditions and the following disclaimer in 26-## the documentation and/or other materials provided with the 27-## distribution. 28- 29-## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 30-## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 31-## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 32-## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 33-## HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 34-## INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 35-## BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 36-## OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 37-## ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 38-## TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 39-## USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 40-## DAMAGE. 41+# ######################### LICENSE ############################ # 42+ 43+# Copyright (c) 2005-2015, Michele Simionato 44+# All rights reserved. 45+ 46+# Redistribution and use in source and binary forms, with or without 47+# modification, are permitted provided that the following conditions are 48+# met: 49+ 50+# Redistributions of source code must retain the above copyright 51+# notice, this list of conditions and the following disclaimer. 52+# Redistributions in bytecode form must reproduce the above copyright 53+# notice, this list of conditions and the following disclaimer in 54+# the documentation and/or other materials provided with the 55+# distribution. 56+ 57+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 58+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 59+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 60+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 61+# HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 62+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 63+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 64+# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 65+# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 66+# TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 67+# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 68+# DAMAGE. 69 70 """ 71 Decorator module, see http://pypi.python.org/pypi/decorator 72 for the documentation. 73 """ 74+from __future__ import print_function 75 76-from __future__ import division, print_function, absolute_import 77- 78-__version__ = '3.3.2' 79- 80-__all__ = ["decorator", "FunctionMaker"] 81- 82-import sys 83 import re 84+import sys 85 import inspect 86-from functools import partial 87+import operator 88+import itertools 89+import collections 90 91-from scipy._lib.six import exec_ 92+__version__ = '4.0.5' 93 94 if sys.version >= '3': 95 from inspect import getfullargspec 96+ 97+ def get_init(cls): 98+ return cls.__init__ 99 else: 100 class getfullargspec(object): 101 "A quick and dirty replacement for getfullargspec for Python 2.X" 102@@ -51,7 +55,6 @@ else: 103 inspect.getargspec(f) 104 self.kwonlyargs = [] 105 self.kwonlydefaults = None 106- self.annotations = getattr(f, '__annotations__', {}) 107 108 def __iter__(self): 109 yield self.args 110@@ -59,17 +62,35 @@ else: 111 yield self.varkw 112 yield self.defaults 113 114-DEF = re.compile('\s*def\s*([_\w][_\w\d]*)\s*\(') 115+ getargspec = inspect.getargspec 116+ 117+ def get_init(cls): 118+ return cls.__init__.__func__ 119+ 120+# getargspec has been deprecated in Python 3.5 121+ArgSpec = collections.namedtuple( 122+ 'ArgSpec', 'args varargs varkw defaults') 123 124-# basic functionality 125 126+def getargspec(f): 127+ """A replacement for inspect.getargspec""" 128+ spec = getfullargspec(f) 129+ return ArgSpec(spec.args, spec.varargs, spec.varkw, spec.defaults) 130 131+DEF = re.compile('\s*def\s*([_\w][_\w\d]*)\s*\(') 132+ 133+ 134+# basic functionality 135 class FunctionMaker(object): 136 """ 137 An object with the ability to create functions with a given signature. 138 It has attributes name, doc, module, signature, defaults, dict and 139 methods update and make. 140 """ 141+ 142+ # Atomic get-and-increment provided by the GIL 143+ _compile_count = itertools.count() 144+ 145 def __init__(self, func=None, name=None, signature=None, 146 defaults=None, doc=None, module=None, funcdict=None): 147 self.shortsignature = signature 148@@ -82,22 +103,32 @@ class FunctionMaker(object): 149 self.module = func.__module__ 150 if inspect.isfunction(func): 151 argspec = getfullargspec(func) 152+ self.annotations = getattr(func, '__annotations__', {}) 153 for a in ('args', 'varargs', 'varkw', 'defaults', 'kwonlyargs', 154- 'kwonlydefaults', 'annotations'): 155+ 'kwonlydefaults'): 156 setattr(self, a, getattr(argspec, a)) 157 for i, arg in enumerate(self.args): 158 setattr(self, 'arg%d' % i, arg) 159- self.signature = inspect.formatargspec( 160- formatvalue=lambda val: "", *argspec)[1:-1] 161- allargs = list(self.args) 162- if self.varargs: 163- allargs.append('*' + self.varargs) 164- if self.varkw: 165- allargs.append('**' + self.varkw) 166- try: 167- self.shortsignature = ', '.join(allargs) 168- except TypeError: # exotic signature, valid only in Python 2.X 169- self.shortsignature = self.signature 170+ if sys.version < '3': # easy way 171+ self.shortsignature = self.signature = ( 172+ inspect.formatargspec( 173+ formatvalue=lambda val: "", *argspec)[1:-1]) 174+ else: # Python 3 way 175+ allargs = list(self.args) 176+ allshortargs = list(self.args) 177+ if self.varargs: 178+ allargs.append('*' + self.varargs) 179+ allshortargs.append('*' + self.varargs) 180+ elif self.kwonlyargs: 181+ allargs.append('*') # single star syntax 182+ for a in self.kwonlyargs: 183+ allargs.append('%s=None' % a) 184+ allshortargs.append('%s=%s' % (a, a)) 185+ if self.varkw: 186+ allargs.append('**' + self.varkw) 187+ allshortargs.append('**' + self.varkw) 188+ self.signature = ', '.join(allargs) 189+ self.shortsignature = ', '.join(allshortargs) 190 self.dict = func.__dict__.copy() 191 # func=None happens when decorating a caller 192 if name: 193@@ -122,12 +153,15 @@ class FunctionMaker(object): 194 func.__name__ = self.name 195 func.__doc__ = getattr(self, 'doc', None) 196 func.__dict__ = getattr(self, 'dict', {}) 197- if sys.version_info[0] >= 3: 198- func.__defaults__ = getattr(self, 'defaults', ()) 199- else: 200- func.func_defaults = getattr(self, 'defaults', ()) 201+ func.__defaults__ = getattr(self, 'defaults', ()) 202 func.__kwdefaults__ = getattr(self, 'kwonlydefaults', None) 203- callermodule = sys._getframe(3).f_globals.get('__name__', '?') 204+ func.__annotations__ = getattr(self, 'annotations', None) 205+ try: 206+ frame = sys._getframe(3) 207+ except AttributeError: # for IronPython and similar implementations 208+ callermodule = '?' 209+ else: 210+ callermodule = frame.f_globals.get('__name__', '?') 211 func.__module__ = getattr(self, 'module', callermodule) 212 func.__dict__.update(kw) 213 214@@ -140,16 +174,20 @@ class FunctionMaker(object): 215 raise SyntaxError('not a valid function template\n%s' % src) 216 name = mo.group(1) # extract the function name 217 names = set([name] + [arg.strip(' *') for arg in 218- self.shortsignature.split(',')]) 219+ self.shortsignature.split(',')]) 220 for n in names: 221 if n in ('_func_', '_call_'): 222 raise NameError('%s is overridden in\n%s' % (n, src)) 223 if not src.endswith('\n'): # add a newline just for safety 224 src += '\n' # this is needed in old versions of Python 225+ 226+ # Ensure each generated function has a unique filename for profilers 227+ # (such as cProfile) that depend on the tuple of (<filename>, 228+ # <definition line>, <function name>) being unique. 229+ filename = '<decorator-gen-%d>' % (next(self._compile_count),) 230 try: 231- code = compile(src, '<string>', 'single') 232- # print >> sys.stderr, 'Compiling %s' % src 233- exec_(code, evaldict) 234+ code = compile(src, filename, 'single') 235+ exec(code, evaldict) 236 except: 237 print('Error in generated code:', file=sys.stderr) 238 print(src, file=sys.stderr) 239@@ -165,9 +203,9 @@ class FunctionMaker(object): 240 doc=None, module=None, addsource=True, **attrs): 241 """ 242 Create a function from the strings name, signature and body. 243- evaldict is the evaluation dictionary. If addsource is true an attribute 244- __source__ is added to the result. The attributes attrs are added, 245- if any. 246+ evaldict is the evaluation dictionary. If addsource is true an 247+ attribute __source__ is added to the result. The attributes attrs 248+ are added, if any. 249 """ 250 if isinstance(obj, str): # "name(signature)" 251 name, rest = obj.strip().split('(', 1) 252@@ -180,37 +218,205 @@ class FunctionMaker(object): 253 self = cls(func, name, signature, defaults, doc, module) 254 ibody = '\n'.join(' ' + line for line in body.splitlines()) 255 return self.make('def %(name)s(%(signature)s):\n' + ibody, 256- evaldict, addsource, **attrs) 257+ evaldict, addsource, **attrs) 258 259 260-def decorator(caller, func=None): 261+def decorate(func, caller): 262 """ 263- decorator(caller) converts a caller function into a decorator; 264- decorator(caller, func) decorates a function using a caller. 265+ decorate(func, caller) decorates a function using a caller. 266 """ 267- if func is not None: # returns a decorated function 268- if sys.version_info[0] >= 3: 269- evaldict = func.__globals__.copy() 270+ evaldict = func.__globals__.copy() 271+ evaldict['_call_'] = caller 272+ evaldict['_func_'] = func 273+ fun = FunctionMaker.create( 274+ func, "return _call_(_func_, %(shortsignature)s)", 275+ evaldict, __wrapped__=func) 276+ if hasattr(func, '__qualname__'): 277+ fun.__qualname__ = func.__qualname__ 278+ return fun 279+ 280+ 281+def decorator(caller, _func=None): 282+ """decorator(caller) converts a caller function into a decorator""" 283+ if _func is not None: # return a decorated function 284+ # this is obsolete behavior; you should use decorate instead 285+ return decorate(_func, caller) 286+ # else return a decorator function 287+ if inspect.isclass(caller): 288+ name = caller.__name__.lower() 289+ callerfunc = get_init(caller) 290+ doc = 'decorator(%s) converts functions/generators into ' \ 291+ 'factories of %s objects' % (caller.__name__, caller.__name__) 292+ elif inspect.isfunction(caller): 293+ if caller.__name__ == '<lambda>': 294+ name = '_lambda_' 295 else: 296- evaldict = func.func_globals.copy() 297- evaldict['_call_'] = caller 298- evaldict['_func_'] = func 299+ name = caller.__name__ 300+ callerfunc = caller 301+ doc = caller.__doc__ 302+ else: # assume caller is an object with a __call__ method 303+ name = caller.__class__.__name__.lower() 304+ callerfunc = caller.__call__.__func__ 305+ doc = caller.__call__.__doc__ 306+ evaldict = callerfunc.__globals__.copy() 307+ evaldict['_call_'] = caller 308+ evaldict['_decorate_'] = decorate 309+ return FunctionMaker.create( 310+ '%s(func)' % name, 'return _decorate_(func, _call_)', 311+ evaldict, doc=doc, module=caller.__module__, 312+ __wrapped__=caller) 313+ 314+ 315+# ####################### contextmanager ####################### # 316+ 317+try: # Python >= 3.2 318+ from contextlib import _GeneratorContextManager 319+except ImportError: # Python >= 2.5 320+ from contextlib import GeneratorContextManager as _GeneratorContextManager 321+ 322+ 323+class ContextManager(_GeneratorContextManager): 324+ def __call__(self, func): 325+ """Context manager decorator""" 326 return FunctionMaker.create( 327- func, "return _call_(_func_, %(shortsignature)s)", 328- evaldict, undecorated=func, __wrapped__=func) 329- else: # returns a decorator 330- if isinstance(caller, partial): 331- return partial(decorator, caller) 332- # otherwise assume caller is a function 333- first = inspect.getargspec(caller)[0][0] # first arg 334- if sys.version_info[0] >= 3: 335- evaldict = caller.__globals__.copy() 336- else: 337- evaldict = caller.func_globals.copy() 338- evaldict['_call_'] = caller 339- evaldict['decorator'] = decorator 340+ func, "with _self_: return _func_(%(shortsignature)s)", 341+ dict(_self_=self, _func_=func), __wrapped__=func) 342+ 343+init = getfullargspec(_GeneratorContextManager.__init__) 344+n_args = len(init.args) 345+if n_args == 2 and not init.varargs: # (self, genobj) Python 2.7 346+ def __init__(self, g, *a, **k): 347+ return _GeneratorContextManager.__init__(self, g(*a, **k)) 348+ ContextManager.__init__ = __init__ 349+elif n_args == 2 and init.varargs: # (self, gen, *a, **k) Python 3.4 350+ pass 351+elif n_args == 4: # (self, gen, args, kwds) Python 3.5 352+ def __init__(self, g, *a, **k): 353+ return _GeneratorContextManager.__init__(self, g, a, k) 354+ ContextManager.__init__ = __init__ 355+ 356+contextmanager = decorator(ContextManager) 357+ 358+ 359+# ############################ dispatch_on ############################ # 360+ 361+def append(a, vancestors): 362+ """ 363+ Append ``a`` to the list of the virtual ancestors, unless it is already 364+ included. 365+ """ 366+ add = True 367+ for j, va in enumerate(vancestors): 368+ if issubclass(va, a): 369+ add = False 370+ break 371+ if issubclass(a, va): 372+ vancestors[j] = a 373+ add = False 374+ if add: 375+ vancestors.append(a) 376+ 377+ 378+# inspired from simplegeneric by P.J. Eby and functools.singledispatch 379+def dispatch_on(*dispatch_args): 380+ """ 381+ Factory of decorators turning a function into a generic function 382+ dispatching on the given arguments. 383+ """ 384+ assert dispatch_args, 'No dispatch args passed' 385+ dispatch_str = '(%s,)' % ', '.join(dispatch_args) 386+ 387+ def check(arguments, wrong=operator.ne, msg=''): 388+ """Make sure one passes the expected number of arguments""" 389+ if wrong(len(arguments), len(dispatch_args)): 390+ raise TypeError('Expected %d arguments, got %d%s' % 391+ (len(dispatch_args), len(arguments), msg)) 392+ 393+ def gen_func_dec(func): 394+ """Decorator turning a function into a generic function""" 395+ 396+ # first check the dispatch arguments 397+ argset = set(getfullargspec(func).args) 398+ if not set(dispatch_args) <= argset: 399+ raise NameError('Unknown dispatch arguments %s' % dispatch_str) 400+ 401+ typemap = {} 402+ 403+ def vancestors(*types): 404+ """ 405+ Get a list of sets of virtual ancestors for the given types 406+ """ 407+ check(types) 408+ ras = [[] for _ in range(len(dispatch_args))] 409+ for types_ in typemap: 410+ for t, type_, ra in zip(types, types_, ras): 411+ if issubclass(t, type_) and type_ not in t.__mro__: 412+ append(type_, ra) 413+ return [set(ra) for ra in ras] 414+ 415+ def ancestors(*types): 416+ """ 417+ Get a list of virtual MROs, one for each type 418+ """ 419+ check(types) 420+ lists = [] 421+ for t, vas in zip(types, vancestors(*types)): 422+ n_vas = len(vas) 423+ if n_vas > 1: 424+ raise RuntimeError( 425+ 'Ambiguous dispatch for %s: %s' % (t, vas)) 426+ elif n_vas == 1: 427+ va, = vas 428+ mro = type('t', (t, va), {}).__mro__[1:] 429+ else: 430+ mro = t.__mro__ 431+ lists.append(mro[:-1]) # discard t and object 432+ return lists 433+ 434+ def register(*types): 435+ """ 436+ Decorator to register an implementation for the given types 437+ """ 438+ check(types) 439+ def dec(f): 440+ check(getfullargspec(f).args, operator.lt, ' in ' + f.__name__) 441+ typemap[types] = f 442+ return f 443+ return dec 444+ 445+ def dispatch_info(*types): 446+ """ 447+ An utility to introspect the dispatch algorithm 448+ """ 449+ check(types) 450+ lst = [] 451+ for anc in itertools.product(*ancestors(*types)): 452+ lst.append(tuple(a.__name__ for a in anc)) 453+ return lst 454+ 455+ def _dispatch(dispatch_args, *args, **kw): 456+ types = tuple(type(arg) for arg in dispatch_args) 457+ try: # fast path 458+ f = typemap[types] 459+ except KeyError: 460+ pass 461+ else: 462+ return f(*args, **kw) 463+ combinations = itertools.product(*ancestors(*types)) 464+ next(combinations) # the first one has been already tried 465+ for types_ in combinations: 466+ f = typemap.get(types_) 467+ if f is not None: 468+ return f(*args, **kw) 469+ 470+ # else call the default implementation 471+ return func(*args, **kw) 472+ 473 return FunctionMaker.create( 474- '%s(%s)' % (caller.__name__, first), 475- 'return decorator(_call_, %s)' % first, 476- evaldict, undecorated=caller, __wrapped__=caller, 477- doc=caller.__doc__, module=caller.__module__) 478+ func, 'return _f_(%s, %%(shortsignature)s)' % dispatch_str, 479+ dict(_f_=_dispatch), register=register, default=func, 480+ typemap=typemap, vancestors=vancestors, ancestors=ancestors, 481+ dispatch_info=dispatch_info, __wrapped__=func) 482+ 483+ gen_func_dec.__name__ = 'dispatch_on' + dispatch_str 484+ return gen_func_dec 485-- 4862.6.3 487