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

Pylint can't find some PyGObject classes' members #6352

Open
Scrashdown opened this issue Apr 16, 2022 · 7 comments · May be fixed by pylint-dev/astroid#2453
Open

Pylint can't find some PyGObject classes' members #6352

Scrashdown opened this issue Apr 16, 2022 · 7 comments · May be fixed by pylint-dev/astroid#2453
Labels
False Positive 🦟 A message is emitted but nothing is wrong with the code Help wanted 🙏 Outside help would be appreciated, good for new contributors Needs astroid Brain 🧠 Needs a brain tip in astroid (then an astroid upgrade) Needs PR This issue is accepted, sufficiently specified and now needs an implementation Needs reproduction 🔍 Need a way to reproduce it locally on a maintainer's machine

Comments

@Scrashdown
Copy link

Bug description

Hello,

I have a simple class inheriting from PyGObject's Gtk.Window class. Pylint cannot Gtk.Window's add and show_all members, yet the code runs fine:

"""
The main window of the application.
"""

from typing import Tuple

import gi
gi.require_version("Gtk", "3.0")
# pylint: disable=wrong-import-position
from gi.repository import Gtk
# pylint: enable=wrong-import-position

class MainWindow(Gtk.Window):
    """
    The main window of the application.
    """

    WINDOW_SIZE: Tuple[int, int] = (500, 250)
    MAIN_PADDING_PX: int = 10
    FRAMES_VERTICAL_SPACE_PX: int = 10

    INPUT_FILE_FRAME_LABEL: str = "Input file"
    INPUT_FILE_BUTTON_LABEL: str = "Choose input file"

    def __init__(self, title: str):
        super().__init__(title=title)
        self.set_size_request(*self.WINDOW_SIZE)

        # --- Add widgets --- #

        # Main container
        main_box: Gtk.Box = Gtk.Box.new(orientation=Gtk.Orientation.VERTICAL,
                                        spacing=self.FRAMES_VERTICAL_SPACE_PX)
        self.add(main_box)
        MainWindow.__pad_on_all_sides(main_box, self.MAIN_PADDING_PX)

        # Input file picker
        input_file_frame: Gtk.Frame = Gtk.Frame.new(label=self.INPUT_FILE_FRAME_LABEL)
        main_box.pack_start(child=input_file_frame, expand=True, fill=True, padding=0)

        hbox: Gtk.Box = Gtk.Box.new(orientation=Gtk.Orientation.HORIZONTAL)
        input_file_frame.add(hbox)

        self.input_file_button = Gtk.Button.new(label=self.INPUT_FILE_BUTTON_LABEL)

        # --- Connect and show --- #
        self.connect("destroy", Gtk.main_quit)
        self.show_all()

    @staticmethod
    def __pad_on_all_sides(widget: Gtk.Widget, padding: int) -> None:
        widget.set_margin_bottom(padding)
        widget.set_margin_top(padding)
        widget.set_margin_left(padding)
        widget.set_margin_right(padding)

Interestingly, if I remove the following line, pylint stops complaining. It looks like adding a member to the MainWindow class which inherits from Gtk.Window throws off pylint.

self.input_file_button = Gtk.Button.new(label=self.INPUT_FILE_BUTTON_LABEL)

Configuration

I am using pylint's default configuration.

Command used

pylint main_window.py

Pylint output

************* Module main_window
main_window.py:34:8: E1101: Instance of 'MainWindow' has no 'add' member (no-member)
main_window.py:48:8: E1101: Instance of 'MainWindow' has no 'show_all' member (no-member)

------------------------------------------------------------------
Your code has been rated at 6.43/10 (previous run: 6.43/10, +0.00)

Expected behavior

I would expect pylint to find these two members, as they clearly exist since the code runs fine.

Pylint version

pylint 2.13.5
astroid 2.11.2
Python 3.10.4 (main, Mar 23 2022, 23:05:40) [GCC 11.2.0]

OS / Environment

EndeavourOS KDE version
5.17.3-arch1-1 kernel
All packages up-to-date

Additional dependencies

astroid==2.11.2
black==22.3.0
click==8.1.2
dill==0.3.4
isort==5.10.1
lazy-object-proxy==1.7.1
mccabe==0.7.0
mypy==0.942
mypy-extensions==0.4.3
pathspec==0.9.0
platformdirs==2.5.1
pycairo==1.21.0
PyGObject==3.42.0
pylint==2.13.5
tomli==2.0.1
typing_extensions==4.1.1
wrapt==1.14.0

@Scrashdown Scrashdown added the Needs triage 📥 Just created, needs acknowledgment, triage, and proper labelling label Apr 16, 2022
@jacobtylerwalls
Copy link
Member

Hi @Scrashdown, thanks for the report.

The astroid project handles most of the static analysis hints for specific projects to help pylint guess about membership. Unfortunately the "brain" for gi is completely untested. If you (or anyone else!) have got a cycle for it, there's a model for how to get a new package-specific unittest written in pylint-dev/astroid#1505.

@jacobtylerwalls jacobtylerwalls added Needs astroid Brain 🧠 Needs a brain tip in astroid (then an astroid upgrade) Bug 🪲 Help wanted 🙏 Outside help would be appreciated, good for new contributors False Positive 🦟 A message is emitted but nothing is wrong with the code Needs investigation 🔬 A bug or crash where it's not immediately obvious what is happenning and removed Needs triage 📥 Just created, needs acknowledgment, triage, and proper labelling labels Apr 18, 2022
@Pierre-Sassoulas Pierre-Sassoulas added the Needs PR This issue is accepted, sufficiently specified and now needs an implementation label Jun 24, 2022
vojtechtrefny added a commit to vojtechtrefny/blivet that referenced this issue Jul 14, 2022
Latest pylint/astroid has problems with parsing/introspecting
GI modules, see pylint-dev/pylint#6352
@hadess
Copy link

hadess commented Jul 18, 2022

The astroid project handles most of the static analysis hints for specific projects to help pylint guess about membership. Unfortunately the "brain" for gi is completely untested. If you (or anyone else!) have got a cycle for it, there's a model for how to get a new package-specific unittest written in PyCQA/astroid#1505.

Based on that, this seems to work correctly with python3-astroid-2.11.6-1.fc36.noarch but fails with python3-astroid-2.12.1-1.fc37, so it would be a regression.

gnomesysadmins pushed a commit to GNOME/totem that referenced this issue Jul 18, 2022
This time, the problem seems to be a regression in astroid:
pylint-dev/pylint#6352
gnomesysadmins pushed a commit to GNOME/totem that referenced this issue Jul 18, 2022
This time, the problem seems to be a regression in astroid:
pylint-dev/pylint#6352
@hadess
Copy link

hadess commented Dec 5, 2022

Seems to work correctly with pylint-2.14.4-3.fc37.noarch and python3-astroid-2.12.13-1.fc37.noarch for me.

@Pierre-Sassoulas Pierre-Sassoulas added Needs reproduction 🔍 Need a way to reproduce it locally on a maintainer's machine and removed Needs investigation 🔬 A bug or crash where it's not immediately obvious what is happenning labels Dec 5, 2022
@DanielNoord
Copy link
Collaborator

So, this is then no longer an issue?

@hadess
Copy link

hadess commented Dec 5, 2022

Not for me, but I'm not the original reporter.

@Salamandar
Copy link

I can confirm this issue is still present with those versions :

pylint 2.17.0
astroid 2.15.0
Python 3.10.9 (main, Dec 19 2022, 17:35:49) [GCC 12.2.0]

I have the same issue on my code AND on the original reporter's code.

@kulikjak
Copy link
Contributor

kulikjak commented May 17, 2023

Hi, I've also hit this issue. The following code is the shortest reproducible case I found.

import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk

cell = Gtk.CellRendererText()
#cell.props.xalign = 1.0

Gtk.Builder().connect_signals({})

When you run it like this, it works as expected; however, when you uncomment the cell.props.xalign line, it breaks with
test.py:8:0: E1101: Instance of 'Builder' has no 'connect_signals' member (no-member)
(connect_signals is only available in Gtk3, not in Gtk4)

I did a little bit more digging and found out that in the second (failing) case, following exception is raised in _register_require_version:
Namespace Gtk is already loaded with version 4.0

Debug prints in each function in brain_gi.py further showed that in the first case, require_version is handled first as expected. In the second case, _register_require_version is called after everything else has been processed, which is wrong (newer Gtk was already loaded at this point).

I found this in astroid 2.12.5 and pylint 2.15.2 with Python 3.7 and 3.11, but I also tried the latest and greatest (astroid 2.15.5 & pylint 2.17.4), and the same issue is still reproducible.

I guess I should report this bug in astroid itself? Sadly, I have no idea how astroid works, so I am afraid I won't be able to fix this, but it's a start.

marmarek added a commit to marmarek/astroid that referenced this issue Jun 24, 2024
When importing Gtk, it looks like this:

    import gi
    gi.require_version('Gtk', '3.0')
    from gi.repository import Gtk

It is vital that gi.require_version() is made before related 'from
gi.repository import ...'. The brain_gi tries to do that using
transforms. And it works unless Gtk is imported as part of delayed
assattr handling.

Fix this by handling transforms earlier.

Fixes pylint-dev#2190
Fixes pylint-dev/pylint#6352
marmarek added a commit to marmarek/astroid that referenced this issue Jun 25, 2024
When importing Gtk, it looks like this:

    import gi
    gi.require_version('Gtk', '3.0')
    from gi.repository import Gtk

It is vital that gi.require_version() is made before related 'from
gi.repository import ...'. The brain_gi tries to do that using
transforms. And it works unless Gtk is imported as part of delayed
assattr handling.

Fix this by adding early transforms that are called before delayed
assattr.

Fixes pylint-dev#2190
Fixes pylint-dev/pylint#6352
marmarek added a commit to marmarek/astroid that referenced this issue Jun 25, 2024
When importing Gtk, it looks like this:

    import gi
    gi.require_version('Gtk', '3.0')
    from gi.repository import Gtk

It is vital that gi.require_version() is made before related 'from
gi.repository import ...'. The brain_gi tries to do that using
transforms. And it works unless Gtk is imported as part of delayed
assattr handling.

Fix this by adding early transforms that are called before delayed
assattr.

Fixes pylint-dev#2190
Fixes pylint-dev/pylint#6352
marmarek added a commit to marmarek/astroid that referenced this issue Jun 27, 2024
When importing Gtk, it looks like this:

    import gi
    gi.require_version('Gtk', '3.0')
    from gi.repository import Gtk

It is vital that gi.require_version() is made before related 'from
gi.repository import ...'. The brain_gi tries to do that using
transforms. And it works unless Gtk is imported as part of delayed
assattr handling.

Fix this by adding early transforms that are called before delayed
assattr.

Fixes pylint-dev#2190
Fixes pylint-dev/pylint#6352
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
False Positive 🦟 A message is emitted but nothing is wrong with the code Help wanted 🙏 Outside help would be appreciated, good for new contributors Needs astroid Brain 🧠 Needs a brain tip in astroid (then an astroid upgrade) Needs PR This issue is accepted, sufficiently specified and now needs an implementation Needs reproduction 🔍 Need a way to reproduce it locally on a maintainer's machine
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants