-
Notifications
You must be signed in to change notification settings - Fork 619
Fix for PyQt6 error: AttributeError: 'CapaExplorerForm' object has no attribute 'range_model_proxy' #2713
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
base: master
Are you sure you want to change the base?
Conversation
…ttribute 'range_model_proxy'
Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA). View this failed invocation of the CLA check for more information. For the most up to date status, view the checks section at the bottom of the pull request. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add bug fixes, new features, breaking changes and anything else you think is worthwhile mentioning to the master (unreleased)
section of CHANGELOG.md. If no CHANGELOG update is needed add the following to the PR description: [x] No CHANGELOG update needed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Summary of Changes
Hello @nicolaipre, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!
This pull request addresses critical compatibility issues preventing the FLARE Capa Explorer plugin from functioning with IDA Pro after its update to PyQt6. The changes introduce a flexible mechanism to handle variations in PyQt API, ensuring the plugin remains operational across different PyQt versions without requiring separate codebases.
Highlights
- PyQt6 Compatibility: Resolves AttributeError issues (range_model_proxy and ItemIsTristate) that arose in the FLARE Capa Explorer plugin after IDA's transition to PyQt6, ensuring the plugin functions correctly.
- Cross-Version PyQt Support: Implements a robust compatibility layer in capa/ida/plugin/item.py to dynamically adapt to QtCore.Qt item flag differences between PyQt5 and PyQt6/PySide6, allowing the codebase to support both versions.
Using Gemini Code Assist
The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.
Invoking Gemini
You can request assistance from Gemini at any point in your pull request via creating an issue comment (i.e. comment on the pull request page) using either /gemini <command>
or @gemini-code-assist <command>
. Below is a summary of the supported commands.
Feature | Command | Description |
---|---|---|
Code Review | /gemini review |
Performs a code review for the current pull request in its current state. |
Pull Request Summary | /gemini summary |
Provides a summary of the current pull request in its current state. |
Comment | @gemini-code-assist | Responds in comments when explicitly tagged, both in issue comments and review comments. |
Help | /gemini help |
Displays a list of available commands. |
Customization
To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/
folder in the base of the repository. Detailed instructions can be found here.
Limitations & Feedback
Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.
You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.
Footnotes
-
Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution. ↩
CHANGELOG updated or no update needed, thanks! 😄
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code Review
This pull request addresses an AttributeError
that occurs when using the plugin with PyQt6 by introducing a compatibility layer for Qt flags. The changes correctly adapt the code for PyQt6's enum-based flags.
However, the implementation for the PyQt5 fallback is incorrect and will cause a crash, as it attempts to access a .value
attribute on integer constants. I've provided a critical review comment with a suggested fix to create a proper shim for PyQt5, ensuring the plugin works correctly with both library versions.
if hasattr(QtCore.Qt, 'ItemFlag'): | ||
# PyQt6 / PySide6 | ||
ItemFlag = QtCore.Qt.ItemFlag | ||
TRISTATE = ItemFlag.ItemIsAutoTristate | ||
else: | ||
# PyQt5 | ||
ItemFlag = QtCore.Qt | ||
TRISTATE = ItemFlag.ItemIsTristate |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This compatibility layer is a great idea to support both PyQt5 and PyQt6. However, the current implementation for the PyQt5 fallback will not work as intended. In PyQt5, ItemFlag
is set to QtCore.Qt
, and attributes like QtCore.Qt.ItemIsEnabled
are integers. Accessing .value
on an integer (e.g., ItemFlag.ItemIsEnabled.value
) will raise an AttributeError
.
To ensure PyQt5 compatibility while keeping the usage sites clean, you can create a shim for PyQt5 that mimics the structure of PyQt6 enums. This will make the code work for both versions without further changes.
if hasattr(QtCore.Qt, 'ItemFlag'): | |
# PyQt6 / PySide6 | |
ItemFlag = QtCore.Qt.ItemFlag | |
TRISTATE = ItemFlag.ItemIsAutoTristate | |
else: | |
# PyQt5 | |
ItemFlag = QtCore.Qt | |
TRISTATE = ItemFlag.ItemIsTristate | |
if hasattr(QtCore.Qt, 'ItemFlag'): | |
# PyQt6 / PySide6 | |
ItemFlag = QtCore.Qt.ItemFlag | |
TRISTATE = ItemFlag.ItemIsAutoTristate | |
else: | |
# PyQt5 | |
# Create a shim to behave like PyQt6's enums which have a .value attribute. | |
class EnumValue: | |
def __init__(self, value): | |
self.value = value | |
class QtEnumShim: | |
ItemIsEnabled = EnumValue(QtCore.Qt.ItemIsEnabled) | |
ItemIsSelectable = EnumValue(QtCore.Qt.ItemIsSelectable) | |
ItemIsUserCheckable = EnumValue(QtCore.Qt.ItemIsUserCheckable) | |
ItemIsEditable = EnumValue(QtCore.Qt.ItemIsEditable) | |
ItemFlag = QtEnumShim() | |
TRISTATE = EnumValue(QtCore.Qt.ItemIsTristate) |
I decided to give it a test with IDA 9.1 too and in its current state it does not work for both PyQt5 and PyQt6. Geminis suggestion did not work either so the PR needs some changes. Before testing further I will wait for your feedback. There are probably more files that need changes to make the plugin fully compatible with PyQt6 but this works temporarily... |
I think it'd be more ideal to check for IDA versioning number and decide to import PyQt5 or PySide6 accordingly instead of doing a simple attr-based check |
You are absolutely right. I will see what I can do when I find time. I'll leave the PR open until then. |
Hey guys, hope you are doing all good.
After IDA moved onto PyQt6 I encountered this error when opening the FLARE Capa Explorer plugin:
The following error also showed up in IDAs output window:
This minimal PR resolves the problem and (according to ChatGPT, lol) has a fallback for PyQt5 which I have not tested. Plugin works as intended with PyQt6 with current implementation. I do not think a new test is needed considering this was caused by a major change in a library version.
Checklist