@@ -106,8 +106,11 @@ def print_line(self, msg: str) -> None:
106
106
del msg # Unused
107
107
return
108
108
109
- self .cleaner = None
110
- return NoOpImpl ()
109
+ def cleanup (self ) -> None :
110
+ pass
111
+
112
+ self .impl = NoOpImpl ()
113
+ return self
111
114
112
115
class Impl :
113
116
"""A real implementation in case stdout is attached to concole."""
@@ -129,18 +132,19 @@ def print_line(self, msg: str) -> None:
129
132
sys .stdout .flush ()
130
133
self .last_output_time_ns = now
131
134
132
- class Cleaner :
133
135
def cleanup (self ) -> None :
134
136
colmuns = os .get_terminal_size ().columns
135
137
sys .stdout .write (' ' * colmuns + '\r ' )
136
138
sys .stdout .flush ()
137
139
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 )
140
145
141
146
def __exit__ (self , * exc ):
142
- if self .cleaner :
143
- self .cleaner .cleanup ()
147
+ self .impl .cleanup ()
144
148
145
149
146
150
def qt_extract_filter (
@@ -180,6 +184,45 @@ def qt_extract_filter(
180
184
yield info
181
185
182
186
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
+
183
226
@dataclasses .dataclass
184
227
@functools .total_ordering
185
228
class QtVersion :
@@ -568,7 +611,13 @@ def extract_qt_src(args: argparse.Namespace) -> None:
568
611
else :
569
612
qt_src_dir .mkdir (parents = True )
570
613
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 ))
572
621
573
622
574
623
def main ():
0 commit comments