Skip to content

Commit c10f18c

Browse files
Fix instance_attrs building error in Qt brain (#1505)
Co-authored-by: Daniël van Noord <[email protected]>
1 parent 6c29972 commit c10f18c

File tree

6 files changed

+81
-12
lines changed

6 files changed

+81
-12
lines changed

.github/workflows/release-tests.yml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,31 @@ jobs:
3131
. venv2\scripts\activate
3232
echo "import distutils.util # pylint: disable=unused-import" > test.py
3333
pylint test.py
34+
35+
additional-dependencies-linux-tests:
36+
name: Regression tests w/ additional dependencies (Linux)
37+
runs-on: ubuntu-latest
38+
timeout-minutes: 5
39+
steps:
40+
- name: Check out code from GitHub
41+
uses: actions/[email protected]
42+
- name: Set up Python
43+
id: python
44+
uses: actions/[email protected]
45+
with:
46+
python-version: ${{ env.DEFAULT_PYTHON }}
47+
- name: Install Qt
48+
run: |
49+
sudo apt-get install build-essential libgl1-mesa-dev
50+
- name: Create Python virtual environment
51+
run: |
52+
python -m venv venv
53+
. venv/bin/activate
54+
python -m pip install -U pip setuptools wheel
55+
pip install -U -r requirements_test.txt -r requirements_test_brain.txt
56+
pip install -e .
57+
- name: Run brain_qt tests
58+
# Regression test added in https://github.com/PyCQA/astroid/pull/1505
59+
run: |
60+
. venv/bin/activate
61+
pytest tests/unittest_brain_qt.py

ChangeLog

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ What's New in astroid 2.11.3?
1212
=============================
1313
Release date: TBA
1414

15+
* Fixed an error in the Qt brain when building ``instance_attrs``.
16+
17+
Closes PyCQA/pylint#6221
1518

1619

1720
What's New in astroid 2.11.2?

astroid/brain/brain_qt.py

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ def _looks_like_signal(node, signal_name="pyqtSignal"):
2121
return False
2222

2323

24-
def transform_pyqt_signal(node):
24+
def transform_pyqt_signal(node: nodes.FunctionDef) -> None:
2525
module = parse(
2626
"""
2727
class pyqtSignal(object):
@@ -33,13 +33,13 @@ def emit(self, *args):
3333
pass
3434
"""
3535
)
36-
signal_cls = module["pyqtSignal"]
37-
node.instance_attrs["emit"] = signal_cls["emit"]
38-
node.instance_attrs["disconnect"] = signal_cls["disconnect"]
39-
node.instance_attrs["connect"] = signal_cls["connect"]
36+
signal_cls: nodes.ClassDef = module["pyqtSignal"]
37+
node.instance_attrs["emit"] = [signal_cls["emit"]]
38+
node.instance_attrs["disconnect"] = [signal_cls["disconnect"]]
39+
node.instance_attrs["connect"] = [signal_cls["connect"]]
4040

4141

42-
def transform_pyside_signal(node):
42+
def transform_pyside_signal(node: nodes.FunctionDef) -> None:
4343
module = parse(
4444
"""
4545
class NotPySideSignal(object):
@@ -51,10 +51,10 @@ def emit(self, *args):
5151
pass
5252
"""
5353
)
54-
signal_cls = module["NotPySideSignal"]
55-
node.instance_attrs["connect"] = signal_cls["connect"]
56-
node.instance_attrs["disconnect"] = signal_cls["disconnect"]
57-
node.instance_attrs["emit"] = signal_cls["emit"]
54+
signal_cls: nodes.ClassDef = module["NotPySideSignal"]
55+
node.instance_attrs["connect"] = [signal_cls["connect"]]
56+
node.instance_attrs["disconnect"] = [signal_cls["disconnect"]]
57+
node.instance_attrs["emit"] = [signal_cls["emit"]]
5858

5959

6060
def pyqt4_qtcore_transform():

astroid/nodes/scoped_nodes/mixin.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,11 +108,10 @@ def add_local_node(self, child_node, name=None):
108108
self._append_node(child_node)
109109
self.set_local(name or child_node.name, child_node)
110110

111-
def __getitem__(self, item):
111+
def __getitem__(self, item: str) -> "nodes.NodeNG":
112112
"""The first node the defines the given local.
113113
114114
:param item: The name of the locally defined object.
115-
:type item: str
116115
117116
:raises KeyError: If the name is not defined.
118117
"""

requirements_test_brain.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ types-attrs
33
nose
44
numpy>=1.17.0
55
python-dateutil
6+
PyQt6
67
types-python-dateutil
78
six
89
types-six

tests/unittest_brain_qt.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
2+
# For details: https://github.com/PyCQA/astroid/blob/main/LICENSE
3+
# Copyright (c) https://github.com/PyCQA/astroid/blob/main/CONTRIBUTORS.txt
4+
5+
from importlib.util import find_spec
6+
7+
import pytest
8+
9+
from astroid import Uninferable, extract_node
10+
from astroid.bases import UnboundMethod
11+
from astroid.manager import AstroidManager
12+
from astroid.nodes import FunctionDef
13+
14+
HAS_PYQT6 = find_spec("PyQt6")
15+
16+
17+
@pytest.mark.skipif(HAS_PYQT6 is None, reason="This test requires the PyQt6 library.")
18+
class TestBrainQt:
19+
@staticmethod
20+
def test_value_of_lambda_instance_attrs_is_list():
21+
"""Regression test for https://github.com/PyCQA/pylint/issues/6221
22+
23+
A crash occurred in pylint when a nodes.FunctionDef was iterated directly,
24+
giving items like "self" instead of iterating a one-element list containing
25+
the wanted nodes.FunctionDef.
26+
"""
27+
src = """
28+
from PyQt6 import QtPrintSupport as printsupport
29+
printsupport.QPrintPreviewDialog.paintRequested #@
30+
"""
31+
AstroidManager.brain["extension_package_whitelist"] = {"PyQt6.QtPrintSupport"}
32+
node = extract_node(src)
33+
attribute_node = node.inferred()[0]
34+
if attribute_node is Uninferable:
35+
pytest.skip("PyQt6 C bindings may not be installed?")
36+
assert isinstance(attribute_node, UnboundMethod)
37+
# scoped_nodes.Lambda.instance_attrs is typed as Dict[str, List[NodeNG]]
38+
assert isinstance(attribute_node.instance_attrs["connect"][0], FunctionDef)

0 commit comments

Comments
 (0)