Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CallContext assertion failed in the wild #9214

Closed
martin-belanger opened this issue Nov 2, 2023 · 2 comments · Fixed by pylint-dev/astroid#2458
Closed

CallContext assertion failed in the wild #9214

martin-belanger opened this issue Nov 2, 2023 · 2 comments · Fixed by pylint-dev/astroid#2458
Assignees
Labels
Astroid Related to astroid Crash 💥 A bug that makes pylint crash
Milestone

Comments

@martin-belanger
Copy link

martin-belanger commented Nov 2, 2023

I wrote a simple mock module (below) to show the problem. The code executes fine with Python 3.10. However, pylint throws an exception (log below) when parsing it. I updated pylint today from 2.17.5 to 3.0.2. That's when it started to fail.

Note: This was run on Ubuntu 22.04 with Python 3.10.

Pylint version that was working OK:

$ pylint --version
pylint 2.17.5
astroid 2.15.6

Pylint version that is not working:

$ pylint --version
pylint 3.0.2
astroid 3.0.1

Mock module:

'''Test module'''
import functools

class MockClass():
    '''Mock class'''
    def __init__(self, enabled=True):
        self._options = {
            'Global': {
                'Enabled': enabled,
            }
        }

    def _get_option(self, section, option):
        '''Mock getter'''
        return self._options[section][option]

    enabled = property(functools.partial(_get_option, section='Global', option='Enabled'))

    @property
    def supported_types(self):
        '''Get supported types'''
        return ['tcp', 'udp'] if self.enabled else list()


if __name__ == '__main__':
    obj = MockClass()

    print(f'enabled={obj.enabled}')
    print(f'supported_types={obj.supported_types}')

This is pylint's output:

pylint --rcfile=/home/mbelanger/work/linux-nvme/nvme-stas/test/pylint.rc ./property.py 
Exception on node <FunctionDef.supported_types l.20 at 0x7f67dae01ae0> in file '/tmp/property.py'
Traceback (most recent call last):
  File "/usr/local/lib/python3.10/dist-packages/astroid/bases.py", line 245, in getattr
    values = self._proxied.instance_attr(name, context)
  File "/usr/local/lib/python3.10/dist-packages/astroid/nodes/scoped_nodes/scoped_nodes.py", line 2353, in instance_attr
    raise AttributeInferenceError(target=self, attribute=name, context=context)
