Skip to content

False positive C2801 unnecessary-dunder-call for descriptor binding __get__ #8265

Open
@eqvinox

Description

@eqvinox

Bug description

When converting an unbound method (on a class) to a bound method (on an object) by calling __get__, pylint emits an unnecessary-dunder-call warning:

class Cls:
    def __init__(self, foobar):
        self.foobar = foobar

    def get_foobar(self):
        return self.foobar

def test(class_ref, method_ref):
    print(method_ref)
    # <function Cls.get_foobar at 0x7f0e0f151f80>

    instance = class_ref(1234)
    bound_method = method_ref.__get__(instance, class_ref)
    # ^- C2801: Unnecessarily calls dunder method __get__. Use get method. (unnecessary-dunder-call)

    print(bound_method)
    # <bound method Cls.get_foobar of <__main__.Cls object at 0x7fc81afa6d90>>
    print(bound_method())
    # 1234

test(Cls, Cls.get_foobar)

The use case of this is in pytest, class attributes are scanned for test case methods first (without an instance) and then later bound to an instance of their class.

To my knowledge (happy to be proven wrong?), the descriptor dunder methods (__get__, __set__, __delete__) don't have any other way of being invoked, there is no get/set/delete. So they should be ignored for the dunder warning.

Command used

python3 method_bind.py

Pylint output

[…]
method_bind.py:13:19: C2801: Unnecessarily calls dunder method __get__. Use get method. (unnecessary-dunder-call)

Expected behavior

No warning.

Pylint version

pylint 2.15.10
astroid 2.13.3
Python 3.11.2 (main, Feb  8 2023, 21:22:32) [GCC 12.2.0]

OS / Environment

Debian unstable

Metadata

Metadata

Assignees

No one assigned

    Labels

    Needs decision 🔒Needs a decision before implemention or rejection

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions