From 943c622342bdcd80f3f5b0225eb0ee3601269d5a Mon Sep 17 00:00:00 2001 From: dalthviz Date: Thu, 4 Nov 2021 12:06:07 -0500 Subject: [PATCH 1/9] PyQt6: Add support for initial unscoped enum access and tests --- qtpy/QtCore.py | 7 ++--- qtpy/QtGui.py | 5 ++-- qtpy/QtWidgets.py | 10 +++++--- qtpy/compat.py | 4 +-- qtpy/enums_compat.py | 50 ++++++++++++++++++++++++++++++++++++ qtpy/sip.py | 15 +++++++++++ qtpy/tests/test_qtcore.py | 17 +++++++++++- qtpy/tests/test_qtgui.py | 33 ++++++++++++++++++++++++ qtpy/tests/test_qtwidgets.py | 45 ++++++++++++++++++++++++++++++++ 9 files changed, 173 insertions(+), 13 deletions(-) create mode 100644 qtpy/enums_compat.py create mode 100644 qtpy/sip.py create mode 100644 qtpy/tests/test_qtgui.py create mode 100644 qtpy/tests/test_qtwidgets.py diff --git a/qtpy/QtCore.py b/qtpy/QtCore.py index ac6e78b9..322b87d0 100644 --- a/qtpy/QtCore.py +++ b/qtpy/QtCore.py @@ -8,18 +8,19 @@ """ Provides QtCore classes and functions. """ - from . import PYQT6, PYQT5, PYSIDE2, PYSIDE6, PythonQtError + if PYQT6: + from PyQt6 import QtCore from PyQt6.QtCore import * from PyQt6.QtCore import pyqtSignal as Signal from PyQt6.QtCore import QT_VERSION_STR as __version__ - QCoreApplication.exec_ = QCoreApplication.exec QEventLoop.exec_ = QEventLoop.exec QThread.exec_ = QThread.exec - + from .enums_compat import promote_enums + promote_enums(QtCore) elif PYQT5: from PyQt5.QtCore import * from PyQt5.QtCore import pyqtSignal as Signal diff --git a/qtpy/QtGui.py b/qtpy/QtGui.py index da8369e6..9bc3ee94 100644 --- a/qtpy/QtGui.py +++ b/qtpy/QtGui.py @@ -8,16 +8,17 @@ """ Provides QtGui classes and functions. """ -import warnings - from . import PYQT6, PYQT5, PYSIDE2, PYSIDE6, PythonQtError if PYQT6: + from PyQt6 import QtGui from PyQt6.QtGui import * QDrag.exec_ = QDrag.exec QGuiApplication.exec_ = QGuiApplication.exec QTextDocument.print_ = QTextDocument.print + from .enums_compat import promote_enums + promote_enums(QtGui) elif PYQT5: from PyQt5.QtGui import * elif PYSIDE2: diff --git a/qtpy/QtWidgets.py b/qtpy/QtWidgets.py index d1f7b730..be82b060 100644 --- a/qtpy/QtWidgets.py +++ b/qtpy/QtWidgets.py @@ -8,23 +8,25 @@ """ Provides widget classes and functions. """ - from . import PYQT5, PYQT6, PYSIDE2, PYSIDE6, PythonQtError -from ._patch.qheaderview import introduce_renamed_methods_qheaderview + if PYQT6: + from PyQt6 import QtWidgets from PyQt6.QtWidgets import * from PyQt6.QtGui import QAction, QActionGroup, QShortcut from PyQt6.QtOpenGLWidgets import QOpenGLWidget QTextEdit.setTabStopWidth = QTextEdit.setTabStopDistance QTextEdit.tabStopWidth = QTextEdit.tabStopDistance + QTextEdit.print_ = QTextEdit.print QPlainTextEdit.setTabStopWidth = QPlainTextEdit.setTabStopDistance QPlainTextEdit.tabStopWidth = QPlainTextEdit.tabStopDistance + QPlainTextEdit.print_ = QPlainTextEdit.print QApplication.exec_ = QApplication.exec QDialog.exec_ = QDialog.exec QMenu.exec_ = QMenu.exec - QTextEdit.print_ = QTextEdit.print - QPlainTextEdit.print_ = QPlainTextEdit.print + from .enums_compat import promote_enums + promote_enums(QtWidgets) elif PYQT5: from PyQt5.QtWidgets import * elif PYSIDE6: diff --git a/qtpy/compat.py b/qtpy/compat.py index 3a51c921..7494862f 100644 --- a/qtpy/compat.py +++ b/qtpy/compat.py @@ -5,8 +5,6 @@ """ Compatibility functions """ - -from collections.abc import Callable import sys from .QtWidgets import QFileDialog @@ -53,7 +51,7 @@ def from_qvariant(qobj=None, pytype=None): # analysis:ignore # Wrappers around QFileDialog static methods # ============================================================================= def getexistingdirectory(parent=None, caption='', basedir='', - options=QFileDialog.ShowDirsOnly): + options=QFileDialog.Option.ShowDirsOnly): """Wrapper around QtGui.QFileDialog.getExistingDirectory static method Compatible with PyQt >=v4.4 (API #1 and #2) and PySide >=v1.0""" # Calling QFileDialog static method diff --git a/qtpy/enums_compat.py b/qtpy/enums_compat.py new file mode 100644 index 00000000..b0a52939 --- /dev/null +++ b/qtpy/enums_compat.py @@ -0,0 +1,50 @@ +# +# Copyright © 2009- The Spyder Development Team +# Licensed under the terms of the MIT License +""" +Compatibility functions for scoped and unscoped enums access +""" +from . import PYQT6 + +if PYQT6: + import enum + + from . import sip + + + def promote_specific_enums(base_class, enum_classes_list, inclusion_criteria): + """ + Allow access for the given enumeration classes values at base class level. + + Based on: + https://github.com/pyqtgraph/pyqtgraph/blob/pyqtgraph-0.12.1/pyqtgraph/Qt.py#L331-L377 + """ + for enum_class_name in enum_classes_list: + klass = getattr(base_class, enum_class_name) + attrib_names = [x for x in dir(klass) if inclusion_criteria(x)] + for attrib_name in attrib_names: + attrib = getattr(klass, attrib_name) + if not isinstance(attrib, (enum.Enum)): + continue + setattr(base_class, attrib.name, attrib) + + + def promote_enums(module): + """ + Search enums in the given module and allow unscoped access. + + Taken from: + https://github.com/pyqtgraph/pyqtgraph/blob/pyqtgraph-0.12.1/pyqtgraph/Qt.py#L331-L377 + """ + class_names = [x for x in dir(module) if x.startswith('Q')] + for class_name in class_names: + klass = getattr(module, class_name) + if not isinstance(klass, sip.wrappertype): + continue + attrib_names = [x for x in dir(klass) if x[0].isupper()] + for attrib_name in attrib_names: + attrib = getattr(klass, attrib_name) + if not isinstance(attrib, enum.EnumMeta): + continue + for e in attrib: + setattr(klass, e.name, e) \ No newline at end of file diff --git a/qtpy/sip.py b/qtpy/sip.py new file mode 100644 index 00000000..b0237c8e --- /dev/null +++ b/qtpy/sip.py @@ -0,0 +1,15 @@ + +# +# Copyright © 2009- The Spyder Development Team +# +# Licensed under the terms of the MIT License +# (see LICENSE.txt for details) + +from . import PYQT6, PYQT5,PythonQtError + +if PYQT6: + from PyQt6.sip import * +elif PYQT5: + from PyQt5.sip import * +else: + raise PythonQtError('No Qt bindings could be found') diff --git a/qtpy/tests/test_qtcore.py b/qtpy/tests/test_qtcore.py index e9b22ae7..2b434daf 100644 --- a/qtpy/tests/test_qtcore.py +++ b/qtpy/tests/test_qtcore.py @@ -1,5 +1,5 @@ import pytest -from qtpy import PYQT5, PYQT6, PYSIDE2, QtCore +from qtpy import PYQT5, PYQT6, PYSIDE2, PYQT_VERSION, QtCore """Test QtCore.""" @@ -25,3 +25,18 @@ class ClassWithSignal(QtCore.QObject): instance = ClassWithSignal() assert isinstance(instance.signal, QtCore.SignalInstance) + + +@pytest.mark.skipif(PYQT5 and PYQT_VERSION.startswith('5.9'), + reason="A specific setup with at least sip 4.9.9 is needed for PyQt5 5.9.*" + "to work with scoped enum access") +def test_enum_access(): + """ + Test scoped and unscoped enum access for qtpy.QtCore.*. + """ + assert QtCore.QAbstractAnimation.Stopped == QtCore.QAbstractAnimation.State.Stopped + assert QtCore.QEvent.ActionAdded == QtCore.QEvent.Type.ActionAdded + assert QtCore.Qt.AlignLeft == QtCore.Qt.AlignmentFlag.AlignLeft + assert QtCore.Qt.Key_Return == QtCore.Qt.Key.Key_Return + assert QtCore.Qt.transparent == QtCore.Qt.GlobalColor.transparent + assert QtCore.Qt.Widget == QtCore.Qt.WindowType.Widget diff --git a/qtpy/tests/test_qtgui.py b/qtpy/tests/test_qtgui.py new file mode 100644 index 00000000..d563e832 --- /dev/null +++ b/qtpy/tests/test_qtgui.py @@ -0,0 +1,33 @@ +"""Test QtGui.""" +import pytest + +from qtpy import PYQT5, PYQT_VERSION, QtGui + + +def test_qdrag_functions(): + """Test functions mapping for QtGui.QDrag.""" + assert QtGui.QDrag.exec_ + + +def test_qguiapplication_functions(): + """Test functions mapping for QtGui.QGuiApplication.""" + assert QtGui.QGuiApplication.exec_ + + +def test_qtextdocument_functions(): + """Test functions mapping for QtGui.QTextDocument.""" + assert QtGui.QTextDocument.print_ + + +@pytest.mark.skipif(PYQT5 and PYQT_VERSION.startswith('5.9'), + reason="A specific setup with at least sip 4.9.9 is needed for PyQt5 5.9.*" + "to work with scoped enum access") +def test_enum_access(): + """ + Test scoped and unscoped enum access for qtpy.QtWidgets.*. + """ + assert QtGui.QColor.Rgb == QtGui.QColor.Spec.Rgb + assert QtGui.QFont.AllUppercase == QtGui.QFont.Capitalization.AllUppercase + assert QtGui.QIcon.Normal == QtGui.QIcon.Mode.Normal + assert QtGui.QImage.Format_Invalid == QtGui.QImage.Format.Format_Invalid + \ No newline at end of file diff --git a/qtpy/tests/test_qtwidgets.py b/qtpy/tests/test_qtwidgets.py new file mode 100644 index 00000000..5432c93d --- /dev/null +++ b/qtpy/tests/test_qtwidgets.py @@ -0,0 +1,45 @@ +"""Test QtWidgets.""" +import pytest + +from qtpy import PYQT5, PYQT_VERSION, QtWidgets + + +def test_qtextedit_functions(): + """Test functions mapping for QtWidgets.QTextEdit.""" + assert QtWidgets.QTextEdit.setTabStopWidth + assert QtWidgets.QTextEdit.tabStopWidth + assert QtWidgets.QTextEdit.print_ + + +def test_qplaintextedit_functions(): + """Test functions mapping for QtWidgets.QPlainTextEdit.""" + assert QtWidgets.QPlainTextEdit.setTabStopWidth + assert QtWidgets.QPlainTextEdit.tabStopWidth + assert QtWidgets.QPlainTextEdit.print_ + + +def test_qapplication_functions(): + """Test functions mapping for QtWidgets.QApplication.""" + assert QtWidgets.QApplication.exec_ + + +def test_qdialog_functions(): + """Test functions mapping for QtWidgets.QDialog.""" + assert QtWidgets.QDialog.exec_ + + +def test_qmenu_functions(): + """Test functions mapping for QtWidgets.QDialog.""" + assert QtWidgets.QMenu.exec_ + + +@pytest.mark.skipif(PYQT5 and PYQT_VERSION.startswith('5.9'), + reason="A specific setup with at least sip 4.9.9 is needed for PyQt5 5.9.*" + "to work with scoped enum access") +def test_enum_access(): + """ + Test scoped and unscoped enum access for qtpy.QtWidgets.*. + """ + assert QtWidgets.QFileDialog.AcceptOpen == QtWidgets.QFileDialog.AcceptMode.AcceptOpen + assert QtWidgets.QMessageBox.InvalidRole == QtWidgets.QMessageBox.ButtonRole.InvalidRole + assert QtWidgets.QStyle.State_None == QtWidgets.QStyle.StateFlag.State_None \ No newline at end of file From 6d75a4ab0b275bdd75a7ffff059222ac59e179b5 Mon Sep 17 00:00:00 2001 From: dalthviz Date: Thu, 4 Nov 2021 13:35:20 -0500 Subject: [PATCH 2/9] PyQt6: Missing aliases for QtCore. Add comments for patches --- qtpy/QtCore.py | 10 ++++++++++ qtpy/QtGui.py | 4 ++++ qtpy/QtWidgets.py | 6 ++++++ 3 files changed, 20 insertions(+) diff --git a/qtpy/QtCore.py b/qtpy/QtCore.py index 322b87d0..98c25b03 100644 --- a/qtpy/QtCore.py +++ b/qtpy/QtCore.py @@ -15,10 +15,20 @@ from PyQt6 import QtCore from PyQt6.QtCore import * from PyQt6.QtCore import pyqtSignal as Signal + from PyQt6.QtCore import pyqtBoundSignal as SignalInstance + from PyQt6.QtCore import pyqtSlot as Slot + from PyQt5.QtCore import pyqtProperty as Property from PyQt6.QtCore import QT_VERSION_STR as __version__ + + # Map missing methods QCoreApplication.exec_ = QCoreApplication.exec QEventLoop.exec_ = QEventLoop.exec QThread.exec_ = QThread.exec + + # Those are imported from `import *` + del pyqtSignal, pyqtBoundSignal, pyqtSlot, pyqtProperty, QT_VERSION_STR + + # Allow unscoped access for enums inside the QtCore module from .enums_compat import promote_enums promote_enums(QtCore) elif PYQT5: diff --git a/qtpy/QtGui.py b/qtpy/QtGui.py index 9bc3ee94..ec861f7c 100644 --- a/qtpy/QtGui.py +++ b/qtpy/QtGui.py @@ -14,9 +14,13 @@ if PYQT6: from PyQt6 import QtGui from PyQt6.QtGui import * + + # Map missing/renamed methods QDrag.exec_ = QDrag.exec QGuiApplication.exec_ = QGuiApplication.exec QTextDocument.print_ = QTextDocument.print + + # Allow unscoped access for enums inside the QtGui module from .enums_compat import promote_enums promote_enums(QtGui) elif PYQT5: diff --git a/qtpy/QtWidgets.py b/qtpy/QtWidgets.py index be82b060..fee8ffb6 100644 --- a/qtpy/QtWidgets.py +++ b/qtpy/QtWidgets.py @@ -16,6 +16,8 @@ from PyQt6.QtWidgets import * from PyQt6.QtGui import QAction, QActionGroup, QShortcut from PyQt6.QtOpenGLWidgets import QOpenGLWidget + + # Map missing/renamed methods QTextEdit.setTabStopWidth = QTextEdit.setTabStopDistance QTextEdit.tabStopWidth = QTextEdit.tabStopDistance QTextEdit.print_ = QTextEdit.print @@ -25,6 +27,8 @@ QApplication.exec_ = QApplication.exec QDialog.exec_ = QDialog.exec QMenu.exec_ = QMenu.exec + + # Allow unscoped access for enums inside the QtWidgets module from .enums_compat import promote_enums promote_enums(QtWidgets) elif PYQT5: @@ -33,6 +37,8 @@ from PySide6.QtWidgets import * from PySide6.QtGui import QAction, QActionGroup, QShortcut from PySide6.QtOpenGLWidgets import QOpenGLWidget + + # Map missing/renamed methods QTextEdit.setTabStopWidth = QTextEdit.setTabStopDistance QTextEdit.tabStopWidth = QTextEdit.tabStopDistance QPlainTextEdit.setTabStopWidth = QPlainTextEdit.setTabStopDistance From dc86e18055181ca71b05febe3070636b7322b209 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Althviz=20Mor=C3=A9?= Date: Fri, 5 Nov 2021 10:27:23 -0500 Subject: [PATCH 3/9] PyQt6: Apply suggestions from code review for enum access Co-authored-by: CAM Gerlach --- qtpy/QtCore.py | 2 +- qtpy/enums_compat.py | 10 +++++----- qtpy/sip.py | 4 ++-- qtpy/tests/test_qtcore.py | 5 ++--- qtpy/tests/test_qtgui.py | 7 ++----- qtpy/tests/test_qtwidgets.py | 6 ++---- 6 files changed, 14 insertions(+), 20 deletions(-) diff --git a/qtpy/QtCore.py b/qtpy/QtCore.py index 98c25b03..3972ef6d 100644 --- a/qtpy/QtCore.py +++ b/qtpy/QtCore.py @@ -17,7 +17,7 @@ from PyQt6.QtCore import pyqtSignal as Signal from PyQt6.QtCore import pyqtBoundSignal as SignalInstance from PyQt6.QtCore import pyqtSlot as Slot - from PyQt5.QtCore import pyqtProperty as Property + from PyQt6.QtCore import pyqtProperty as Property from PyQt6.QtCore import QT_VERSION_STR as __version__ # Map missing methods diff --git a/qtpy/enums_compat.py b/qtpy/enums_compat.py index b0a52939..218acb6b 100644 --- a/qtpy/enums_compat.py +++ b/qtpy/enums_compat.py @@ -2,7 +2,7 @@ # Copyright © 2009- The Spyder Development Team # Licensed under the terms of the MIT License """ -Compatibility functions for scoped and unscoped enums access +Compatibility functions for scoped and unscoped enum access. """ from . import PYQT6 @@ -36,15 +36,15 @@ def promote_enums(module): Taken from: https://github.com/pyqtgraph/pyqtgraph/blob/pyqtgraph-0.12.1/pyqtgraph/Qt.py#L331-L377 """ - class_names = [x for x in dir(module) if x.startswith('Q')] + class_names = [name for name in dir(module) if name.startswith('Q')] for class_name in class_names: klass = getattr(module, class_name) if not isinstance(klass, sip.wrappertype): continue - attrib_names = [x for x in dir(klass) if x[0].isupper()] + attrib_names = [name for name in dir(klass) if name[0].isupper()] for attrib_name in attrib_names: attrib = getattr(klass, attrib_name) if not isinstance(attrib, enum.EnumMeta): continue - for e in attrib: - setattr(klass, e.name, e) \ No newline at end of file + for enum_obj in attrib: + setattr(klass, enum_obj.name, enum_obj) diff --git a/qtpy/sip.py b/qtpy/sip.py index b0237c8e..ffb1d334 100644 --- a/qtpy/sip.py +++ b/qtpy/sip.py @@ -1,4 +1,3 @@ - # # Copyright © 2009- The Spyder Development Team # @@ -12,4 +11,5 @@ elif PYQT5: from PyQt5.sip import * else: - raise PythonQtError('No Qt bindings could be found') + raise PythonQtError( + 'Currently selected Qt binding does not support this module') diff --git a/qtpy/tests/test_qtcore.py b/qtpy/tests/test_qtcore.py index 2b434daf..d8068a5b 100644 --- a/qtpy/tests/test_qtcore.py +++ b/qtpy/tests/test_qtcore.py @@ -1,4 +1,5 @@ import pytest + from qtpy import PYQT5, PYQT6, PYSIDE2, PYQT_VERSION, QtCore """Test QtCore.""" @@ -31,9 +32,7 @@ class ClassWithSignal(QtCore.QObject): reason="A specific setup with at least sip 4.9.9 is needed for PyQt5 5.9.*" "to work with scoped enum access") def test_enum_access(): - """ - Test scoped and unscoped enum access for qtpy.QtCore.*. - """ + """Test scoped and unscoped enum access for qtpy.QtCore.*.""" assert QtCore.QAbstractAnimation.Stopped == QtCore.QAbstractAnimation.State.Stopped assert QtCore.QEvent.ActionAdded == QtCore.QEvent.Type.ActionAdded assert QtCore.Qt.AlignLeft == QtCore.Qt.AlignmentFlag.AlignLeft diff --git a/qtpy/tests/test_qtgui.py b/qtpy/tests/test_qtgui.py index d563e832..09798955 100644 --- a/qtpy/tests/test_qtgui.py +++ b/qtpy/tests/test_qtgui.py @@ -23,11 +23,8 @@ def test_qtextdocument_functions(): reason="A specific setup with at least sip 4.9.9 is needed for PyQt5 5.9.*" "to work with scoped enum access") def test_enum_access(): - """ - Test scoped and unscoped enum access for qtpy.QtWidgets.*. - """ + """Test scoped and unscoped enum access for qtpy.QtWidgets.*.""" assert QtGui.QColor.Rgb == QtGui.QColor.Spec.Rgb assert QtGui.QFont.AllUppercase == QtGui.QFont.Capitalization.AllUppercase assert QtGui.QIcon.Normal == QtGui.QIcon.Mode.Normal - assert QtGui.QImage.Format_Invalid == QtGui.QImage.Format.Format_Invalid - \ No newline at end of file + assert QtGui.QImage.Format_Invalid == QtGui.QImage.Format.Format_Invalid \ No newline at end of file diff --git a/qtpy/tests/test_qtwidgets.py b/qtpy/tests/test_qtwidgets.py index 5432c93d..68e8192c 100644 --- a/qtpy/tests/test_qtwidgets.py +++ b/qtpy/tests/test_qtwidgets.py @@ -37,9 +37,7 @@ def test_qmenu_functions(): reason="A specific setup with at least sip 4.9.9 is needed for PyQt5 5.9.*" "to work with scoped enum access") def test_enum_access(): - """ - Test scoped and unscoped enum access for qtpy.QtWidgets.*. - """ + """Test scoped and unscoped enum access for qtpy.QtWidgets.*.""" assert QtWidgets.QFileDialog.AcceptOpen == QtWidgets.QFileDialog.AcceptMode.AcceptOpen assert QtWidgets.QMessageBox.InvalidRole == QtWidgets.QMessageBox.ButtonRole.InvalidRole - assert QtWidgets.QStyle.State_None == QtWidgets.QStyle.StateFlag.State_None \ No newline at end of file + assert QtWidgets.QStyle.State_None == QtWidgets.QStyle.StateFlag.State_None From 8ef3b5d2b12f6983e9846f129db1a948e1661a68 Mon Sep 17 00:00:00 2001 From: dalthviz Date: Fri, 5 Nov 2021 10:29:45 -0500 Subject: [PATCH 4/9] PyQt6: Remove unused promote_specific_enums function --- qtpy/enums_compat.py | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/qtpy/enums_compat.py b/qtpy/enums_compat.py index 218acb6b..220968db 100644 --- a/qtpy/enums_compat.py +++ b/qtpy/enums_compat.py @@ -12,23 +12,6 @@ from . import sip - def promote_specific_enums(base_class, enum_classes_list, inclusion_criteria): - """ - Allow access for the given enumeration classes values at base class level. - - Based on: - https://github.com/pyqtgraph/pyqtgraph/blob/pyqtgraph-0.12.1/pyqtgraph/Qt.py#L331-L377 - """ - for enum_class_name in enum_classes_list: - klass = getattr(base_class, enum_class_name) - attrib_names = [x for x in dir(klass) if inclusion_criteria(x)] - for attrib_name in attrib_names: - attrib = getattr(klass, attrib_name) - if not isinstance(attrib, (enum.Enum)): - continue - setattr(base_class, attrib.name, attrib) - - def promote_enums(module): """ Search enums in the given module and allow unscoped access. From 589d09c19708c4a39d8bcd62c4dffd2419696f08 Mon Sep 17 00:00:00 2001 From: dalthviz Date: Fri, 5 Nov 2021 10:48:02 -0500 Subject: [PATCH 5/9] PyQt6: Update copyright string --- qtpy/enums_compat.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/qtpy/enums_compat.py b/qtpy/enums_compat.py index 220968db..a8e71981 100644 --- a/qtpy/enums_compat.py +++ b/qtpy/enums_compat.py @@ -1,5 +1,9 @@ # # Copyright © 2009- The Spyder Development Team +# Copyright © 2012- University of North Carolina at Chapel Hill +# Luke Campagnola ('luke.campagnola@%s.com' % 'gmail') +# Ogi Moore ('ognyan.moore@%s.com' % 'gmail') +# KIU Shueng Chuan ('nixchuan@%s.com' % 'gmail') # Licensed under the terms of the MIT License """ Compatibility functions for scoped and unscoped enum access. From 8590108c50877084b2033e13d7c9128216f34328 Mon Sep 17 00:00:00 2001 From: dalthviz Date: Fri, 5 Nov 2021 12:38:32 -0500 Subject: [PATCH 6/9] Compat: Restore use of QFileDialog.ShowDirsOnly (unscoped enum access) --- qtpy/compat.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qtpy/compat.py b/qtpy/compat.py index 7494862f..dbac4396 100644 --- a/qtpy/compat.py +++ b/qtpy/compat.py @@ -51,7 +51,7 @@ def from_qvariant(qobj=None, pytype=None): # analysis:ignore # Wrappers around QFileDialog static methods # ============================================================================= def getexistingdirectory(parent=None, caption='', basedir='', - options=QFileDialog.Option.ShowDirsOnly): + options=QFileDialog.ShowDirsOnly): """Wrapper around QtGui.QFileDialog.getExistingDirectory static method Compatible with PyQt >=v4.4 (API #1 and #2) and PySide >=v1.0""" # Calling QFileDialog static method From bfa5cbfc642ddadef1d968cbaa46ac3ea79e9a6d Mon Sep 17 00:00:00 2001 From: dalthviz Date: Mon, 8 Nov 2021 12:57:40 -0500 Subject: [PATCH 7/9] PyQt6: Add missing map for QDateTime.toPython Co-authored-by: Talley Lambert --- qtpy/QtCore.py | 4 ++++ qtpy/tests/test_qtcore.py | 2 -- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/qtpy/QtCore.py b/qtpy/QtCore.py index 3972ef6d..e65d01f8 100644 --- a/qtpy/QtCore.py +++ b/qtpy/QtCore.py @@ -20,6 +20,10 @@ from PyQt6.QtCore import pyqtProperty as Property from PyQt6.QtCore import QT_VERSION_STR as __version__ + # For issue #153 + from PyQt6.QtCore import QDateTime + QDateTime.toPython = QDateTime.toPyDateTime + # Map missing methods QCoreApplication.exec_ = QCoreApplication.exec QEventLoop.exec_ = QEventLoop.exec diff --git a/qtpy/tests/test_qtcore.py b/qtpy/tests/test_qtcore.py index d8068a5b..423b2f2b 100644 --- a/qtpy/tests/test_qtcore.py +++ b/qtpy/tests/test_qtcore.py @@ -10,8 +10,6 @@ def test_qtmsghandler(): assert QtCore.qInstallMessageHandler is not None -@pytest.mark.skipif(not (PYQT5 or PYSIDE2), - reason="Targeted to PyQt5 or PySide2") def test_DateTime_toPython(): """Test QDateTime.toPython""" assert QtCore.QDateTime.toPython is not None From 61c34788765b547461bd321d3aaa2e00a9112ad8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Althviz=20Mor=C3=A9?= Date: Mon, 22 Nov 2021 10:05:20 -0500 Subject: [PATCH 8/9] PyQt6: Apply suggestions from code review for enum access Co-authored-by: Carlos Cordoba --- qtpy/enums_compat.py | 4 ++-- qtpy/sip.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/qtpy/enums_compat.py b/qtpy/enums_compat.py index a8e71981..1340fa36 100644 --- a/qtpy/enums_compat.py +++ b/qtpy/enums_compat.py @@ -1,13 +1,14 @@ -# # Copyright © 2009- The Spyder Development Team # Copyright © 2012- University of North Carolina at Chapel Hill # Luke Campagnola ('luke.campagnola@%s.com' % 'gmail') # Ogi Moore ('ognyan.moore@%s.com' % 'gmail') # KIU Shueng Chuan ('nixchuan@%s.com' % 'gmail') # Licensed under the terms of the MIT License + """ Compatibility functions for scoped and unscoped enum access. """ + from . import PYQT6 if PYQT6: @@ -15,7 +16,6 @@ from . import sip - def promote_enums(module): """ Search enums in the given module and allow unscoped access. diff --git a/qtpy/sip.py b/qtpy/sip.py index ffb1d334..64e71e66 100644 --- a/qtpy/sip.py +++ b/qtpy/sip.py @@ -4,7 +4,7 @@ # Licensed under the terms of the MIT License # (see LICENSE.txt for details) -from . import PYQT6, PYQT5,PythonQtError +from . import PYQT6, PYQT5, PythonQtError if PYQT6: from PyQt6.sip import * From b02425b2f884ccefaca25d904f5d61bae14756a4 Mon Sep 17 00:00:00 2001 From: dalthviz Date: Mon, 22 Nov 2021 10:18:34 -0500 Subject: [PATCH 9/9] PyQt6: Remove imported QtCore, QtGui and QtWidgets after promoting enums --- qtpy/QtCore.py | 1 + qtpy/QtGui.py | 1 + qtpy/QtWidgets.py | 1 + 3 files changed, 3 insertions(+) diff --git a/qtpy/QtCore.py b/qtpy/QtCore.py index e65d01f8..1a66d88e 100644 --- a/qtpy/QtCore.py +++ b/qtpy/QtCore.py @@ -35,6 +35,7 @@ # Allow unscoped access for enums inside the QtCore module from .enums_compat import promote_enums promote_enums(QtCore) + del QtCore elif PYQT5: from PyQt5.QtCore import * from PyQt5.QtCore import pyqtSignal as Signal diff --git a/qtpy/QtGui.py b/qtpy/QtGui.py index ec861f7c..62344572 100644 --- a/qtpy/QtGui.py +++ b/qtpy/QtGui.py @@ -23,6 +23,7 @@ # Allow unscoped access for enums inside the QtGui module from .enums_compat import promote_enums promote_enums(QtGui) + del QtGui elif PYQT5: from PyQt5.QtGui import * elif PYSIDE2: diff --git a/qtpy/QtWidgets.py b/qtpy/QtWidgets.py index fee8ffb6..2734e780 100644 --- a/qtpy/QtWidgets.py +++ b/qtpy/QtWidgets.py @@ -31,6 +31,7 @@ # Allow unscoped access for enums inside the QtWidgets module from .enums_compat import promote_enums promote_enums(QtWidgets) + del QtWidgets elif PYQT5: from PyQt5.QtWidgets import * elif PYSIDE6: