1- import asyncio
21import builtins
32import locale
4- import logging
53import os
6- import shutil
74import sys
8- import sysconfig
95import threading
10- import urllib .request
11- import warnings
126from test import support
137from test .support import os_helper
148from test .libregrtest .utils import print_warning
15- try :
16- import _multiprocessing , multiprocessing . process
17- except ImportError :
18- multiprocessing = None
9+
10+
11+ class SkipTestEnvironment ( Exception ) :
12+ pass
1913
2014
2115# Unit tests are supposed to leave the execution environment unchanged
@@ -33,15 +27,13 @@ class saved_test_environment:
3327 #stuff
3428
3529 Unless quiet is True, a warning is printed to stderr if any of
36- the saved items was changed by the test. The attribute 'changed'
37- is initially False, but is set to True if a change is detected.
30+ the saved items was changed by the test. The support.environment_altered
31+ attribute is set to True if a change is detected.
3832
3933 If verbose is more than 1, the before and after state of changed
4034 items is also printed.
4135 """
4236
43- changed = False
44-
4537 def __init__ (self , testname , verbose = 0 , quiet = False , * , pgo = False ):
4638 self .testname = testname
4739 self .verbose = verbose
@@ -73,20 +65,36 @@ def __init__(self, testname, verbose=0, quiet=False, *, pgo=False):
7365 'urllib.requests._url_tempfiles' , 'urllib.requests._opener' ,
7466 )
7567
68+ def get_module (self , name ):
69+ # function for restore() methods
70+ return sys .modules [name ]
71+
72+ def try_get_module (self , name ):
73+ # function for get() methods
74+ try :
75+ return self .get_module (name )
76+ except KeyError :
77+ raise SkipTestEnvironment
78+
7679 def get_urllib_requests__url_tempfiles (self ):
77- return list (urllib .request ._url_tempfiles )
80+ urllib_request = self .try_get_module ('urllib.request' )
81+ return list (urllib_request ._url_tempfiles )
7882 def restore_urllib_requests__url_tempfiles (self , tempfiles ):
7983 for filename in tempfiles :
8084 os_helper .unlink (filename )
8185
8286 def get_urllib_requests__opener (self ):
83- return urllib .request ._opener
87+ urllib_request = self .try_get_module ('urllib.request' )
88+ return urllib_request ._opener
8489 def restore_urllib_requests__opener (self , opener ):
85- urllib .request ._opener = opener
90+ urllib_request = self .get_module ('urllib.request' )
91+ urllib_request ._opener = opener
8692
8793 def get_asyncio_events__event_loop_policy (self ):
94+ self .try_get_module ('asyncio' )
8895 return support .maybe_get_event_loop_policy ()
8996 def restore_asyncio_events__event_loop_policy (self , policy ):
97+ asyncio = self .get_module ('asyncio' )
9098 asyncio .set_event_loop_policy (policy )
9199
92100 def get_sys_argv (self ):
@@ -145,8 +153,10 @@ def restore___import__(self, import_):
145153 builtins .__import__ = import_
146154
147155 def get_warnings_filters (self ):
156+ warnings = self .try_get_module ('warnings' )
148157 return id (warnings .filters ), warnings .filters , warnings .filters [:]
149158 def restore_warnings_filters (self , saved_filters ):
159+ warnings = self .get_module ('warnings' )
150160 warnings .filters = saved_filters [1 ]
151161 warnings .filters [:] = saved_filters [2 ]
152162
@@ -161,30 +171,36 @@ def restore_asyncore_socket_map(self, saved_map):
161171 asyncore .socket_map .update (saved_map )
162172
163173 def get_shutil_archive_formats (self ):
174+ shutil = self .try_get_module ('shutil' )
164175 # we could call get_archives_formats() but that only returns the
165176 # registry keys; we want to check the values too (the functions that
166177 # are registered)
167178 return shutil ._ARCHIVE_FORMATS , shutil ._ARCHIVE_FORMATS .copy ()
168179 def restore_shutil_archive_formats (self , saved ):
180+ shutil = self .get_module ('shutil' )
169181 shutil ._ARCHIVE_FORMATS = saved [0 ]
170182 shutil ._ARCHIVE_FORMATS .clear ()
171183 shutil ._ARCHIVE_FORMATS .update (saved [1 ])
172184
173185 def get_shutil_unpack_formats (self ):
186+ shutil = self .try_get_module ('shutil' )
174187 return shutil ._UNPACK_FORMATS , shutil ._UNPACK_FORMATS .copy ()
175188 def restore_shutil_unpack_formats (self , saved ):
189+ shutil = self .get_module ('shutil' )
176190 shutil ._UNPACK_FORMATS = saved [0 ]
177191 shutil ._UNPACK_FORMATS .clear ()
178192 shutil ._UNPACK_FORMATS .update (saved [1 ])
179193
180194 def get_logging__handlers (self ):
195+ logging = self .try_get_module ('logging' )
181196 # _handlers is a WeakValueDictionary
182197 return id (logging ._handlers ), logging ._handlers , logging ._handlers .copy ()
183198 def restore_logging__handlers (self , saved_handlers ):
184199 # Can't easily revert the logging state
185200 pass
186201
187202 def get_logging__handlerList (self ):
203+ logging = self .try_get_module ('logging' )
188204 # _handlerList is a list of weakrefs to handlers
189205 return id (logging ._handlerList ), logging ._handlerList , logging ._handlerList [:]
190206 def restore_logging__handlerList (self , saved_handlerList ):
@@ -208,32 +224,34 @@ def restore_threading__dangling(self, saved):
208224
209225 # Same for Process objects
210226 def get_multiprocessing_process__dangling (self ):
211- if not multiprocessing :
212- return None
227+ multiprocessing_process = self .try_get_module ('multiprocessing.process' )
213228 # Unjoined process objects can survive after process exits
214- multiprocessing . process ._cleanup ()
229+ multiprocessing_process ._cleanup ()
215230 # This copies the weakrefs without making any strong reference
216- return multiprocessing . process ._dangling .copy ()
231+ return multiprocessing_process ._dangling .copy ()
217232 def restore_multiprocessing_process__dangling (self , saved ):
218- if not multiprocessing :
219- return
220- multiprocessing .process ._dangling .clear ()
221- multiprocessing .process ._dangling .update (saved )
233+ multiprocessing_process = self .get_module ('multiprocessing.process' )
234+ multiprocessing_process ._dangling .clear ()
235+ multiprocessing_process ._dangling .update (saved )
222236
223237 def get_sysconfig__CONFIG_VARS (self ):
224238 # make sure the dict is initialized
239+ sysconfig = self .try_get_module ('sysconfig' )
225240 sysconfig .get_config_var ('prefix' )
226241 return (id (sysconfig ._CONFIG_VARS ), sysconfig ._CONFIG_VARS ,
227242 dict (sysconfig ._CONFIG_VARS ))
228243 def restore_sysconfig__CONFIG_VARS (self , saved ):
244+ sysconfig = self .get_module ('sysconfig' )
229245 sysconfig ._CONFIG_VARS = saved [1 ]
230246 sysconfig ._CONFIG_VARS .clear ()
231247 sysconfig ._CONFIG_VARS .update (saved [2 ])
232248
233249 def get_sysconfig__INSTALL_SCHEMES (self ):
250+ sysconfig = self .try_get_module ('sysconfig' )
234251 return (id (sysconfig ._INSTALL_SCHEMES ), sysconfig ._INSTALL_SCHEMES ,
235252 sysconfig ._INSTALL_SCHEMES .copy ())
236253 def restore_sysconfig__INSTALL_SCHEMES (self , saved ):
254+ sysconfig = self .get_module ('sysconfig' )
237255 sysconfig ._INSTALL_SCHEMES = saved [1 ]
238256 sysconfig ._INSTALL_SCHEMES .clear ()
239257 sysconfig ._INSTALL_SCHEMES .update (saved [2 ])
@@ -264,8 +282,10 @@ def restore_locale(self, saved):
264282 locale .setlocale (lc , setting )
265283
266284 def get_warnings_showwarning (self ):
285+ warnings = self .try_get_module ('warnings' )
267286 return warnings .showwarning
268287 def restore_warnings_showwarning (self , fxn ):
288+ warnings = self .get_module ('warnings' )
269289 warnings .showwarning = fxn
270290
271291 def resource_info (self ):
@@ -276,26 +296,28 @@ def resource_info(self):
276296 yield name , getattr (self , get_name ), getattr (self , restore_name )
277297
278298 def __enter__ (self ):
279- self .saved_values = dict ((name , get ()) for name , get , restore
280- in self .resource_info ())
299+ self .saved_values = []
300+ for name , get , restore in self .resource_info ():
301+ try :
302+ original = get ()
303+ except SkipTestEnvironment :
304+ continue
305+
306+ self .saved_values .append ((name , get , restore , original ))
281307 return self
282308
283309 def __exit__ (self , exc_type , exc_val , exc_tb ):
284310 saved_values = self .saved_values
285- del self .saved_values
311+ self .saved_values = None
286312
287313 # Some resources use weak references
288314 support .gc_collect ()
289315
290- # Read support.environment_altered, set by support helper functions
291- self .changed |= support .environment_altered
292-
293- for name , get , restore in self .resource_info ():
316+ for name , get , restore , original in saved_values :
294317 current = get ()
295- original = saved_values .pop (name )
296318 # Check for changes to the resource's value
297319 if current != original :
298- self . changed = True
320+ support . environment_altered = True
299321 restore (original )
300322 if not self .quiet and not self .pgo :
301323 print_warning (f"{ name } was modified by { self .testname } " )
0 commit comments