Skip to content

Commit 14fe931

Browse files
authored
Conform PEP 706 in build_qt.py (#1085)
Python 3.14 is going to have a breaking change in tarfile.TarFile.extractall as announced in PEP 706 [1]. This commit makes sure that 'build_qt.py' uses the new recommended pattern when available. There must be no observable change in the executables built. Closes #1084. [1]: https://peps.python.org/pep-0706/ PiperOrigin-RevId: 688076452
1 parent ad30419 commit 14fe931

File tree

1 file changed

+57
-8
lines changed

1 file changed

+57
-8
lines changed

src/build_tools/build_qt.py

+57-8
Original file line numberDiff line numberDiff line change
@@ -106,8 +106,11 @@ def print_line(self, msg: str) -> None:
106106
del msg # Unused
107107
return
108108

109-
self.cleaner = None
110-
return NoOpImpl()
109+
def cleanup(self) -> None:
110+
pass
111+
112+
self.impl = NoOpImpl()
113+
return self
111114

112115
class Impl:
113116
"""A real implementation in case stdout is attached to concole."""
@@ -129,18 +132,19 @@ def print_line(self, msg: str) -> None:
129132
sys.stdout.flush()
130133
self.last_output_time_ns = now
131134

132-
class Cleaner:
133135
def cleanup(self) -> None:
134136
colmuns = os.get_terminal_size().columns
135137
sys.stdout.write(' ' * colmuns + '\r')
136138
sys.stdout.flush()
137139

138-
self.cleaner = Cleaner()
139-
return Impl()
140+
self.impl = Impl()
141+
return self
142+
143+
def print_line(self, msg: str) -> None:
144+
self.impl.print_line(msg)
140145

141146
def __exit__(self, *exc):
142-
if self.cleaner:
143-
self.cleaner.cleanup()
147+
self.impl.cleanup()
144148

145149

146150
def qt_extract_filter(
@@ -180,6 +184,45 @@ def qt_extract_filter(
180184
yield info
181185

182186

187+
class StatefulQtExtractionFilter:
188+
"""A stateful extraction filter for PEP 706.
189+
190+
See https://peps.python.org/pep-0706/ for details.
191+
"""
192+
193+
def __enter__(self):
194+
self.printer = ProgressPrinter().__enter__()
195+
return self
196+
197+
def __exit__(self, *exc):
198+
self.printer.__exit__(exc)
199+
200+
def __call__(
201+
self,
202+
member: tarfile.TarInfo,
203+
dest_path: Union[str, pathlib.Path],
204+
) -> Union[tarfile.TarInfo, None]:
205+
data = tarfile.data_filter(member, dest_path)
206+
if data is None:
207+
return data
208+
209+
paths = member.name.split('/')
210+
if len(paths) < 1:
211+
return None
212+
paths = paths[1:]
213+
new_path = '/'.join(paths)
214+
skipping = False
215+
if len(paths) >= 1 and paths[0] == 'examples':
216+
skipping = True
217+
elif len(paths) >= 1 and paths[0] == 'tests':
218+
skipping = True
219+
if skipping:
220+
self.printer.print_line('skipping ' + new_path)
221+
return None
222+
self.printer.print_line('extracting ' + new_path)
223+
return member.replace(name=new_path, deep=False)
224+
225+
183226
@dataclasses.dataclass
184227
@functools.total_ordering
185228
class QtVersion:
@@ -568,7 +611,13 @@ def extract_qt_src(args: argparse.Namespace) -> None:
568611
else:
569612
qt_src_dir.mkdir(parents=True)
570613
with tarfile.open(args.qt_archive_path, mode='r|xz') as f:
571-
f.extractall(path=qt_src_dir, members=qt_extract_filter(f))
614+
# tarfile.data_filter is available in Python 3.12+.
615+
# See https://peps.python.org/pep-0706/ for details.
616+
if getattr(tarfile, 'data_filter', None):
617+
with StatefulQtExtractionFilter() as filter:
618+
f.extractall(path=qt_src_dir, filter=filter)
619+
else:
620+
f.extractall(path=qt_src_dir, members=qt_extract_filter(f))
572621

573622

574623
def main():

0 commit comments

Comments
 (0)