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

PR: Fix bug with environ handling #340

Merged
merged 5 commits into from
Apr 28, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 22 additions & 10 deletions qtpy/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,10 @@ class PythonQtWarning(Warning):
"""Warning if some features are not implemented in a binding."""


class PythonQtValueError(ValueError):
"""Error raised if an invalid QT_API is specified."""


# Qt API environment variable name
QT_API = 'QT_API'

Expand All @@ -98,14 +102,14 @@ class PythonQtWarning(Warning):
# Detecting if a binding was specified by the user
binding_specified = QT_API in os.environ

# Setting a default value for QT_API
os.environ.setdefault(QT_API, 'pyqt5')

API_NAMES = {'pyqt5': 'PyQt5', 'pyqt6': 'PyQt6',
'pyside2':'PySide2', 'pyside6': 'PySide6'}
API = os.environ[QT_API].lower()
'pyside2': 'PySide2', 'pyside6': 'PySide6'}
API = os.environ.get(QT_API, 'pyqt5').lower()
initial_api = API
assert API in API_NAMES
if API not in API_NAMES:
raise PythonQtValueError(
f'Specified QT_API={repr(QT_API.lower())} is not in valid options: '
f'{API_NAMES}')

is_old_pyqt = is_pyqt46 = False
QT5 = PYQT5 = True
Expand Down Expand Up @@ -150,7 +154,9 @@ class PythonQtWarning(Warning):

del macos_version
except ImportError:
API = os.environ['QT_API'] = 'pyqt6'
API = 'pyqt6'
ccordoba12 marked this conversation as resolved.
Show resolved Hide resolved
else:
os.environ[QT_API] = API

if API in PYQT6_API:
try:
Expand All @@ -161,7 +167,9 @@ class PythonQtWarning(Warning):
QT6 = PYQT6 = True

except ImportError:
API = os.environ['QT_API'] = 'pyside2'
API = 'pyside2'
ccordoba12 marked this conversation as resolved.
Show resolved Hide resolved
else:
os.environ[QT_API] = API


if API in PYSIDE2_API:
Expand All @@ -183,7 +191,9 @@ class PythonQtWarning(Warning):

del macos_version
except ImportError:
API = os.environ['QT_API'] = 'pyside6'
API = 'pyside6'
ccordoba12 marked this conversation as resolved.
Show resolved Hide resolved
else:
os.environ[QT_API] = API

if API in PYSIDE6_API:
try:
Expand All @@ -194,7 +204,9 @@ class PythonQtWarning(Warning):
QT6 = PYSIDE6 = True

except ImportError:
API = os.environ['QT_API'] = 'pyqt5'
API = 'pyqt5'
ccordoba12 marked this conversation as resolved.
Show resolved Hide resolved
else:
os.environ[QT_API] = API


# If a correct API name is passed to QT_API and it could not be found,
Expand Down
5 changes: 3 additions & 2 deletions qtpy/tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,9 @@ def pytest_report_header(config):
versions += 'PyQt6: '

try:
from PyQt6 import Qt
versions += f"PyQt: {Qt.PYQT_VERSION_STR} - Qt: {Qt.QT_VERSION_STR}"
from PyQt6 import QtCore
versions += \
f"PyQt: {QtCore.PYQT_VERSION_STR} - Qt: {QtCore.QT_VERSION_STR}"
dalthviz marked this conversation as resolved.
Show resolved Hide resolved
except ImportError:
versions += 'not installed'
except AttributeError:
Expand Down
47 changes: 46 additions & 1 deletion qtpy/tests/test_main.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import os
import sys
import subprocess

import pytest

from qtpy import QtCore, QtGui, QtWidgets, API_NAMES, PythonQtValueError

from qtpy import QtCore, QtGui, QtWidgets
try:
larsoner marked this conversation as resolved.
Show resolved Hide resolved
# removed in qt 6.0
from qtpy import QtWebEngineWidgets
Expand All @@ -16,6 +21,7 @@ def assert_pyside2():
assert QtGui.QPainter is PySide2.QtGui.QPainter
assert QtWidgets.QWidget is PySide2.QtWidgets.QWidget
assert QtWebEngineWidgets.QWebEnginePage is PySide2.QtWebEngineWidgets.QWebEnginePage
assert os.environ['QT_API'] == 'pyside2'

def assert_pyside6():
"""
Expand All @@ -27,6 +33,7 @@ def assert_pyside6():
assert QtWidgets.QWidget is PySide6.QtWidgets.QWidget
# Only valid for qt>=6.2
# assert QtWebEngineWidgets.QWebEnginePage is PySide6.QtWebEngineCore.QWebEnginePage
assert os.environ['QT_API'] == 'pyside6'

def assert_pyqt5():
"""
Expand All @@ -40,6 +47,7 @@ def assert_pyqt5():
assert QtWebEngineWidgets.QWebEnginePage is PyQt5.QtWebEngineWidgets.QWebEnginePage
else:
assert QtWebEngineWidgets.QWebEnginePage is PyQt5.QtWebKitWidgets.QWebPage
assert os.environ['QT_API'] == 'pyqt5'

def assert_pyqt6():
larsoner marked this conversation as resolved.
Show resolved Hide resolved
"""
Expand All @@ -49,6 +57,7 @@ def assert_pyqt6():
assert QtCore.QEvent is PyQt6.QtCore.QEvent
assert QtGui.QPainter is PyQt6.QtGui.QPainter
assert QtWidgets.QWidget is PyQt6.QtWidgets.QWidget
assert os.environ['QT_API'] == 'pyqt6'


def test_qt_api():
Expand Down Expand Up @@ -83,3 +92,39 @@ def test_qt_api():
assert_pyqt6()
else:
assert_pyqt5()


@pytest.mark.parametrize('api', API_NAMES.values())
def test_qt_api_environ(api):
"""
If no QT_API is specified but some Qt is imported, ensure QT_API is set properly.
"""
mod = f'{api}.QtCore'
pytest.importorskip(mod, reason=f'Requires {api}')
# clean env
env = os.environ.copy()
for key in ('QT_API', 'USE_QT_API'):
if key in env:
del env[key]
cmd = f"""
import {mod}
from qtpy import API
import os
print(API)
print(os.environ['QT_API'])
"""
output = subprocess.check_output([sys.executable, '-c', cmd], env=env)
got_api, env_qt_api = output.strip().decode('utf-8').splitlines()
assert got_api == api.lower()
assert env_qt_api == api.lower()
# Also ensure we raise a nice error
env['QT_API'] = 'bad'
cmd = """
try:
import qtpy
except ValueError as exc:
assert 'Specified QT_API' in str(exc), str(exc)
else:
raise AssertionError('QtPy imported despite bad QT_API')
"""
subprocess.check_call([sys.executable, '-Oc', cmd], env=env)