Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package python-pytest-qt for
openSUSE:Factory checked in at 2022-11-30 15:00:28
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-pytest-qt (Old)
and /work/SRC/openSUSE:Factory/.python-pytest-qt.new.1597 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-pytest-qt"
Wed Nov 30 15:00:28 2022 rev:10 rq:1039106 version:4.2.0
Changes:
--------
--- /work/SRC/openSUSE:Factory/python-pytest-qt/python-pytest-qt.changes
2022-07-05 12:10:24.388636554 +0200
+++
/work/SRC/openSUSE:Factory/.python-pytest-qt.new.1597/python-pytest-qt.changes
2022-11-30 15:01:21.669842828 +0100
@@ -1,0 +2,20 @@
+Wed Nov 30 12:26:35 UTC 2022 - Daniel Garcia <[email protected]>
+
+- Remove python_module macro definition
+- Update to 4.2.0:
+ * Import the code sub-package from the correct location rather than the
+ deprecated py package, restoring compatibility with pytest 7.2.0, where py
+ was dropped. Thanks @The-Compiler for the PR.
+ * Use pytest.hookimpl to configure hooks, avoiding a deprecation warning in
+ pytest 7.2.0. Thanks @The-Compiler for the PR.
+ * Now pytest-qt will check if any of the Qt libraries is already imported by
+ the time the plugin loads, and use it if that is the case (#412). Thanks
+ @eyllanesc for the PR.
+ * Most custom pytest-qt exceptions can be accessed via qtbot (for example
+ qtbot.TimeoutError), but it was not always explicit in the documentation
+ that this is the recommended way to access those exceptions, instead of
+ importing them from pytestqt.exceptions. This is now clarified in the
+ documentation and examples, and an alias to ScreenshotError has been added
+ to qtbot so it can be accessed in the same way (#460).
+
+-------------------------------------------------------------------
Old:
----
pytest-qt-4.1.0.tar.gz
New:
----
pytest-qt-4.2.0.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-pytest-qt.spec ++++++
--- /var/tmp/diff_new_pack.03lJer/_old 2022-11-30 15:01:22.117845457 +0100
+++ /var/tmp/diff_new_pack.03lJer/_new 2022-11-30 15:01:22.125845504 +0100
@@ -16,7 +16,6 @@
#
-%{?!python_module:%define python_module() python3-%{**}}
%define skip_python2 1
%global flavor @BUILD_FLAVOR@%{nil}
%if "%{flavor}" == ""
@@ -65,7 +64,7 @@
%endif
Name: python-pytest-qt%{psuffix}
-Version: 4.1.0
+Version: 4.2.0
Release: 0
Summary: Pytest support for PyQt and PySide applications
License: MIT
++++++ pytest-qt-4.1.0.tar.gz -> pytest-qt-4.2.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pytest-qt-4.1.0/.pre-commit-config.yaml
new/pytest-qt-4.2.0/.pre-commit-config.yaml
--- old/pytest-qt-4.1.0/.pre-commit-config.yaml 2022-06-23 16:39:11.000000000
+0200
+++ new/pytest-qt-4.2.0/.pre-commit-config.yaml 2022-10-25 17:01:03.000000000
+0200
@@ -1,6 +1,25 @@
repos:
+- repo: https://github.com/PyCQA/autoflake
+ rev: v1.7.6
+ hooks:
+ - id: autoflake
+ name: autoflake
+ args: ["--in-place", "--remove-unused-variables",
"--remove-all-unused-imports"]
+ language: python
+ files: \.py$
+- repo: https://github.com/pre-commit/pre-commit-hooks
+ rev: v4.3.0
+ hooks:
+ - id: trailing-whitespace
+ - id: end-of-file-fixer
+ - id: check-yaml
+ - id: debug-statements
+- repo: https://github.com/asottile/pyupgrade
+ rev: v3.1.0
+ hooks:
+ - id: pyupgrade
- repo: https://github.com/psf/black
- rev: 22.3.0
+ rev: 22.10.0
hooks:
- id: black
args: [--safe, --quiet]
@@ -11,19 +30,8 @@
- id: blacken-docs
additional_dependencies: [black==20.8b1]
language_version: python3
-- repo: https://github.com/pre-commit/pre-commit-hooks
- rev: v4.2.0
- hooks:
- - id: trailing-whitespace
- - id: end-of-file-fixer
- - id: check-yaml
- - id: debug-statements
-- repo: https://github.com/asottile/pyupgrade
- rev: v2.32.1
- hooks:
- - id: pyupgrade
- repo: https://github.com/PyCQA/flake8
- rev: 4.0.1
+ rev: 5.0.4
hooks:
- id: flake8
- repo: https://github.com/pre-commit/pygrep-hooks
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pytest-qt-4.1.0/CHANGELOG.rst
new/pytest-qt-4.2.0/CHANGELOG.rst
--- old/pytest-qt-4.1.0/CHANGELOG.rst 2022-06-23 16:39:11.000000000 +0200
+++ new/pytest-qt-4.2.0/CHANGELOG.rst 2022-10-25 17:01:03.000000000 +0200
@@ -1,5 +1,25 @@
-UNRELEASED
-----------
+4.2.0 (2022-10-25)
+------------------
+
+- Import the ``code`` sub-package from the correct location rather than the
+ deprecated ``py`` package, restoring compatibility with pytest 7.2.0, where
+ ``py`` was dropped. Thanks `@The-Compiler`_ for the PR.
+
+- Use ``pytest.hookimpl`` to configure hooks, avoiding a deprecation warning in
+ pytest 7.2.0. Thanks `@The-Compiler`_ for the PR.
+
+- Now ``pytest-qt`` will check if any of the Qt libraries is already imported
by the time the plugin loads,
+ and use it if that is the case (`#412`_). Thanks `@eyllanesc`_ for the PR.
+
+- Most custom ``pytest-qt`` exceptions can be accessed via ``qtbot`` (for
example ``qtbot.TimeoutError``),
+ but it was not always explicit in the documentation that this is the
recommended way to access those exceptions, instead
+ of importing them from ``pytestqt.exceptions``.
+ This is now clarified in the documentation and examples, and an alias to
``ScreenshotError`` has been
+ added to ``qtbot`` so it can be accessed in the same way (`#460`_).
+
+.. _#412: https://github.com/pytest-dev/pytest-qt/pull/412
+.. _#460: https://github.com/pytest-dev/pytest-qt/pull/460
+.. _@eyllanesc: https://github.com/eyllanesc
4.1.0 (2022-06-23)
------------------
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pytest-qt-4.1.0/PKG-INFO new/pytest-qt-4.2.0/PKG-INFO
--- old/pytest-qt-4.1.0/PKG-INFO 2022-06-23 16:39:27.000000000 +0200
+++ new/pytest-qt-4.2.0/PKG-INFO 2022-10-25 17:01:14.000000000 +0200
@@ -1,6 +1,6 @@
Metadata-Version: 2.1
Name: pytest-qt
-Version: 4.1.0
+Version: 4.2.0
Summary: pytest support for PyQt and PySide applications
Home-page: http://github.com/pytest-dev/pytest-qt
Author: Bruno Oliveira
@@ -104,9 +104,11 @@
Since version 4.1.0, ``pytest-qt`` requires Python 3.7+.
-Works with either PySide6_, PySide2_, PyQt6_ or PyQt5_, picking whichever
-is available on the system, giving preference to the first one installed in
-this order:
+Works with either PySide6_, PySide2_, PyQt6_ or PyQt5_.
+
+If any of the above libraries is already imported by the time the tests
execute, that library will be used.
+
+If not, pytest-qt will try to import and use the Qt APIs, in this order:
- ``PySide6``
- ``PySide2``
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pytest-qt-4.1.0/README.rst
new/pytest-qt-4.2.0/README.rst
--- old/pytest-qt-4.1.0/README.rst 2022-06-23 16:39:11.000000000 +0200
+++ new/pytest-qt-4.2.0/README.rst 2022-10-25 17:01:03.000000000 +0200
@@ -76,9 +76,11 @@
Since version 4.1.0, ``pytest-qt`` requires Python 3.7+.
-Works with either PySide6_, PySide2_, PyQt6_ or PyQt5_, picking whichever
-is available on the system, giving preference to the first one installed in
-this order:
+Works with either PySide6_, PySide2_, PyQt6_ or PyQt5_.
+
+If any of the above libraries is already imported by the time the tests
execute, that library will be used.
+
+If not, pytest-qt will try to import and use the Qt APIs, in this order:
- ``PySide6``
- ``PySide2``
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pytest-qt-4.1.0/docs/conf.py
new/pytest-qt-4.2.0/docs/conf.py
--- old/pytest-qt-4.1.0/docs/conf.py 2022-06-23 16:39:11.000000000 +0200
+++ new/pytest-qt-4.2.0/docs/conf.py 2022-10-25 17:01:03.000000000 +0200
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
#
# pytest-qt documentation build configuration file, created by
# sphinx-quickstart on Mon Mar 04 22:54:36 2013.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pytest-qt-4.1.0/docs/reference.rst
new/pytest-qt-4.2.0/docs/reference.rst
--- old/pytest-qt-4.1.0/docs/reference.rst 2022-06-23 16:39:11.000000000
+0200
+++ new/pytest-qt-4.2.0/docs/reference.rst 2022-10-25 17:01:03.000000000
+0200
@@ -12,6 +12,24 @@
.. autoclass:: TimeoutError
+ScreenshotError
+------------------
+
+.. autoclass:: ScreenshotError
+
+
+SignalEmittedError
+------------------
+
+.. autoclass:: SignalEmittedError
+
+
+CallbackCalledTwiceError
+------------------------
+
+.. autoclass:: CallbackCalledTwiceError
+
+
SignalBlocker
-------------
@@ -23,10 +41,6 @@
.. autoclass:: MultiSignalBlocker
-SignalEmittedError
-------------------
-
-.. autoclass:: SignalEmittedError
Record
------
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pytest-qt-4.1.0/docs/signals.rst
new/pytest-qt-4.2.0/docs/signals.rst
--- old/pytest-qt-4.1.0/docs/signals.rst 2022-06-23 16:39:11.000000000
+0200
+++ new/pytest-qt-4.2.0/docs/signals.rst 2022-10-25 17:01:03.000000000
+0200
@@ -21,7 +21,7 @@
app.worker.start()
# Test will block at this point until either the "finished" or the
# "failed" signal is emitted. If 10 seconds passed without a
signal,
- # TimeoutError will be raised.
+ # qtbot.TimeoutError will be raised.
assert_application_results(app)
@@ -34,7 +34,7 @@
.. versionchanged:: 2.0
You can pass ``raising=False`` to avoid raising a
-:class:`qtbot.TimeoutError <TimeoutError>` if the timeout is
+:class:`qtbot.TimeoutError <pytestqt.exceptions.TimeoutError>` if the timeout
is
reached before the signal is triggered:
.. code-block:: python
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pytest-qt-4.1.0/docs/troubleshooting.rst
new/pytest-qt-4.2.0/docs/troubleshooting.rst
--- old/pytest-qt-4.1.0/docs/troubleshooting.rst 2022-06-23
16:39:11.000000000 +0200
+++ new/pytest-qt-4.2.0/docs/troubleshooting.rst 2022-10-25
17:01:03.000000000 +0200
@@ -62,7 +62,7 @@
.. _issue #206: https://github.com/pytest-dev/pytest-qt/issues/206
GitHub Actions
-----------------
+--------------
When using ``ubuntu-latest`` on Github Actions, the package
``libxkbcommon-x11-0`` has to be installed, ``DISPLAY`` should be set and
``xvfb`` run. More details can be found in `issue #293`_.
@@ -70,7 +70,7 @@
Since Qt in version 5.15 ``xcb`` libraries are not distributed with Qt so this
library in version at least 1.11 on runner. See more in
https://codereview.qt-project.org/c/qt/qtbase/+/253905
-For Github Actions, Azure pipelines and Travis-CI you will need to install
``libxcb-icccm4 libxcb-image0 libxcb-keysyms1 libxcb-randr0 libxcb-render-util0
libxcb-xinerama0 libxcb-xfixes0``
+For Github Actions, Azure pipelines and Travis-CI you will need to install
``libxcb-icccm4 libxcb-image0 libxcb-keysyms1 libxcb-randr0 libxcb-render-util0
libxcb-xinerama0 libxcb-xfixes0 x11-utils``
As an example, here is a working config :
@@ -84,21 +84,25 @@
strategy:
matrix:
os : [ubuntu-latest]
- python: [3.7]
+ python: ["3.10"]
env:
DISPLAY: ':99.0'
steps:
- name: get repo
- uses: actions/checkout@v1
+ uses: actions/checkout@v3
- name: Set up Python
- uses: actions/setup-python@v1
+ uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python }}
- name: setup ${{ matrix.os }}
run: |
- sudo apt install libxkbcommon-x11-0 libxcb-icccm4 libxcb-image0
libxcb-keysyms1 libxcb-randr0 libxcb-render-util0 libxcb-xinerama0
libxcb-xfixes0
+ sudo apt install libxkbcommon-x11-0 libxcb-icccm4 libxcb-image0
libxcb-keysyms1 libxcb-randr0 libxcb-render-util0 libxcb-xinerama0
libxcb-xfixes0 x11-utils
/sbin/start-stop-daemon --start --quiet --pidfile
/tmp/custom_xvfb_99.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :99
-screen 0 1920x1200x24 -ac +extension GLX
+``tlambert03/setup-qt-libs``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Instead manually curate list of used packages you may use
``tlambert03/setup-qt-libs`` github action:
https://github.com/tlambert03/setup-qt-libs
+
pytest-xvfb
~~~~~~~~~~~
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pytest-qt-4.1.0/docs/wait_callback.rst
new/pytest-qt-4.2.0/docs/wait_callback.rst
--- old/pytest-qt-4.1.0/docs/wait_callback.rst 2022-06-23 16:39:11.000000000
+0200
+++ new/pytest-qt-4.2.0/docs/wait_callback.rst 2022-10-25 17:01:03.000000000
+0200
@@ -25,8 +25,8 @@
Anything following the ``with`` block will be run only after the callback has
been called.
If the callback doesn't get called during the given timeout,
-:class:`qtbot.TimeoutError <TimeoutError>` is raised. If it is called more
than once,
-:class:`qtbot.CallbackCalledTwiceError <CallbackCalledTwiceError>` is raised.
+:class:`qtbot.TimeoutError <pytestqt.exceptions.TimeoutError>` is raised. If
it is called more than once,
+:class:`qtbot.CallbackCalledTwiceError
<pytestqt.wait_signal.CallbackCalledTwiceError>` is raised.
raising parameter
-----------------
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pytest-qt-4.1.0/docs/wait_until.rst
new/pytest-qt-4.2.0/docs/wait_until.rst
--- old/pytest-qt-4.1.0/docs/wait_until.rst 2022-06-23 16:39:11.000000000
+0200
+++ new/pytest-qt-4.2.0/docs/wait_until.rst 2022-10-25 17:01:03.000000000
+0200
@@ -46,7 +46,7 @@
``qtbot.waitUntil`` will periodically call ``check_label`` until it no longer
raises
``AssertionError`` or a timeout is reached. If a timeout is reached, a
-:class:`qtbot.TimeoutError <TimeoutError>`
+:class:`qtbot.TimeoutError <pytestqt.exceptions.TimeoutError>`
is raised from the last assertion error and the test will fail:
::
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pytest-qt-4.1.0/src/pytest_qt.egg-info/PKG-INFO
new/pytest-qt-4.2.0/src/pytest_qt.egg-info/PKG-INFO
--- old/pytest-qt-4.1.0/src/pytest_qt.egg-info/PKG-INFO 2022-06-23
16:39:26.000000000 +0200
+++ new/pytest-qt-4.2.0/src/pytest_qt.egg-info/PKG-INFO 2022-10-25
17:01:14.000000000 +0200
@@ -1,6 +1,6 @@
Metadata-Version: 2.1
Name: pytest-qt
-Version: 4.1.0
+Version: 4.2.0
Summary: pytest support for PyQt and PySide applications
Home-page: http://github.com/pytest-dev/pytest-qt
Author: Bruno Oliveira
@@ -104,9 +104,11 @@
Since version 4.1.0, ``pytest-qt`` requires Python 3.7+.
-Works with either PySide6_, PySide2_, PyQt6_ or PyQt5_, picking whichever
-is available on the system, giving preference to the first one installed in
-this order:
+Works with either PySide6_, PySide2_, PyQt6_ or PyQt5_.
+
+If any of the above libraries is already imported by the time the tests
execute, that library will be used.
+
+If not, pytest-qt will try to import and use the Qt APIs, in this order:
- ``PySide6``
- ``PySide2``
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pytest-qt-4.1.0/src/pytestqt/_version.py
new/pytest-qt-4.2.0/src/pytestqt/_version.py
--- old/pytest-qt-4.1.0/src/pytestqt/_version.py 2022-06-23
16:39:25.000000000 +0200
+++ new/pytest-qt-4.2.0/src/pytestqt/_version.py 2022-10-25
17:01:14.000000000 +0200
@@ -1,5 +1,5 @@
# coding: utf-8
# file generated by setuptools_scm
# don't change, don't track in version control
-__version__ = version = '4.1.0'
-__version_tuple__ = version_tuple = (4, 1, 0)
+__version__ = version = '4.2.0'
+__version_tuple__ = version_tuple = (4, 2, 0)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pytest-qt-4.1.0/src/pytestqt/exceptions.py
new/pytest-qt-4.2.0/src/pytestqt/exceptions.py
--- old/pytest-qt-4.1.0/src/pytestqt/exceptions.py 2022-06-23
16:39:11.000000000 +0200
+++ new/pytest-qt-4.2.0/src/pytestqt/exceptions.py 2022-10-25
17:01:03.000000000 +0200
@@ -98,17 +98,19 @@
.. versionadded:: 2.1
Exception thrown by :class:`pytestqt.qtbot.QtBot` methods.
- """
- pass
+ Access via ``qtbot.TimeoutError``.
+ """
class ScreenshotError(Exception):
"""
.. versionadded:: 4.1
- Exception thrown by :method:`pytestqt.qtbot.QtBot.screenshot` if taking the
+ Exception thrown by :meth:`pytestqt.qtbot.QtBot.screenshot` if taking the
screenshot failed.
- """
- pass
+ .. versionchanged:: 4.2
+
+ Access via ``qtbot.ScreenshotError``.
+ """
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pytest-qt-4.1.0/src/pytestqt/logging.py
new/pytest-qt-4.2.0/src/pytestqt/logging.py
--- old/pytest-qt-4.1.0/src/pytestqt/logging.py 2022-06-23 16:39:11.000000000
+0200
+++ new/pytest-qt-4.2.0/src/pytestqt/logging.py 2022-10-25 17:01:03.000000000
+0200
@@ -2,7 +2,7 @@
from contextlib import contextmanager
import datetime
import re
-from py._code.code import TerminalRepr, ReprFileLocation
+from _pytest._code.code import TerminalRepr, ReprFileLocation
import pytest
from pytestqt.qt_compat import qt_api
from pytestqt.utils import get_marker
@@ -39,7 +39,7 @@
item.qt_log_capture = _QtMessageCapture(ignore_regexes)
item.qt_log_capture._start()
- @pytest.mark.hookwrapper
+ @pytest.hookimpl(hookwrapper=True)
def pytest_runtest_makereport(self, item, call):
"""Add captured Qt messages to test item report if the call failed."""
outcome = yield
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pytest-qt-4.1.0/src/pytestqt/plugin.py
new/pytest-qt-4.2.0/src/pytestqt/plugin.py
--- old/pytest-qt-4.1.0/src/pytestqt/plugin.py 2022-06-23 16:39:11.000000000
+0200
+++ new/pytest-qt-4.2.0/src/pytestqt/plugin.py 2022-10-25 17:01:03.000000000
+0200
@@ -157,8 +157,7 @@
)
[email protected]
[email protected]
[email protected](hookwrapper=True, tryfirst=True)
def pytest_runtest_setup(item):
"""
Hook called after before test setup starts, to start capturing exceptions
@@ -174,8 +173,7 @@
item.qt_exception_capture_manager.fail_if_exceptions_occurred("SETUP")
[email protected]
[email protected]
[email protected](hookwrapper=True, tryfirst=True)
def pytest_runtest_call(item):
yield
_process_events()
@@ -184,8 +182,7 @@
item.qt_exception_capture_manager.fail_if_exceptions_occurred("CALL")
[email protected]
[email protected]
[email protected](hookwrapper=True, trylast=True)
def pytest_runtest_teardown(item):
"""
Hook called after each test tear down, to process any pending events and
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pytest-qt-4.1.0/src/pytestqt/qt_compat.py
new/pytest-qt-4.2.0/src/pytestqt/qt_compat.py
--- old/pytest-qt-4.1.0/src/pytestqt/qt_compat.py 2022-06-23
16:39:11.000000000 +0200
+++ new/pytest-qt-4.2.0/src/pytestqt/qt_compat.py 2022-10-25
17:01:03.000000000 +0200
@@ -1,6 +1,6 @@
"""
Provide a common way to import Qt classes used by pytest-qt in a unique manner,
-abstracting API differences between PyQt5 and PySide2/6.
+abstracting API differences between PyQt5/6 and PySide2/6.
.. note:: This module is not part of pytest-qt public API, hence its interface
may change between releases and users should not rely on it.
@@ -9,20 +9,31 @@
"""
-from collections import namedtuple
+from collections import namedtuple, OrderedDict
import os
+import sys
import pytest
VersionTuple = namedtuple("VersionTuple", "qt_api, qt_api_version, runtime,
compiled")
+QT_APIS = OrderedDict()
+QT_APIS["pyside6"] = "PySide6"
+QT_APIS["pyside2"] = "PySide2"
+QT_APIS["pyqt6"] = "PyQt6"
+QT_APIS["pyqt5"] = "PyQt5"
+
def _import(name):
"""Think call so we can mock it during testing"""
return __import__(name)
+def _is_library_loaded(name):
+ return name in sys.modules
+
+
class _QtApi:
"""
Interface to the underlying Qt API currently configured for pytest-qt.
@@ -36,12 +47,7 @@
def _get_qt_api_from_env(self):
api = os.environ.get("PYTEST_QT_API")
- supported_apis = [
- "pyside6",
- "pyside2",
- "pyqt6",
- "pyqt5",
- ]
+ supported_apis = QT_APIS.keys()
if api is not None:
api = api.lower()
@@ -50,6 +56,12 @@
raise pytest.UsageError(msg)
return api
+ def _get_already_loaded_backend(self):
+ for api, backend in QT_APIS.items():
+ if _is_library_loaded(backend):
+ return api
+ return None
+
def _guess_qt_api(self): # pragma: no cover
def _can_import(name):
try:
@@ -61,18 +73,18 @@
# Note, not importing only the root namespace because when
uninstalling from conda,
# the namespace can still be there.
- if _can_import("PySide6.QtCore"):
- return "pyside6"
- elif _can_import("PySide2.QtCore"):
- return "pyside2"
- elif _can_import("PyQt6.QtCore"):
- return "pyqt6"
- elif _can_import("PyQt5.QtCore"):
- return "pyqt5"
+ for api, backend in QT_APIS.items():
+ if _can_import(f"{backend}.QtCore"):
+ return api
return None
def set_qt_api(self, api):
- self.pytest_qt_api = self._get_qt_api_from_env() or api or
self._guess_qt_api()
+ self.pytest_qt_api = (
+ self._get_qt_api_from_env()
+ or api
+ or self._get_already_loaded_backend()
+ or self._guess_qt_api()
+ )
self.is_pyside = self.pytest_qt_api in ["pyside2", "pyside6"]
self.is_pyqt = self.pytest_qt_api in ["pyqt5", "pyqt6"]
@@ -88,13 +100,7 @@
)
raise pytest.UsageError(msg)
- _root_modules = {
- "pyside6": "PySide6",
- "pyside2": "PySide2",
- "pyqt6": "PyQt6",
- "pyqt5": "PyQt5",
- }
- _root_module = _root_modules[self.pytest_qt_api]
+ _root_module = QT_APIS[self.pytest_qt_api]
def _import_module(module_name):
m = __import__(_root_module, globals(), locals(), [module_name], 0)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pytest-qt-4.1.0/src/pytestqt/qtbot.py
new/pytest-qt-4.2.0/src/pytestqt/qtbot.py
--- old/pytest-qt-4.1.0/src/pytestqt/qtbot.py 2022-06-23 16:39:11.000000000
+0200
+++ new/pytest-qt-4.2.0/src/pytestqt/qtbot.py 2022-10-25 17:01:03.000000000
+0200
@@ -182,7 +182,8 @@
def waitActive(self, widget, *, timeout=5000):
"""
Context manager that waits for ``timeout`` milliseconds or until the
window is active.
- If window is not exposed within ``timeout`` milliseconds, raise
``TimeoutError``.
+ If window is not exposed within ``timeout`` milliseconds, raise
+ :class:`qtbot.TimeoutError <pytestqt.exceptions.TimeoutError>`
This is mainly useful for asynchronous systems like X11, where a
window will be mapped to screen
some time after being asked to show itself on the screen.
@@ -208,7 +209,8 @@
def waitExposed(self, widget, *, timeout=5000):
"""
Context manager that waits for ``timeout`` milliseconds or until the
window is exposed.
- If the window is not exposed within ``timeout`` milliseconds, raise
``TimeoutError``.
+ If the window is not exposed within ``timeout`` milliseconds, raise
+ :class:`qtbot.TimeoutError <pytestqt.exceptions.TimeoutError>`
This is mainly useful for asynchronous systems like X11, where a
window will be mapped to screen
some time after being asked to show itself on the screen.
@@ -238,10 +240,11 @@
show itself on the screen.
.. warning::
- This method does **not** raise ``TimeoutError`` if the window
wasn't shown.
+ This method does **not** raise :class:`qtbot.TimeoutError
<pytestqt.exceptions.TimeoutError>` if
+ the window wasn't shown.
.. deprecated:: 4.0
- Use the qtbot.waitForWindowExposed context manager instead.
+ Use the ``qtbot.waitExposed`` context manager instead.
:param QWidget widget:
Widget to wait on.
@@ -255,7 +258,7 @@
warnings.warn(
"waitForWindowShown is deprecated, as the underlying Qt method was
"
"obsoleted in Qt 5.0 and removed in Qt 6.0. Its name is imprecise
and "
- "the pytest-qt wrapper does not raise TimeoutError if the window "
+ "the pytest-qt wrapper does not raise qtbot.TimeoutError if the
window "
"wasn't shown. Please use the qtbot.waitExposed context manager "
"instead.",
DeprecationWarning,
@@ -315,11 +318,11 @@
:param Signal signal:
A signal to wait for, or a tuple ``(signal, signal_name_as_str)``
to improve the error message that is part
- of ``TimeoutError``.
+ of :class:`qtbot.TimeoutError <pytestqt.exceptions.TimeoutError>`.
:param int timeout:
How many milliseconds to wait before resuming control flow.
:param bool raising:
- If :class:`QtBot.TimeoutError <pytestqt.plugin.TimeoutError>`
+ If :class:`qtbot.TimeoutError <pytestqt.exceptions.TimeoutError>`
should be raised if a timeout occurred.
This defaults to ``True`` unless ``qt_default_raising = false``
is set in the config.
@@ -376,11 +379,11 @@
:param list signals:
A list of :class:`Signal` objects to wait for. Alternatively: a
list of (``Signal, str``) tuples of the form
- ``(signal, signal_name_as_str)`` to improve the error message that
is part of ``TimeoutError``.
+ ``(signal, signal_name_as_str)`` to improve the error message that
is part of ``qtbot.TimeoutError``.
:param int timeout:
How many milliseconds to wait before resuming control flow.
:param bool raising:
- If :class:`QtBot.TimeoutError <pytestqt.plugin.TimeoutError>`
+ If :class:`qtbot.TimeoutError <pytestqt.exceptions.TimeoutError>`
should be raised if a timeout occurred.
This defaults to ``True`` unless ``qt_default_raising = false``
is set in the config.
@@ -566,7 +569,7 @@
:param int timeout:
How many milliseconds to wait before resuming control flow.
:param bool raising:
- If :class:`QtBot.TimeoutError <pytestqt.plugin.TimeoutError>`
+ If :class:`qtbot.TimeoutError <pytestqt.exceptions.TimeoutError>`
should be raised if a timeout occurred.
This defaults to ``True`` unless ``qt_default_raising = false``
is set in the config.
@@ -616,6 +619,9 @@
``objectName()`` of the widget if set, as well as its class name. A
custom
``suffix`` can be given to add to the generated name.
+ Raises :class:`qtbot.ScreenshotError
<pytestqt.exceptions.ScreenshotError>`
+ if taking the screenshot or saving the file failed.
+
:param QWidget widget:
The widget to take a screenshot of.
:param str suffix:
@@ -625,7 +631,6 @@
contained.
:returns:
A ``pathlib.Path`` object with the taken screenshot.
- :raises ScreenshotError: if taking the screenshot or saving the file
failed.
"""
pixmap = widget.grab() if region is None else widget.grab(region)
if pixmap.isNull():
@@ -711,6 +716,7 @@
# provide easy access to exceptions to qtbot fixtures
QtBot.SignalEmittedError = SignalEmittedError
QtBot.TimeoutError = TimeoutError
+QtBot.ScreenshotError = ScreenshotError
QtBot.CallbackCalledTwiceError = CallbackCalledTwiceError
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pytest-qt-4.1.0/src/pytestqt/wait_signal.py
new/pytest-qt-4.2.0/src/pytestqt/wait_signal.py
--- old/pytest-qt-4.1.0/src/pytestqt/wait_signal.py 2022-06-23
16:39:11.000000000 +0200
+++ new/pytest-qt-4.2.0/src/pytestqt/wait_signal.py 2022-10-25
17:01:03.000000000 +0200
@@ -164,7 +164,8 @@
this is set to ``None``.
:ivar bool raising:
- If :class:`TimeoutError` should be raised if a timeout occurred.
+ If :class:`qtbot.TimeoutError <pytestqt.exceptions.TimeoutError>`
should be raised
+ if a timeout occurred.
.. note:: contrary to the parameter of same name in
:meth:`pytestqt.qtbot.QtBot.waitSignal`, this parameter does not
@@ -626,7 +627,8 @@
:ivar int timeout: maximum time to wait for the callback to be called.
:ivar bool raising:
- If :class:`TimeoutError` should be raised if a timeout occurred.
+ If :class:`qtbot.TimeoutError <pytestqt.exceptions.TimeoutError>`
should be raised if
+ a timeout occurred.
.. note:: contrary to the parameter of same name in
:meth:`pytestqt.qtbot.QtBot.waitCallback`, this parameter does not
@@ -722,8 +724,6 @@
signal was emitted unexpectedly.
"""
- pass
-
class CallbackCalledTwiceError(Exception):
"""
@@ -733,8 +733,6 @@
callback was called twice.
"""
- pass
-
def _silent_disconnect(signal, slot):
"""Disconnects a signal from a slot, ignoring errors. Sometimes
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pytest-qt-4.1.0/tests/test_basics.py
new/pytest-qt-4.2.0/tests/test_basics.py
--- old/pytest-qt-4.1.0/tests/test_basics.py 2022-06-23 16:39:11.000000000
+0200
+++ new/pytest-qt-4.2.0/tests/test_basics.py 2022-10-25 17:01:03.000000000
+0200
@@ -563,8 +563,12 @@
def _fake_import(name, *args):
raise ModuleNotFoundError(f"Failed to import {name}")
+ def _fake_is_library_loaded(name, *args):
+ return False
+
monkeypatch.delenv("PYTEST_QT_API", raising=False)
monkeypatch.setattr(qt_compat, "_import", _fake_import)
+ monkeypatch.setattr(qt_compat, "_is_library_loaded",
_fake_is_library_loaded)
expected = (
"pytest-qt requires either PySide2, PySide6, PyQt5 or PyQt6
installed.\n"
@@ -578,6 +582,73 @@
qt_api.set_qt_api(api=None)
[email protected](
+ "option_api, backend",
+ [
+ ("pyqt5", "PyQt5"),
+ ("pyqt6", "PyQt6"),
+ ("pyside2", "PySide2"),
+ ("pyside6", "PySide6"),
+ ],
+)
+def test_already_loaded_backend(monkeypatch, option_api, backend):
+
+ import builtins
+
+ class Mock:
+ pass
+
+ qtcore = Mock()
+ for method_name in (
+ "qInstallMessageHandler",
+ "qDebug",
+ "qWarning",
+ "qCritical",
+ "qFatal",
+ ):
+ setattr(qtcore, method_name, lambda *_: None)
+
+ if backend in ("PyQt5", "PyQt6"):
+ pyqt_version = 0x050B00 if backend == "PyQt5" else 0x060000
+ qtcore.PYQT_VERSION = pyqt_version + 1
+ qtcore.pyqtSignal = object()
+ qtcore.pyqtSlot = object()
+ qtcore.pyqtProperty = object()
+ else:
+ qtcore.Signal = object()
+ qtcore.Slot = object()
+ qtcore.Property = object()
+
+ qtwidgets = Mock()
+ qapplication = Mock()
+ qapplication.instance = lambda *_: None
+ qtwidgets.QApplication = qapplication
+
+ qbackend = Mock()
+ qbackend.QtCore = qtcore
+ qbackend.QtGui = object()
+ qbackend.QtTest = object()
+ qbackend.QtWidgets = qtwidgets
+
+ import_orig = builtins.__import__
+
+ def _fake_import(name, *args, **kwargs):
+ if name == backend:
+ return qbackend
+ return import_orig(name, *args, **kwargs)
+
+ def _fake_is_library_loaded(name, *args):
+ return name == backend
+
+ monkeypatch.delenv("PYTEST_QT_API", raising=False)
+ monkeypatch.setattr(qt_compat, "_is_library_loaded",
_fake_is_library_loaded)
+ monkeypatch.setattr(builtins, "__import__", _fake_import)
+
+ qt_api.set_qt_api(api=None)
+
+ assert qt_api.pytest_qt_api == option_api
+
+
def test_before_close_func(testdir):
"""
Test the `before_close_func` argument of qtbot.addWidget.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pytest-qt-4.1.0/tests/test_logging.py
new/pytest-qt-4.2.0/tests/test_logging.py
--- old/pytest-qt-4.1.0/tests/test_logging.py 2022-06-23 16:39:11.000000000
+0200
+++ new/pytest-qt-4.2.0/tests/test_logging.py 2022-10-25 17:01:03.000000000
+0200
@@ -541,7 +541,7 @@
conftest="""
import pytest
- @pytest.mark.hookwrapper(tryfirst=True)
+ @pytest.hookimpl(hookwrapper=True, tryfirst=True)
def pytest_runtest_makereport(call):
if call.when == 'call':
raise Exception("This should not be hidden")
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pytest-qt-4.1.0/tests/test_modeltest.py
new/pytest-qt-4.2.0/tests/test_modeltest.py
--- old/pytest-qt-4.1.0/tests/test_modeltest.py 2022-06-23 16:39:11.000000000
+0200
+++ new/pytest-qt-4.2.0/tests/test_modeltest.py 2022-10-25 17:01:03.000000000
+0200
@@ -267,7 +267,6 @@
def test_nop(qtmodeltester):
"""We should not get a crash on cleanup with no model."""
- pass
def test_overridden_methods(qtmodeltester):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pytest-qt-4.1.0/tests/test_screenshot.py
new/pytest-qt-4.2.0/tests/test_screenshot.py
--- old/pytest-qt-4.1.0/tests/test_screenshot.py 2022-06-23
16:39:11.000000000 +0200
+++ new/pytest-qt-4.2.0/tests/test_screenshot.py 2022-10-25
17:01:03.000000000 +0200
@@ -3,7 +3,6 @@
import pytest
from pytestqt.qt_compat import qt_api
-from pytestqt.exceptions import ScreenshotError
@pytest.fixture
@@ -60,12 +59,12 @@
def test_filename_endless(qtbot, widget, monkeypatch):
monkeypatch.setattr(pathlib.Path, "exists", lambda _self: True)
- with pytest.raises(ScreenshotError, match="Failed to find unique
filename"):
+ with pytest.raises(qtbot.ScreenshotError, match="Failed to find unique
filename"):
qtbot.screenshot(widget, suffix="before")
def test_filename_invalid(qtbot, widget):
- with pytest.raises(ScreenshotError, match="Saving to .* failed"):
+ with pytest.raises(qtbot.ScreenshotError, match="Saving to .* failed"):
qtbot.screenshot(widget, suffix=r"invalid/path\everywhere")
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pytest-qt-4.1.0/tests/test_wait_until.py
new/pytest-qt-4.2.0/tests/test_wait_until.py
--- old/pytest-qt-4.1.0/tests/test_wait_until.py 2022-06-23
16:39:11.000000000 +0200
+++ new/pytest-qt-4.2.0/tests/test_wait_until.py 2022-10-25
17:01:03.000000000 +0200
@@ -1,7 +1,5 @@
import pytest
-from pytestqt.exceptions import TimeoutError
-
def test_wait_until(qtbot, wait_4_ticks_callback, tick_counter):
tick_counter.start(100)
@@ -11,7 +9,7 @@
def test_wait_until_timeout(qtbot, wait_4_ticks_callback, tick_counter):
tick_counter.start(200)
- with pytest.raises(TimeoutError):
+ with pytest.raises(qtbot.TimeoutError):
qtbot.waitUntil(wait_4_ticks_callback, timeout=100)
assert tick_counter.ticks < 4