Skip to content

Commit

Permalink
Fix instance_attrs building error in Qt brain (#1505)
Browse files Browse the repository at this point in the history
Co-authored-by: Daniël van Noord <13665637+DanielNoord@users.noreply.github.com>
  • Loading branch information
2 people authored and Pierre-Sassoulas committed Apr 19, 2022
1 parent 87a9653 commit 6b1bf6c
Show file tree
Hide file tree
Showing 6 changed files with 81 additions and 12 deletions.
28 changes: 28 additions & 0 deletions .github/workflows/release-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,31 @@ jobs:
. venv2\scripts\activate
echo "import distutils.util # pylint: disable=unused-import" > test.py
pylint test.py
additional-dependencies-linux-tests:
name: Regression tests w/ additional dependencies (Linux)
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- name: Check out code from GitHub
uses: actions/checkout@v3.0.0
- name: Set up Python
id: python
uses: actions/setup-python@v3.1.0
with:
python-version: ${{ env.DEFAULT_PYTHON }}
- name: Install Qt
run: |
sudo apt-get install build-essential libgl1-mesa-dev
- name: Create Python virtual environment
run: |
python -m venv venv
. venv/bin/activate
python -m pip install -U pip setuptools wheel
pip install -U -r requirements_test.txt -r requirements_test_brain.txt
pip install -e .
- name: Run brain_qt tests
# Regression test added in https://github.com/PyCQA/astroid/pull/1505
run: |
. venv/bin/activate
pytest tests/unittest_brain_qt.py
3 changes: 3 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ What's New in astroid 2.11.3?
=============================
Release date: TBA

* Fixed an error in the Qt brain when building ``instance_attrs``.

Closes PyCQA/pylint#6221


What's New in astroid 2.11.2?
Expand Down
20 changes: 10 additions & 10 deletions astroid/brain/brain_qt.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ def _looks_like_signal(node, signal_name="pyqtSignal"):
return False


def transform_pyqt_signal(node):
def transform_pyqt_signal(node: nodes.FunctionDef) -> None:
module = parse(
"""
class pyqtSignal(object):
Expand All @@ -33,13 +33,13 @@ def emit(self, *args):
pass
"""
)
signal_cls = module["pyqtSignal"]
node.instance_attrs["emit"] = signal_cls["emit"]
node.instance_attrs["disconnect"] = signal_cls["disconnect"]
node.instance_attrs["connect"] = signal_cls["connect"]
signal_cls: nodes.ClassDef = module["pyqtSignal"]
node.instance_attrs["emit"] = [signal_cls["emit"]]
node.instance_attrs["disconnect"] = [signal_cls["disconnect"]]
node.instance_attrs["connect"] = [signal_cls["connect"]]


def transform_pyside_signal(node):
def transform_pyside_signal(node: nodes.FunctionDef) -> None:
module = parse(
"""
class NotPySideSignal(object):
Expand All @@ -51,10 +51,10 @@ def emit(self, *args):
pass
"""
)
signal_cls = module["NotPySideSignal"]
node.instance_attrs["connect"] = signal_cls["connect"]
node.instance_attrs["disconnect"] = signal_cls["disconnect"]
node.instance_attrs["emit"] = signal_cls["emit"]
signal_cls: nodes.ClassDef = module["NotPySideSignal"]
node.instance_attrs["connect"] = [signal_cls["connect"]]
node.instance_attrs["disconnect"] = [signal_cls["disconnect"]]
node.instance_attrs["emit"] = [signal_cls["emit"]]


def pyqt4_qtcore_transform():
Expand Down
3 changes: 1 addition & 2 deletions astroid/nodes/scoped_nodes/mixin.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,11 +108,10 @@ def add_local_node(self, child_node, name=None):
self._append_node(child_node)
self.set_local(name or child_node.name, child_node)

def __getitem__(self, item):
def __getitem__(self, item: str) -> "nodes.NodeNG":
"""The first node the defines the given local.
:param item: The name of the locally defined object.
:type item: str
:raises KeyError: If the name is not defined.
"""
Expand Down
1 change: 1 addition & 0 deletions requirements_test_brain.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ types-attrs
nose
numpy>=1.17.0
python-dateutil
PyQt6
types-python-dateutil
six
types-six
38 changes: 38 additions & 0 deletions tests/unittest_brain_qt.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
# For details: https://github.com/PyCQA/astroid/blob/main/LICENSE
# Copyright (c) https://github.com/PyCQA/astroid/blob/main/CONTRIBUTORS.txt

from importlib.util import find_spec

import pytest

from astroid import Uninferable, extract_node
from astroid.bases import UnboundMethod
from astroid.manager import AstroidManager
from astroid.nodes import FunctionDef

HAS_PYQT6 = find_spec("PyQt6")


@pytest.mark.skipif(HAS_PYQT6 is None, reason="This test requires the PyQt6 library.")
class TestBrainQt:
@staticmethod
def test_value_of_lambda_instance_attrs_is_list():
"""Regression test for https://github.com/PyCQA/pylint/issues/6221
A crash occurred in pylint when a nodes.FunctionDef was iterated directly,
giving items like "self" instead of iterating a one-element list containing
the wanted nodes.FunctionDef.
"""
src = """
from PyQt6 import QtPrintSupport as printsupport
printsupport.QPrintPreviewDialog.paintRequested #@
"""
AstroidManager.brain["extension_package_whitelist"] = {"PyQt6.QtPrintSupport"}
node = extract_node(src)
attribute_node = node.inferred()[0]
if attribute_node is Uninferable:
pytest.skip("PyQt6 C bindings may not be installed?")
assert isinstance(attribute_node, UnboundMethod)
# scoped_nodes.Lambda.instance_attrs is typed as Dict[str, List[NodeNG]]
assert isinstance(attribute_node.instance_attrs["connect"][0], FunctionDef)

0 comments on commit 6b1bf6c

Please sign in to comment.