classification
Title: No-argument super in method with variable arguments raises SystemError
Type: behavior Stage:
Components: Interpreter Core Versions: Python 3.8
process
Status: open Resolution:
Dependencies: Superseder:
Assigned To: Nosy List: Arfrever, Cristóbal Ganter, amaury.forgeotdarc, asvetlov, benjamin.peterson, eric.araujo, ezio.melotti, james.sanders, josh.r, martin.panter, r.david.murray, remi.lapeyre
Priority: low Keywords: patch

Created on 2012-08-21 11:52 by james.sanders, last changed 2019-02-14 10:09 by BreamoreBoy.

Files
File name Uploaded Description Edit
issue15753_varargsuper.patch james.sanders, 2012-08-23 19:13 review
Messages (12)
msg168757 - (view) Author: James (james.sanders) Date: 2012-08-21 11:52
For example:

Python 3.2.2 (default, Feb 10 2012, 09:23:17) 
[GCC 4.4.5 20110214 (Red Hat 4.4.5-6)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> class A:
...     def f(*args):
...             print(super().__repr__())
... 
>>> A().f()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in f
SystemError: super(): no arguments

(There is no change in the current development version 3.3.0b2+)

I guess that the problem here is related to the fact that the super call makes sense if we call A().f() but not if we call A.f() (which is allowed by the method signature)?  I understand that not including self in the signature is almost always bad style, but occasionally it is necessary, for example if you want to allow arbitrary keyword arguments as dict.update does.

Also, how come using the no-argument form of super outside a method raises SystemError - isn't that supposed to be for internal errors?
msg168959 - (view) Author: James (james.sanders) Date: 2012-08-23 19:13
I've attached a patch that I think fixes the variable arguments problem, and changes the SystemErrors that can be obtained by misusing super() into RuntimeErrors (I assume that's more appropriate?).  There are three more SystemErrors I'm not sure about: "super(): no code object", "super(): bad __class__ cell", and "super(): empty __class__ cell" - can they only be caused by internal bugs?
msg168989 - (view) Author: James (james.sanders) Date: 2012-08-24 09:01
It turns out I don't really understand how frame objects work.  My patch can crash python if you do this:

>>> class A:
...     def f(*args):
...             args = 1
...             print(super())
... 
>>> A().f()
python: Objects/typeobject.c:6516: super_init: Assertion `((((((PyObject*)(obj))->ob_type))->tp_flags & ((1L<<26))) != 0)' failed.
Aborted

Is there a way of checking if the first argument has been overwritten, or do you just have to assume that if it is still a tuple, it hasn't been?  Should the super documentation mention that assigning to self (or args in this case) can make the no-argument version work incorrectly?
msg168995 - (view) Author: Amaury Forgeot d'Arc (amaury.forgeotdarc) * (Python committer) Date: 2012-08-24 10:28
The failing assertion is the "assert(PyTuple_Check(obj))" added by your patch.
At this point, "obj" is not the arguments tuple, but the first entry in "f->f_localsplus". Maybe this block should be moved a bit earlier?
msg168997 - (view) Author: James (james.sanders) Date: 2012-08-24 11:19
Sorry, I wasn't very clear.  super() currently works by assuming that self is the first entry in f_localsplus, which is defeated, for example, by doing:

>>> class A:
...     def f(self):
...             del self
...             super()
... 
>>> A().f()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 4, in f
SystemError: super(): arg[0] deleted
>>> class B:
...     def f(self):
...             self = 1
...             super()
... 
>>> B().f()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 4, in f
TypeError: super(type, obj): obj must be an instance or subtype of type

I don't know if this is the intended behaviour (in which case, my assertion that obj is a tuple should be replaced by just checking whether it is a tuple and raising an exception otherwise; and I suppose the super documentation should mention this caveat), or whether this should be fixed somehow.
msg169002 - (view) Author: Andrew Svetlov (asvetlov) * (Python committer) Date: 2012-08-24 12:02
Changing exception type is not backward compatible and should be documented at least if that change is really required.
Personally I slightly prefer to leave SystemError untouched
msg169720 - (view) Author: Andrew Svetlov (asvetlov) * (Python committer) Date: 2012-09-02 20:07
BTW see #15839: super now raises RuntimeError.
After that I revoke my objection for exception type changing.
msg236499 - (view) Author: Mark Lawrence (BreamoreBoy) * Date: 2015-02-24 14:25
RuntimeError is now given instead of SystemError.

Python 3.4.2 (v3.4.2:ab2c023a9432, Oct  6 2014, 22:16:31) [MSC v.1600 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> class A:
...     def f(*args):
...         print(super().__repr__())
...
>>> A().f()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in f
RuntimeError: super(): no arguments

so presumably this can be closed as "out of date"?
msg236554 - (view) Author: Josh Rosenberg (josh.r) * (Python triager) Date: 2015-02-24 23:37
Wasn't the objection that super shouldn't screw up, not the specific type of the exception?
msg245571 - (view) Author: Cristóbal Ganter (Cristóbal Ganter) Date: 2015-06-20 19:42
I have the same question as Josh Rosenberg.
Also, do you know any workarounds for this problem?
msg245578 - (view) Author: Martin Panter (martin.panter) * (Python committer) Date: 2015-06-21 00:15
The obvious workaround is to include an explicit “self” parameter (name shouldn’t matter):

def f(arbitrary, *positional, **most_keywords):
    all_positional = (arbitrary,) + positional
    ...

If you need to reserve all keyword parameter names, you could try the manual version of super():

class A:
    def f(*all_positional, **all_keywords):
        print(super(A, all_positional[0]).__repr__())
msg335472 - (view) Author: Josh Rosenberg (josh.r) * (Python triager) Date: 2019-02-13 18:33
Moving from pending back to open (not sure what was "pending" about it?).

The workaround is viable (and used by Python implemented dict subclasses in the standard library since they must accept **kwargs with arbitrary strings, including self), but it does seem a little silly that it's required. Leaving it as low priority since the workaround exists.

Still, would be nice to make super() seamless, pulling the first argument if the function accepts it as non-varargs, and the first element of the first argument if it's varargs. If someone reassigns self/args, that's on them; it's fine to raise a RuntimeError if they use no-arg super(), requiring them to use two-arg super explicitly in that case.
History
Date User Action Args
2019-02-14 10:09:42BreamoreBoysetnosy: - BreamoreBoy
2019-02-13 18:51:17remi.lapeyresetnosy: + remi.lapeyre
2019-02-13 18:33:09josh.rsetpriority: normal -> low
status: pending -> open
messages: + msg335472

versions: + Python 3.8, - Python 3.2, Python 3.3, Python 3.4
2016-05-06 08:33:35serhiy.storchakasetstatus: open -> pending
2015-06-21 00:15:42martin.pantersetnosy: + martin.panter
messages: + msg245578
2015-06-20 19:42:03Cristóbal Gantersetnosy: + Cristóbal Ganter

messages: + msg245571
versions: + Python 3.4
2015-02-24 23:37:14josh.rsetnosy: + josh.r
messages: + msg236554
2015-02-24 14:56:06serhiy.storchakasetnosy: + benjamin.peterson
2015-02-24 14:25:05BreamoreBoysetnosy: + BreamoreBoy
messages: + msg236499
2012-09-02 20:07:33asvetlovsetmessages: + msg169720
2012-08-26 19:58:04Arfreversetnosy: + Arfrever
2012-08-26 02:32:32eric.araujosetnosy: + eric.araujo
2012-08-24 12:02:00asvetlovsetnosy: + asvetlov
messages: + msg169002
2012-08-24 11:19:17james.sanderssetmessages: + msg168997
2012-08-24 11:17:16ezio.melottisetnosy: + ezio.melotti
2012-08-24 10:28:25amaury.forgeotdarcsetnosy: + amaury.forgeotdarc
messages: + msg168995
2012-08-24 09:01:40james.sanderssetmessages: + msg168989
2012-08-23 19:13:45james.sanderssetfiles: + issue15753_varargsuper.patch
keywords: + patch
messages: + msg168959
2012-08-21 12:28:08r.david.murraysetnosy: + r.david.murray
2012-08-21 11:52:40james.sanderscreate