qts - use the Qt you’ve got¶
Resources¶
Introduction¶
Note
qts is presently an exploratory project. It does have test coverage and is significantly documented. It only covers a few Qt modules.
qts is a Qt5/6 and PyQt/PySide compatibility layer for your libraries and applications. It is designed to work with mypy and includes a CLI utility to notify mypy of the needed conditions. To keep the scope reasonable, qts will focus on the variances that all code using Qt will need such as imports and signals. Nuanced detailed differences will not be abstracted away. Helper functions and similar may be provided on a case by case basis.
import qts
import qts.util
def main():
qts.set_wrapper(qts.available_wrappers()[0])
from qts import QtWidgets
application = QtWidgets.QApplication([])
widget = QtWidgets.QLabel("this is qts")
widget.show()
qts.util.exec(application)
main()
qts¶
The top level package exposes the basic functionality of the qts library.
Selecting a wrapper¶
A Qt wrapper must be chosen before leveraging the qts compatibility features.
qts is notified of the choice by a call to qts.set_wrapper()
.
- qts.set_wrapper(wrapper: qts._core.Wrapper) → None[source]¶
Set the wrapper you want to back the Qt modules accessed through qts.
- Raises
qts.WrapperAlreadySelectedError – When called and a wrapper has already been set.
qts.InvalidWrapperError – When called with an invalid wrapper.
Supported wrappers¶
The objects representing the supported wrappers are directly available.
Each is an instance of the qts.Wrapper
class.
The full list of supported wrappers is available as qts._core.supported_wrappers
.
- qts._core.pyqt_5_wrapper = Wrapper(family='PyQt', name='PyQt5', major_version=5, module_name='PyQt5')¶
The PyQt/Qt5 wrapper object.
- qts._core.pyqt_6_wrapper = Wrapper(family='PyQt', name='PyQt6', major_version=6, module_name='PyQt6')¶
The PyQt/Qt6 wrapper object.
- qts._core.pyside_5_wrapper = Wrapper(family='PySide', name='PySide2', major_version=5, module_name='PySide2')¶
The PySide/Qt5 wrapper object.
- qts._core.pyside_6_wrapper = Wrapper(family='PySide', name='PySide6', major_version=6, module_name='PySide6')¶
The PySide/Qt6 wrapper object.
- qts._core.supported_wrappers = [Wrapper(family='PyQt', name='PyQt5', major_version=5, module_name='PyQt5'), Wrapper(family='PyQt', name='PyQt6', major_version=6, module_name='PyQt6'), Wrapper(family='PySide', name='PySide2', major_version=5, module_name='PySide2'), Wrapper(family='PySide', name='PySide6', major_version=6, module_name='PySide6')]¶
A list of all the supported wrapper objects.
- class qts.Wrapper(family: str, name: str, major_version: int, module_name: str)[source]¶
Bases:
object
A representation of a specific wrapper that can be used to access a specific version of Qt.
- family¶
The wrapper family.
"PyQt"
or"PySide"
.
- name¶
The name of the specific wrapper, including the version number. Such as
"PySide6"
.
- major_version¶
The major version of the wrapped Qt library. Such as
6
.
- module_name¶
The name used to import the module. Such as
"PySide6"
.
Available wrappers¶
Not all supported wrappers will be available in every case.
- qts.available_wrapper(wrappers: Optional[Iterable[qts._core.Wrapper]] = None) → qts._core.Wrapper[source]¶
Get the available wrapper when there is only one.
- Returns
The wrapper object for the single available wrapper.
- Raises
qts.NoWrapperAvailableError – When no wrappers are available.
qts.MultipleWrappersAvailableError – If more than one wrapper is available.
- qts.available_wrappers(wrappers: Optional[Iterable[qts._core.Wrapper]] = None) → Sequence[qts._core.Wrapper][source]¶
Get a sequence of the wrappers that are available for use. If
wrappers
is passed, only wrappers that are both available and in the passed iterable will be returned.- Returns
The wrappers that are installed and available for use.
- qts.wrapper_by_name(name: str) → qts._core.Wrapper[source]¶
Get a wrapper object by its name. The name is checked case insensitively.
- Returns
The wrapper that goes by the passed name.
Present configuration¶
You can directly query the present wrapper object multiple ways.
The wrapper object can be retrieved directly through qts.wrapper
.
In some cases it is more useful to simply check if a specific wrapper is selected.
The qts.is_*
values are helpful for this.
In particular, mypy is able to understand booleans via the command line arguments --always-false
and --always-true
.
The Command line interface can be used to help generate the relevant options to pass to mypy.
- qts.wrapper: Optional[qts._core.Wrapper]¶
The presently active wrapper.
None
if no wrapper is set.
Exceptions¶
See Exceptions.
Command line interface¶
This tooling is a bit sparse right now. Perhaps other useful helpers will be identified in the future.
qts¶
qts [OPTIONS] COMMAND [ARGS]...
mypy¶
qts mypy [OPTIONS] COMMAND [ARGS]...
args¶
Generate arguments to be passed to mypy so it can understand which code should be active. If applications or other libraries use the same conditions in their code then this will work for them as well. The output can be directly injected in some shells such as is done below in bash.
$ mypy $(qts mypy args --wrapper pyside6) my_file.py
The module import selection code in qts itself can act as a reference.
1import qts
2
3
4if qts.wrapper is None:
5 raise qts.NoWrapperSelectedError()
6elif qts.is_pyqt_5_wrapper:
7 from PyQt5.QtCore import *
8elif qts.is_pyqt_6_wrapper:
9 from PyQt6.QtCore import *
10elif qts.is_pyside_5_wrapper:
11 from PySide2.QtCore import *
12elif qts.is_pyside_6_wrapper:
13 from PySide6.QtCore import *
14else:
15 raise qts.InvalidWrapperError(wrapper=qts.wrapper)
qts mypy args [OPTIONS]
Options
- --wrapper <wrapper_name>¶
- Options
PyQt5 | PyQt6 | PySide2 | PySide6
- --delimiter <delimiter>¶
Defaults to a space for TTYs and a newline otherwise.
Utilities¶
- qts.util.exec(execable: qts.util.ExecProtocol) → int[source]¶
Call the proper execute method on the passed object. Either
.exec()
or.exec_()
is chosen based on the configured wrapper..exec_()
exists as an artifact from supporting Python 2 whereexec
was a keyword.
Exceptions¶
- class qts.QtsError[source]¶
Bases:
Exception
Base exception class for all qts exceptions.
Do not raise directly.
- class qts.InternalError[source]¶
Bases:
qts._errors.QtsError
Raised when things that should not happen do, and they aren’t the user’s fault.
- class qts.InvalidWrapperError(wrapper: qts._core.Wrapper)[source]¶
Bases:
qts._errors.QtsError
Raised when an invalid wrapper is specified.
- class qts.MultipleWrappersAvailableError(searched: Iterable[qts._core.Wrapper], found: Iterable[qts._core.Wrapper])[source]¶
Bases:
qts._errors.QtsError
Raised when searching for one wrapper but multiple are available.
- class qts.NoWrapperAvailableError(wrappers: Iterable[qts._core.Wrapper])[source]¶
Bases:
qts._errors.QtsError
Raised when searching for wrappers and none are available.
- class qts.NoWrapperSelectedError[source]¶
Bases:
qts._errors.QtsError
Raised when a wrapper selection is required but has not been made.
- class qts.WrapperAlreadySelectedError(existing_wrapper: qts._core.Wrapper, requested_wrapper: qts._core.Wrapper)[source]¶
Bases:
qts._errors.QtsError
Raised when attempting to set a wrapper but one has already been selected.
Qt Modules¶
QtCore¶
Note
This documentation is meant only to describe the details that qts helps make more common. Complete documentation is left to the individual wrappers and the underlying C++ Qt library.
- qts.QtCore.Signal¶
The class attribute
Signal
object. It is a descriptor that evaluates to aSignalInstance
when accessed on an instance of its owning class.PyQt -
pyqtSignal
PySide -
Signal
QtGui¶
Note
This documentation is meant only to describe the details that qts helps make more common. Complete documentation is left to the individual wrappers and the underlying C++ Qt library.
No special handling is provided for this module.
QtWidgets¶
Note
This documentation is meant only to describe the details that qts helps make more common. Complete documentation is left to the individual wrappers and the underlying C++ Qt library.
No special handling is provided for this module.