astroid.exceptions.AttributeInferenceError: 'enabled' not found on <ClassDef.MockClass l.4 at 0x7f67dae028f0>.

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/usr/local/lib/python3.10/dist-packages/astroid/bases.py", line 278, in igetattr
    get_attr = self.getattr(name, context, lookupclass=False)
  File "/usr/local/lib/python3.10/dist-packages/astroid/bases.py", line 255, in getattr
    raise AttributeInferenceError(
astroid.exceptions.AttributeInferenceError: 'enabled' not found on <Instance of property.MockClass at 0x140084026905104>.

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/local/lib/python3.10/dist-packages/pylint/utils/ast_walker.py", line 91, in walk
    callback(astroid)
  File "/usr/local/lib/python3.10/dist-packages/pylint/checkers/classes/special_methods_checker.py", line 183, in visit_functiondef
    inferred = _safe_infer_call_result(node, node)
  File "/usr/local/lib/python3.10/dist-packages/pylint/checkers/classes/special_methods_checker.py", line 42, in _safe_infer_call_result
    value = next(inferit)
  File "/usr/local/lib/python3.10/dist-packages/astroid/nodes/scoped_nodes/scoped_nodes.py", line 1650, in infer_call_result
    yield from returnnode.value.infer(context)
  File "/usr/local/lib/python3.10/dist-packages/astroid/nodes/node_ng.py", line 169, in infer
    for i, result in enumerate(self._infer(context=context, **kwargs)):
  File "/usr/local/lib/python3.10/dist-packages/astroid/decorators.py", line 90, in inner
    yield next(generator)
  File "/usr/local/lib/python3.10/dist-packages/astroid/nodes/node_classes.py", line 3108, in _infer
    test = next(self.test.infer(context=context.clone()))
  File "/usr/local/lib/python3.10/dist-packages/astroid/nodes/node_ng.py", line 169, in infer
    for i, result in enumerate(self._infer(context=context, **kwargs)):
  File "/usr/local/lib/python3.10/dist-packages/astroid/decorators.py", line 90, in inner
    yield next(generator)
  File "/usr/local/lib/python3.10/dist-packages/astroid/decorators.py", line 49, in wrapped
    for res in _func(node, context, **kwargs):
  File "/usr/local/lib/python3.10/dist-packages/astroid/nodes/node_classes.py", line 1107, in _infer_attribute
    yield from owner.igetattr(node.attrname, context)
  File "/usr/local/lib/python3.10/dist-packages/astroid/bases.py", line 290, in igetattr
    yield from self._wrap_attr(attrs, context)
  File "/usr/local/lib/python3.10/dist-packages/astroid/bases.py", line 298, in _wrap_attr
    for attr in attrs:
  File "/usr/local/lib/python3.10/dist-packages/astroid/nodes/scoped_nodes/scoped_nodes.py", line 2520, in igetattr
    yield from function.infer_call_result(
  File "/usr/local/lib/python3.10/dist-packages/astroid/objects.py", line 317, in infer_call_result
    assert (
AssertionError: CallContext should be set before inferring call result
************* Module property
property.py:1:0: F0002: property.py: Fatal error while checking 'property.py'. Please open an issue in our bug tracker so we address this. There is a pre-filled template that you can use in '/home/mbelanger/.cache/pylint/pylint-crash-2023-11-02-13-05-18.txt'. (astroid-error)

--------------------------------------------------------------------
Your code has been rated at 10.00/10 (previous run: 10.00/10, +0.00)
@jacobtylerwalls jacobtylerwalls added the Needs triage 📥 Just created, needs acknowledgment, triage, and proper labelling label Nov 4, 2023
@jacobtylerwalls jacobtylerwalls added Astroid Related to astroid Needs investigation 🔬 A bug or crash where it's not immediately obvious what is happenning High priority Issue with more than 10 reactions and removed Needs triage 📥 Just created, needs acknowledgment, triage, and proper labelling labels Dec 25, 2023
@jacobtylerwalls jacobtylerwalls added this to the 3.1.0 milestone Dec 25, 2023
@jacobtylerwalls jacobtylerwalls added the Crash 💥 A bug that makes pylint crash label Dec 25, 2023
@jacobtylerwalls jacobtylerwalls changed the title Pylint throws astroid.exceptions.AttributeInferenceError when property is used with functools CallContext assertion failed in the wild Dec 26, 2023
@jacobtylerwalls jacobtylerwalls modified the milestones: 3.1.0, 3.2.0 Feb 24, 2024
@jacobtylerwalls jacobtylerwalls modified the milestones: 3.2.0, 3.3.0 May 7, 2024
@brycepg
Copy link
Contributor

brycepg commented Jul 3, 2024

Here's a more minimal example:

import astroid

text = """
import functools

class MockClass:
    def _get_option(self, option):
        return "mystr"

    enabled = property(functools.partial(_get_option, option='myopt'))

MockClass().enabled #@
"""
print(astroid.extract_node(text).inferred())

I can confirm that this has something to do with the partial brain since commenting out that brain fixes this issue

Unsure where/how this call context should be set, should we remove this assertion?

@jacobtylerwalls
Copy link
Member

Thanks for the reproducer. I think removing the assertion won't help; it would just crash on the next line.

Unsure where/how this call context should be set, should we remove this assertion?

Based on this, I wonder if we can do something like:

diff --git a/astroid/nodes/scoped_nodes/scoped_nodes.py b/astroid/nodes/scoped_nodes/scoped_nodes.py
index cad91dcf..efd5439b 100644
--- a/astroid/nodes/scoped_nodes/scoped_nodes.py
+++ b/astroid/nodes/scoped_nodes/scoped_nodes.py
@@ -2518,6 +2518,10 @@ class ClassDef(  # pylint: disable=too-many-instance-attributes
                 elif isinstance(inferred, objects.Property):
                     function = inferred.function
                     if not class_context:
+                        if not context.callcontext:
+                            context.callcontext = CallContext(
+                                args=function.args.arguments, callee=function
+                            )
                         # Through an instance so we can solve the property
                         yield from function.infer_call_result(
                             caller=self, context=context

@jacobtylerwalls jacobtylerwalls self-assigned this Jul 7, 2024
@jacobtylerwalls jacobtylerwalls modified the milestones: 3.3.0, 3.2.6 Jul 7, 2024
jacobtylerwalls added a commit to pylint-dev/astroid that referenced this issue Jul 7, 2024
…function.

Closes pylint-dev/pylint#9214

Thanks Martin Belanger for the report and
Bryce Guinta for the test case.
@jacobtylerwalls jacobtylerwalls removed Needs investigation 🔬 A bug or crash where it's not immediately obvious what is happenning High priority Issue with more than 10 reactions labels Jul 7, 2024
github-actions bot pushed a commit to pylint-dev/astroid that referenced this issue Jul 8, 2024
…function. (#2458)

Closes pylint-dev/pylint#9214

Thanks Martin Belanger for the report and
Bryce Guinta for the test case.

(cherry picked from commit 0f9dfa6)
jacobtylerwalls added a commit to pylint-dev/astroid that referenced this issue Jul 9, 2024
…function. (#2458)

Closes pylint-dev/pylint#9214

Thanks Martin Belanger for the report and
Bryce Guinta for the test case.

(cherry picked from commit 0f9dfa6)
jacobtylerwalls added a commit to pylint-dev/astroid that referenced this issue Jul 9, 2024
…function. (#2458) (#2460)

Closes pylint-dev/pylint#9214

Thanks Martin Belanger for the report and
Bryce Guinta for the test case.

(cherry picked from commit 0f9dfa6)

Co-authored-by: Jacob Walls <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Astroid Related to astroid Crash 💥 A bug that makes pylint crash
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants