Qt.py icon indicating copy to clipboard operation
Qt.py copied to clipboard

Qt6 QtCore.QRegularExpression not available in Qt.py

Open sylvainberger opened this issue 1 year ago • 12 comments

Hi, When I try to import QtCore.QRegularExpression from Qt, I get an error. Importing directly from PySide6 works.

Example in Python3.11 with PySide6 and Qt.py: Python 3.11.9 (main, Oct 30 2024, 17:54:48) [GCC 11.3.1 20221121 (Red Hat 11.3.1-4)] on linux Type "help", "copyright", "credits" or "license" for more information.

from Qt.QtCore import QRegularExpression Traceback (most recent call last): File "", line 1, in ImportError: cannot import name 'QRegularExpression' from 'Qt.QtCore' (unknown location) from PySide6.QtCore import QRegularExpression print(QRegularExpression) <class 'PySide6.QtCore.QRegularExpression'>

sylvainberger avatar Nov 06 '24 17:11 sylvainberger

Looks like it's been remapped to QRegExp for backwards compatibility with Qt 4 and 5.

  • https://github.com/mottosso/Qt.py/blob/e8a2bf298e9e2e2fd544ee0dfb5d60118f867c62/Qt.py#L945C46-L945C53

mottosso avatar Nov 07 '24 07:11 mottosso

I can't make it work using QRegEx to get code compatible with Qt5 and Qt6

The best way I found is to do the import in try/except and use QRegularExpression

Example:

try:
    from PySide6.QtCore import QRegularExpression
except:
    from PySide2.QtCore import QRegularExpression

proxy_model = QtCore.QSortFilterProxyModel()
proxy_model.setFilterRegularExpression(QRegularExpression(re_pattern, QRegularExpression.CaseInsensitiveOption))

Any attemps to write compatible code using QRegEx fails in either Qt5 or Qt6

sylvainberger avatar Nov 07 '24 13:11 sylvainberger

QRegExp api is not compatible with QRegularExpression. QRegExp is gone in Qt6 so code getting updated will be ported to the QRegularExpression api which has been available since Qt5.0.

We also need QRegularExpressionMatch and QRegularExpressionMatchIterator classes exposed.

I am updating a lot of c++ code to qt6 currently and QRegExp -> QRegularExpression changes are a significant portion of the work due to the the api differences.

newellshk avatar Jan 16 '25 18:01 newellshk

seems like I'm in the same boat. a simple remapping of QRegExp -> QRegularExpression to keep the code compatible between pyside 2 and 6 doesn't work as the two functions are not interchangeable and cannot be used in the same way. I'm not sure if Qt.py can handle this gracefully in a simple way.

our code complains about: 'PySide6.QtCore.QRegularExpression' object has no attribute 'indexIn' when we switch the bindings to Pyside6 for Qt.py. I think we will need to detect the bindings and switch how we handle the regex internally.

p0las avatar Jan 24 '25 05:01 p0las

I think Qt.py needs an env var to control if we want to map QRegExp -> QRegularExpression or the other way around or possibly disable it all together and allow both. Currently I see no way to migrate the code to use QRegularExpression. QRegExp is gone and is not coming back and this migration is unavoidable.

p0las avatar Jan 29 '25 22:01 p0las

Am I understanding this correctly that QRegularExpression is Qt 6-only? If so, it couldn't be included with Qt.py, since then code written using Qt.py wouldn't run on Qt 5 apps, is that right?

If so, would it not be safe and equivalent to write this?

from Qt import QtWidgets # Compatible with Qt 5 and 6
from PySide6 import QRegularExpression  # Making this module Qt 6-only

EDIT: Aha, I see now. It's since Qt 5, but Qt.py still supports Qt 4, where it is not available.

  • https://github.com/mottosso/Qt.py/issues/413

Happy to take a pull request to vanquish Qt 4 and introduce QRegularExpression. 👍

mottosso avatar Jan 30 '25 08:01 mottosso

I spent some time today fixing some issues in our code related to this. The problem is that QRegExp was removed in Pyside6 while QRegularExpression was introduced a while ago and is available in Pyside2 and PySide6. PySide2.QtCore.QRegularExpression seems like a better class to keep the code compatible with multiple versions. having said that in most of the native QT code QRegExp can be replaced/substituted with QRegularExpression as long as it is simply passed around to validators and views and is not being interacted with, which is most of the cases. In our case we used some methods from that class and since all the methods are different in the new one the code broke. I discovered that in all our cases where we needed to use methods of QRegExp we could simply replace it with python's re module and keep the code compatible. so, in the end the substitution that Qt.py does works ok. However this is not future proof. We should be writing the code using QRegularExpression syntax as this is the only available one in the current QT and the substitution should be the other way around.

this illustrates the problem in more programmer friendly way:

>>> from PySide2 import QtCore
>>> QtCore.QRegularExpression
<class 'PySide2.QtCore.QRegularExpression'>
>>> from Qt import QtCore
>>> QtCore.QRegularExpression
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: module 'Qt.QtCore' has no attribute 'QRegularExpression'

I think we probably should have both available in Qt.py as both were available in Pyside2

p0las avatar Jan 30 '25 08:01 p0las

I think we probably should have both available in Qt.py as both were available in Pyside2

Then code written with Qt.py would not run on PySide or PyQt4. The problem is Qt 4 still being supported, what needs to happen is removal of Qt 4 support such that all supported bindings have this QRegularExpression class.

mottosso avatar Jan 31 '25 06:01 mottosso

what if in PySide and PyQt4 both QRegularExpression and QRegExp are mapped to QRegExp? wouldn't this work? then depending on Qt version the mapping of both changes accordingly.

p0las avatar Jan 31 '25 06:01 p0las

Hm, I'm unsure.

a simple remapping of QRegExp -> QRegularExpression to keep the code compatible between pyside 2 and 6 doesn't work as the two functions are not interchangeable and cannot be used in the same way.

What about this?

mottosso avatar Feb 03 '25 10:02 mottosso

Hm, I'm unsure.

a simple remapping of QRegExp -> QRegularExpression to keep the code compatible between pyside 2 and 6 doesn't work as the two functions are not interchangeable and cannot be used in the same way.

What about this?

what I have found so far is that as long as the QregExp and QRegularExpressions are passed to QT to deal with then there is no problem in Qt.py as all functions that accept them as inputs are also duplicated in QT and mapped in Qt.py. this simple solution works perfectly fine. the problems only start when there is any additional interaction with the regex functions outside of QT ecosystem as what appears to be QRegExp can, under the hood, in reality be QRegularExpression with different API. I do not have a perfect solution to this problem. We wrote a class that combined both Qt classes into one with common interface but we ditched this idea as too complicated and weird to use. in the end we opted to use Qt regex in cases where we need to pass it back to QT and in those cases we only make instances and pass them around. this works fine. for any case where we need to interact with regex we switched to re module. So far we have no cases where we need to both interact with regex instance and pass it to QT.

I totally understand the difficulty here.

p0las avatar Feb 03 '25 11:02 p0las

While you wait for qt4 to be ripped out, if your own code doesn't intend to support qt4 bindings (does anyone still write qt4 compatible code?) then the best solution is probably to add a QtSiteConfig.py in the root of your project and expose it yourself.

# Content of QtSiteConfig.py
def update_members(members):
    members["QtCore"].append("QRegularExpression")

Jerakin avatar Apr 11 '25 09:04 Jerakin