Decorating methods makes **kwargs pass duplicate arguments

Issue #2996 resolved

I think demonstrating the bug with some code would do better job than if I tried to explain it with words. The code works on CPython 3.6 - 3.8, but on PyPy 3.5.3 it throws TypeError.

Comments (10)

  1. Αριστοτέλης Μικρόπουλος reporter

    May I add, that it works fine on CPython 3.5.2 too (no error)

  2. Kyle Altendorf

    I think this is a simpler example of hopefully the same issue. It seems like the implicit self is missing the *args and ending up in a_parameter.

    d = {'a_parameter': 4}
    
    def function(*args, a_parameter=None, **kwargs):
        pass
    
    function(1, **d)
    
    
    class Class:
        def method(*args, a_parameter=None, **kwargs):
            pass
    
    Class.method(**d)
    
    instance = Class()
    instance.method(a_parameter=4)
    instance.method(**d)
    
     ~/amikrop   master ●  pypy3.5 --version
    Python 3.5.3 (928a4f70d3de7d17449456946154c5da6e600162, Feb 09 2019, 11:50:43)
    [PyPy 7.0.0 with GCC 8.2.0]
    
     ~/amikrop   master ●  pypy3.5 a.py
    Traceback (most recent call last):
      File "a.py", line 17, in <module>
        instance.method(**d)
    TypeError: method() got multiple values for argument 'a_parameter'
    
     ✘  ~/amikrop   master ●  pypy3.6 --version
    Python 3.6.1 (fb40f7a5524c77b80e6c468e087d621610137261, Feb 09 2019, 15:00:51)
    [PyPy 7.0.0-alpha0 with GCC 8.2.0]
    
     ~/amikrop   master ●  pypy3.6 a.py
    Traceback (most recent call last):
      File "a.py", line 17, in <module>
        instance.method(**d)
    TypeError: method() got multiple values for argument 'a_parameter'
    
  3. Armin Rigo

    Similarly:

    class Foo:
        def meth(*args, offset=None):
            print(args)
            print(offset)
    
    Foo().meth(**{})
    

    first prints args as expected as (<__main__.Foo object at 0x00007f0ae8698790>,), but then crashes with
    UnboundLocalError: local variable 'offset' referenced before assignment

  4. Arthur Darcet

    @Armin Rigo the example code you provided still fails in the 3.6 interpreter of 7.1.1

    It also fails with the latest 3.5 interpreter. Could this patch be backported? (3.6 is still beta…)

    Also, why are the two tests you added commented? they would be failing if they weren't de-activated.

  5. mattip

    7.1.1 was release before the fix, which will be available in an upcoming release. In the meantime, you can use the nightly build of the py3.6 branch. All our efforts are concentrated on py3.6. We could be convinced otherwise if there is ongoing financial support, or if someone wishes to volunteer to maintain older versions.

  6. Arthur Darcet

    Ok, thank you for the answer!

    For anyone stumbling on this, a quick workaround is to add an explicit self parameter in the method

  7. Log in to comment