Mercurial > repos > guerler > springsuite
comparison planemo/lib/python3.7/site-packages/future/builtins/newsuper.py @ 0:d30785e31577 draft
"planemo upload commit 6eee67778febed82ddd413c3ca40b3183a3898f1"
author | guerler |
---|---|
date | Fri, 31 Jul 2020 00:18:57 -0400 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:d30785e31577 |
---|---|
1 ''' | |
2 This module provides a newsuper() function in Python 2 that mimics the | |
3 behaviour of super() in Python 3. It is designed to be used as follows: | |
4 | |
5 from __future__ import division, absolute_import, print_function | |
6 from future.builtins import super | |
7 | |
8 And then, for example: | |
9 | |
10 class VerboseList(list): | |
11 def append(self, item): | |
12 print('Adding an item') | |
13 super().append(item) # new simpler super() function | |
14 | |
15 Importing this module on Python 3 has no effect. | |
16 | |
17 This is based on (i.e. almost identical to) Ryan Kelly's magicsuper | |
18 module here: | |
19 | |
20 https://github.com/rfk/magicsuper.git | |
21 | |
22 Excerpts from Ryan's docstring: | |
23 | |
24 "Of course, you can still explicitly pass in the arguments if you want | |
25 to do something strange. Sometimes you really do want that, e.g. to | |
26 skip over some classes in the method resolution order. | |
27 | |
28 "How does it work? By inspecting the calling frame to determine the | |
29 function object being executed and the object on which it's being | |
30 called, and then walking the object's __mro__ chain to find out where | |
31 that function was defined. Yuck, but it seems to work..." | |
32 ''' | |
33 | |
34 from __future__ import absolute_import | |
35 import sys | |
36 from types import FunctionType | |
37 | |
38 from future.utils import PY3, PY26 | |
39 | |
40 | |
41 _builtin_super = super | |
42 | |
43 _SENTINEL = object() | |
44 | |
45 def newsuper(typ=_SENTINEL, type_or_obj=_SENTINEL, framedepth=1): | |
46 '''Like builtin super(), but capable of magic. | |
47 | |
48 This acts just like the builtin super() function, but if called | |
49 without any arguments it attempts to infer them at runtime. | |
50 ''' | |
51 # Infer the correct call if used without arguments. | |
52 if typ is _SENTINEL: | |
53 # We'll need to do some frame hacking. | |
54 f = sys._getframe(framedepth) | |
55 | |
56 try: | |
57 # Get the function's first positional argument. | |
58 type_or_obj = f.f_locals[f.f_code.co_varnames[0]] | |
59 except (IndexError, KeyError,): | |
60 raise RuntimeError('super() used in a function with no args') | |
61 | |
62 try: | |
63 # Get the MRO so we can crawl it. | |
64 mro = type_or_obj.__mro__ | |
65 except (AttributeError, RuntimeError): # see issue #160 | |
66 try: | |
67 mro = type_or_obj.__class__.__mro__ | |
68 except AttributeError: | |
69 raise RuntimeError('super() used with a non-newstyle class') | |
70 | |
71 # A ``for...else`` block? Yes! It's odd, but useful. | |
72 # If unfamiliar with for...else, see: | |
73 # | |
74 # http://psung.blogspot.com/2007/12/for-else-in-python.html | |
75 for typ in mro: | |
76 # Find the class that owns the currently-executing method. | |
77 for meth in typ.__dict__.values(): | |
78 # Drill down through any wrappers to the underlying func. | |
79 # This handles e.g. classmethod() and staticmethod(). | |
80 try: | |
81 while not isinstance(meth,FunctionType): | |
82 if isinstance(meth, property): | |
83 # Calling __get__ on the property will invoke | |
84 # user code which might throw exceptions or have | |
85 # side effects | |
86 meth = meth.fget | |
87 else: | |
88 try: | |
89 meth = meth.__func__ | |
90 except AttributeError: | |
91 meth = meth.__get__(type_or_obj, typ) | |
92 except (AttributeError, TypeError): | |
93 continue | |
94 if meth.func_code is f.f_code: | |
95 break # Aha! Found you. | |
96 else: | |
97 continue # Not found! Move onto the next class in MRO. | |
98 break # Found! Break out of the search loop. | |
99 else: | |
100 raise RuntimeError('super() called outside a method') | |
101 | |
102 # Dispatch to builtin super(). | |
103 if type_or_obj is not _SENTINEL: | |
104 return _builtin_super(typ, type_or_obj) | |
105 return _builtin_super(typ) | |
106 | |
107 | |
108 def superm(*args, **kwds): | |
109 f = sys._getframe(1) | |
110 nm = f.f_code.co_name | |
111 return getattr(newsuper(framedepth=2),nm)(*args, **kwds) | |
112 | |
113 | |
114 __all__ = ['newsuper'] |