0
# Compatibility Utilities
1
2
Cross-binding compatibility functions for file dialogs, text processing, object lifecycle management, and QVariant handling that smooth over differences between Qt bindings and versions.
3
4
## Capabilities
5
6
### Text Processing Functions
7
8
Utilities for handling text strings consistently across Python versions and Qt bindings.
9
10
```python { .api }
11
def is_text_string(obj) -> bool:
12
"""
13
Return True if obj is a text string, False if it is anything else.
14
15
Args:
16
obj: Object to check
17
18
Returns:
19
bool: True if obj is a text string (str)
20
"""
21
22
def to_text_string(obj, encoding: str | None = None) -> str:
23
"""
24
Convert obj to (unicode) text string.
25
26
Args:
27
obj: Object to convert to string
28
encoding: Encoding to use if obj is bytes, defaults to None
29
30
Returns:
31
str: Text string representation of obj
32
"""
33
34
TEXT_TYPES: tuple[type, ...]
35
"""Tuple of text string types (str,)"""
36
```
37
38
Usage example:
39
40
```python
41
from qtpy.compat import is_text_string, to_text_string
42
43
data = "Hello World"
44
if is_text_string(data):
45
print("It's a string!")
46
47
# Convert various objects to text
48
text = to_text_string(42) # "42"
49
text = to_text_string(b"bytes", encoding="utf-8") # "bytes"
50
```
51
52
### QVariant Compatibility
53
54
Compatibility layer for QVariant differences between Qt bindings.
55
56
```python { .api }
57
def to_qvariant(obj=None):
58
"""
59
Convert Python object to QVariant.
60
This is a transitional function from PyQt API#1 (QVariant exist)
61
to PyQt API#2 and PySide (QVariant does not exist).
62
63
Args:
64
obj: Python object to convert
65
66
Returns:
67
The object itself (no conversion needed in modern bindings)
68
"""
69
70
def from_qvariant(qobj=None, pytype=None):
71
"""
72
Convert QVariant object to Python object.
73
This is a transitional function from PyQt API #1 (QVariant exist)
74
to PyQt API #2 and PySide (QVariant does not exist).
75
76
Args:
77
qobj: QVariant object to convert
78
pytype: Python type hint (unused in modern bindings)
79
80
Returns:
81
The object itself (no conversion needed in modern bindings)
82
"""
83
84
PYQT_API_1: bool
85
"""Always False - legacy PyQt API compatibility flag"""
86
```
87
88
### File Dialog Wrappers
89
90
Consistent file dialog interfaces that handle differences between Qt bindings and return types.
91
92
```python { .api }
93
def getexistingdirectory(
94
parent=None,
95
caption: str = '',
96
basedir: str = '',
97
options=None
98
) -> str:
99
"""
100
Wrapper for QFileDialog.getExistingDirectory.
101
102
Args:
103
parent: Parent widget
104
caption: Dialog caption
105
basedir: Starting directory
106
options: Dialog options
107
108
Returns:
109
str: Selected directory path or empty string if cancelled
110
"""
111
112
def getopenfilename(
113
parent=None,
114
caption: str = '',
115
basedir: str = '',
116
filters: str = '',
117
selectedfilter: str = '',
118
options=None
119
) -> tuple[str, str]:
120
"""
121
Wrapper for QFileDialog.getOpenFileName.
122
123
Args:
124
parent: Parent widget
125
caption: Dialog caption
126
basedir: Starting directory
127
filters: File filters (e.g., "Images (*.png *.jpg);;All Files (*)")
128
selectedfilter: Initially selected filter
129
options: Dialog options
130
131
Returns:
132
tuple[str, str]: (selected_filename, selected_filter)
133
"""
134
135
def getopenfilenames(
136
parent=None,
137
caption: str = '',
138
basedir: str = '',
139
filters: str = '',
140
selectedfilter: str = '',
141
options=None
142
) -> tuple[list[str], str]:
143
"""
144
Wrapper for QFileDialog.getOpenFileNames.
145
146
Args:
147
parent: Parent widget
148
caption: Dialog caption
149
basedir: Starting directory
150
filters: File filters
151
selectedfilter: Initially selected filter
152
options: Dialog options
153
154
Returns:
155
tuple[list[str], str]: (selected_filenames, selected_filter)
156
"""
157
158
def getsavefilename(
159
parent=None,
160
caption: str = '',
161
basedir: str = '',
162
filters: str = '',
163
selectedfilter: str = '',
164
options=None
165
) -> tuple[str, str]:
166
"""
167
Wrapper for QFileDialog.getSaveFileName.
168
169
Args:
170
parent: Parent widget
171
caption: Dialog caption
172
basedir: Starting directory
173
filters: File filters
174
selectedfilter: Initially selected filter
175
options: Dialog options
176
177
Returns:
178
tuple[str, str]: (selected_filename, selected_filter)
179
"""
180
```
181
182
Usage example:
183
184
```python
185
from qtpy.compat import getopenfilename, getsavefilename, getexistingdirectory
186
from qtpy.QtWidgets import QApplication, QWidget
187
188
app = QApplication([])
189
parent = QWidget()
190
191
# Open file dialog
192
filename, filter_used = getopenfilename(
193
parent,
194
"Open File",
195
"",
196
"Python Files (*.py);;All Files (*)"
197
)
198
if filename:
199
print(f"Selected: {filename}")
200
201
# Save file dialog
202
filename, filter_used = getsavefilename(
203
parent,
204
"Save File",
205
"",
206
"Text Files (*.txt);;All Files (*)"
207
)
208
209
# Directory selection
210
directory = getexistingdirectory(parent, "Select Directory")
211
```
212
213
### Object Lifecycle Functions
214
215
Utilities for checking Qt object validity across different bindings.
216
217
```python { .api }
218
def isalive(obj) -> bool:
219
"""
220
Wrapper for sip.isdeleted/shiboken.isValid to check if Qt object is alive.
221
222
Args:
223
obj: Qt object to check
224
225
Returns:
226
bool: True if the Qt object is still valid/alive, False if deleted
227
"""
228
```
229
230
Usage example:
231
232
```python
233
from qtpy.compat import isalive
234
from qtpy.QtWidgets import QWidget
235
236
widget = QWidget()
237
print(isalive(widget)) # True
238
239
widget.deleteLater()
240
# After event loop processes deletion
241
print(isalive(widget)) # False
242
```
243
244
## Import Patterns
245
246
All compatibility functions are available through the compat module:
247
248
```python
249
# Import specific functions
250
from qtpy.compat import getopenfilename, isalive, to_text_string
251
252
# Import entire module
253
from qtpy import compat
254
255
filename, _ = compat.getopenfilename(None, "Open File")
256
is_valid = compat.isalive(some_widget)
257
text = compat.to_text_string(some_object)
258
```
259
260
## Cross-Binding Consistency
261
262
The compatibility module ensures consistent behavior across all supported Qt bindings:
263
264
- **File Dialogs**: Uniform return types and parameter handling
265
- **Text Processing**: Consistent string handling across Python versions
266
- **Object Lifecycle**: Unified interface for checking object validity
267
- **QVariant**: Transparent handling of QVariant differences
268
269
This allows code to work identically whether using PyQt5, PyQt6, PySide2, or PySide6.