| 
									
										
										
										
											2018-06-14 14:58:13 +02:00
										 |  |  | import math | 
					
						
							| 
									
										
										
										
											2019-04-26 04:08:53 +02:00
										 |  |  | import os.path | 
					
						
							|  |  |  | import sys | 
					
						
							| 
									
										
										
										
											2022-12-08 01:38:47 +01:00
										 |  |  | import sysconfig | 
					
						
							| 
									
										
										
										
											2018-06-01 11:04:45 +02:00
										 |  |  | import textwrap | 
					
						
							| 
									
										
										
										
											2019-06-13 01:09:04 +02:00
										 |  |  | from test import support | 
					
						
							| 
									
										
										
										
											2018-06-01 11:04:45 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def format_duration(seconds): | 
					
						
							| 
									
										
										
										
											2018-06-14 14:58:13 +02:00
										 |  |  |     ms = math.ceil(seconds * 1e3) | 
					
						
							|  |  |  |     seconds, ms = divmod(ms, 1000) | 
					
						
							|  |  |  |     minutes, seconds = divmod(seconds, 60) | 
					
						
							|  |  |  |     hours, minutes = divmod(minutes, 60) | 
					
						
							| 
									
										
										
										
											2018-06-01 11:04:45 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-14 14:58:13 +02:00
										 |  |  |     parts = [] | 
					
						
							| 
									
										
										
										
											2018-06-01 11:04:45 +02:00
										 |  |  |     if hours: | 
					
						
							| 
									
										
										
										
											2018-06-14 14:58:13 +02:00
										 |  |  |         parts.append('%s hour' % hours) | 
					
						
							|  |  |  |     if minutes: | 
					
						
							|  |  |  |         parts.append('%s min' % minutes) | 
					
						
							|  |  |  |     if seconds: | 
					
						
							| 
									
										
										
										
											2019-10-03 16:15:16 +02:00
										 |  |  |         if parts: | 
					
						
							|  |  |  |             # 2 min 1 sec | 
					
						
							|  |  |  |             parts.append('%s sec' % seconds) | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             # 1.0 sec | 
					
						
							|  |  |  |             parts.append('%.1f sec' % (seconds + ms / 1000)) | 
					
						
							| 
									
										
										
										
											2018-06-14 14:58:13 +02:00
										 |  |  |     if not parts: | 
					
						
							| 
									
										
										
										
											2019-10-03 16:15:16 +02:00
										 |  |  |         return '%s ms' % ms | 
					
						
							| 
									
										
										
										
											2018-06-14 14:58:13 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     parts = parts[:2] | 
					
						
							|  |  |  |     return ' '.join(parts) | 
					
						
							| 
									
										
										
										
											2018-06-01 11:04:45 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def removepy(names): | 
					
						
							|  |  |  |     if not names: | 
					
						
							|  |  |  |         return | 
					
						
							|  |  |  |     for idx, name in enumerate(names): | 
					
						
							|  |  |  |         basename, ext = os.path.splitext(name) | 
					
						
							|  |  |  |         if ext == '.py': | 
					
						
							|  |  |  |             names[idx] = basename | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def count(n, word): | 
					
						
							|  |  |  |     if n == 1: | 
					
						
							|  |  |  |         return "%d %s" % (n, word) | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         return "%d %ss" % (n, word) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def printlist(x, width=70, indent=4, file=None): | 
					
						
							|  |  |  |     """Print the elements of iterable x to stdout.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Optional arg width (default 70) is the maximum line length. | 
					
						
							|  |  |  |     Optional arg indent (default 4) is the number of blanks with which to | 
					
						
							|  |  |  |     begin each line. | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     blanks = ' ' * indent | 
					
						
							|  |  |  |     # Print the sorted list: 'x' may be a '--random' list or a set() | 
					
						
							|  |  |  |     print(textwrap.fill(' '.join(str(elt) for elt in sorted(x)), width, | 
					
						
							|  |  |  |                         initial_indent=blanks, subsequent_indent=blanks), | 
					
						
							|  |  |  |           file=file) | 
					
						
							| 
									
										
										
										
											2019-04-26 04:08:53 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def print_warning(msg): | 
					
						
							| 
									
										
										
										
											2020-04-23 19:03:52 +02:00
										 |  |  |     support.print_warning(msg) | 
					
						
							| 
									
										
										
										
											2019-06-13 01:09:04 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | orig_unraisablehook = None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def regrtest_unraisable_hook(unraisable): | 
					
						
							|  |  |  |     global orig_unraisablehook | 
					
						
							|  |  |  |     support.environment_altered = True | 
					
						
							| 
									
										
										
										
											2021-10-13 01:52:22 +02:00
										 |  |  |     support.print_warning("Unraisable exception") | 
					
						
							| 
									
										
										
										
											2020-08-03 22:51:23 +02:00
										 |  |  |     old_stderr = sys.stderr | 
					
						
							|  |  |  |     try: | 
					
						
							| 
									
										
										
										
											2021-10-11 23:07:21 +02:00
										 |  |  |         support.flush_std_streams() | 
					
						
							| 
									
										
										
										
											2021-10-13 14:08:18 +02:00
										 |  |  |         sys.stderr = support.print_warning.orig_stderr | 
					
						
							| 
									
										
										
										
											2020-08-03 22:51:23 +02:00
										 |  |  |         orig_unraisablehook(unraisable) | 
					
						
							| 
									
										
										
										
											2021-04-16 14:33:10 +02:00
										 |  |  |         sys.stderr.flush() | 
					
						
							| 
									
										
										
										
											2020-08-03 22:51:23 +02:00
										 |  |  |     finally: | 
					
						
							|  |  |  |         sys.stderr = old_stderr | 
					
						
							| 
									
										
										
										
											2019-06-13 01:09:04 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def setup_unraisable_hook(): | 
					
						
							|  |  |  |     global orig_unraisablehook | 
					
						
							|  |  |  |     orig_unraisablehook = sys.unraisablehook | 
					
						
							|  |  |  |     sys.unraisablehook = regrtest_unraisable_hook | 
					
						
							| 
									
										
										
										
											2021-03-23 00:17:05 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-16 14:33:10 +02:00
										 |  |  | orig_threading_excepthook = None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def regrtest_threading_excepthook(args): | 
					
						
							|  |  |  |     global orig_threading_excepthook | 
					
						
							|  |  |  |     support.environment_altered = True | 
					
						
							| 
									
										
										
										
											2021-10-13 01:52:22 +02:00
										 |  |  |     support.print_warning(f"Uncaught thread exception: {args.exc_type.__name__}") | 
					
						
							| 
									
										
										
										
											2021-04-16 14:33:10 +02:00
										 |  |  |     old_stderr = sys.stderr | 
					
						
							|  |  |  |     try: | 
					
						
							| 
									
										
										
										
											2021-10-11 23:07:21 +02:00
										 |  |  |         support.flush_std_streams() | 
					
						
							| 
									
										
										
										
											2021-10-13 14:08:18 +02:00
										 |  |  |         sys.stderr = support.print_warning.orig_stderr | 
					
						
							| 
									
										
										
										
											2021-04-16 14:33:10 +02:00
										 |  |  |         orig_threading_excepthook(args) | 
					
						
							|  |  |  |         sys.stderr.flush() | 
					
						
							|  |  |  |     finally: | 
					
						
							|  |  |  |         sys.stderr = old_stderr | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def setup_threading_excepthook(): | 
					
						
							|  |  |  |     global orig_threading_excepthook | 
					
						
							|  |  |  |     import threading | 
					
						
							|  |  |  |     orig_threading_excepthook = threading.excepthook | 
					
						
							|  |  |  |     threading.excepthook = regrtest_threading_excepthook | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-23 00:17:05 +01:00
										 |  |  | def clear_caches(): | 
					
						
							|  |  |  |     # Clear the warnings registry, so they can be displayed again | 
					
						
							|  |  |  |     for mod in sys.modules.values(): | 
					
						
							|  |  |  |         if hasattr(mod, '__warningregistry__'): | 
					
						
							|  |  |  |             del mod.__warningregistry__ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Flush standard output, so that buffered data is sent to the OS and | 
					
						
							|  |  |  |     # associated Python objects are reclaimed. | 
					
						
							|  |  |  |     for stream in (sys.stdout, sys.stderr, sys.__stdout__, sys.__stderr__): | 
					
						
							|  |  |  |         if stream is not None: | 
					
						
							|  |  |  |             stream.flush() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     try: | 
					
						
							|  |  |  |         re = sys.modules['re'] | 
					
						
							|  |  |  |     except KeyError: | 
					
						
							|  |  |  |         pass | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         re.purge() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     try: | 
					
						
							|  |  |  |         _strptime = sys.modules['_strptime'] | 
					
						
							|  |  |  |     except KeyError: | 
					
						
							|  |  |  |         pass | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         _strptime._regex_cache.clear() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     try: | 
					
						
							|  |  |  |         urllib_parse = sys.modules['urllib.parse'] | 
					
						
							|  |  |  |     except KeyError: | 
					
						
							|  |  |  |         pass | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         urllib_parse.clear_cache() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     try: | 
					
						
							|  |  |  |         urllib_request = sys.modules['urllib.request'] | 
					
						
							|  |  |  |     except KeyError: | 
					
						
							|  |  |  |         pass | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         urllib_request.urlcleanup() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     try: | 
					
						
							|  |  |  |         linecache = sys.modules['linecache'] | 
					
						
							|  |  |  |     except KeyError: | 
					
						
							|  |  |  |         pass | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         linecache.clearcache() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     try: | 
					
						
							|  |  |  |         mimetypes = sys.modules['mimetypes'] | 
					
						
							|  |  |  |     except KeyError: | 
					
						
							|  |  |  |         pass | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         mimetypes._default_mime_types() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     try: | 
					
						
							|  |  |  |         filecmp = sys.modules['filecmp'] | 
					
						
							|  |  |  |     except KeyError: | 
					
						
							|  |  |  |         pass | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         filecmp._cache.clear() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     try: | 
					
						
							|  |  |  |         struct = sys.modules['struct'] | 
					
						
							|  |  |  |     except KeyError: | 
					
						
							|  |  |  |         pass | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         struct._clearcache() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     try: | 
					
						
							|  |  |  |         doctest = sys.modules['doctest'] | 
					
						
							|  |  |  |     except KeyError: | 
					
						
							|  |  |  |         pass | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         doctest.master = None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     try: | 
					
						
							|  |  |  |         ctypes = sys.modules['ctypes'] | 
					
						
							|  |  |  |     except KeyError: | 
					
						
							|  |  |  |         pass | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         ctypes._reset_cache() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     try: | 
					
						
							|  |  |  |         typing = sys.modules['typing'] | 
					
						
							|  |  |  |     except KeyError: | 
					
						
							|  |  |  |         pass | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         for f in typing._cleanups: | 
					
						
							|  |  |  |             f() | 
					
						
							| 
									
										
										
										
											2022-09-08 13:52:07 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     try: | 
					
						
							|  |  |  |         fractions = sys.modules['fractions'] | 
					
						
							|  |  |  |     except KeyError: | 
					
						
							|  |  |  |         pass | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         fractions._hash_algorithm.cache_clear() | 
					
						
							| 
									
										
										
										
											2022-12-08 01:38:47 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-09 13:33:36 +01:00
										 |  |  |     try: | 
					
						
							|  |  |  |         inspect = sys.modules['inspect'] | 
					
						
							|  |  |  |     except KeyError: | 
					
						
							|  |  |  |         pass | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         inspect._shadowed_dict_from_mro_tuple.cache_clear() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-08 01:38:47 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | def get_build_info(): | 
					
						
							|  |  |  |     # Get most important configure and build options as a list of strings. | 
					
						
							|  |  |  |     # Example: ['debug', 'ASAN+MSAN'] or ['release', 'LTO+PGO']. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     config_args = sysconfig.get_config_var('CONFIG_ARGS') or '' | 
					
						
							|  |  |  |     cflags = sysconfig.get_config_var('PY_CFLAGS') or '' | 
					
						
							|  |  |  |     cflags_nodist = sysconfig.get_config_var('PY_CFLAGS_NODIST') or '' | 
					
						
							|  |  |  |     ldflags_nodist = sysconfig.get_config_var('PY_LDFLAGS_NODIST') or '' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     build = [] | 
					
						
							|  |  |  |     if hasattr(sys, 'gettotalrefcount'): | 
					
						
							|  |  |  |         # --with-pydebug | 
					
						
							|  |  |  |         build.append('debug') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if '-DNDEBUG' in (cflags + cflags_nodist): | 
					
						
							|  |  |  |             build.append('without_assert') | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         build.append('release') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if '--with-assertions' in config_args: | 
					
						
							|  |  |  |             build.append('with_assert') | 
					
						
							|  |  |  |         elif '-DNDEBUG' not in (cflags + cflags_nodist): | 
					
						
							|  |  |  |             build.append('with_assert') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # --enable-framework=name | 
					
						
							|  |  |  |     framework = sysconfig.get_config_var('PYTHONFRAMEWORK') | 
					
						
							|  |  |  |     if framework: | 
					
						
							|  |  |  |         build.append(f'framework={framework}') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # --enable-shared | 
					
						
							|  |  |  |     shared = int(sysconfig.get_config_var('PY_ENABLE_SHARED') or '0') | 
					
						
							|  |  |  |     if shared: | 
					
						
							|  |  |  |         build.append('shared') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # --with-lto | 
					
						
							|  |  |  |     optimizations = [] | 
					
						
							|  |  |  |     if '-flto=thin' in ldflags_nodist: | 
					
						
							|  |  |  |         optimizations.append('ThinLTO') | 
					
						
							|  |  |  |     elif '-flto' in ldflags_nodist: | 
					
						
							|  |  |  |         optimizations.append('LTO') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # --enable-optimizations | 
					
						
							|  |  |  |     pgo_options = ( | 
					
						
							|  |  |  |         # GCC | 
					
						
							|  |  |  |         '-fprofile-use', | 
					
						
							|  |  |  |         # clang: -fprofile-instr-use=code.profclangd | 
					
						
							|  |  |  |         '-fprofile-instr-use', | 
					
						
							|  |  |  |         # ICC | 
					
						
							|  |  |  |         "-prof-use", | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     if any(option in cflags_nodist for option in pgo_options): | 
					
						
							|  |  |  |         optimizations.append('PGO') | 
					
						
							|  |  |  |     if optimizations: | 
					
						
							|  |  |  |         build.append('+'.join(optimizations)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # --with-address-sanitizer | 
					
						
							|  |  |  |     sanitizers = [] | 
					
						
							|  |  |  |     if support.check_sanitizer(address=True): | 
					
						
							|  |  |  |         sanitizers.append("ASAN") | 
					
						
							|  |  |  |     # --with-memory-sanitizer | 
					
						
							|  |  |  |     if support.check_sanitizer(memory=True): | 
					
						
							|  |  |  |         sanitizers.append("MSAN") | 
					
						
							|  |  |  |     # --with-undefined-behavior-sanitizer | 
					
						
							|  |  |  |     if support.check_sanitizer(ub=True): | 
					
						
							|  |  |  |         sanitizers.append("UBSAN") | 
					
						
							|  |  |  |     if sanitizers: | 
					
						
							|  |  |  |         build.append('+'.join(sanitizers)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # --with-trace-refs | 
					
						
							|  |  |  |     if hasattr(sys, 'getobjects'): | 
					
						
							|  |  |  |         build.append("TraceRefs") | 
					
						
							|  |  |  |     # --enable-pystats | 
					
						
							|  |  |  |     if hasattr(sys, '_stats_on'): | 
					
						
							|  |  |  |         build.append("pystats") | 
					
						
							|  |  |  |     # --with-valgrind | 
					
						
							|  |  |  |     if sysconfig.get_config_var('WITH_VALGRIND'): | 
					
						
							|  |  |  |         build.append("valgrind") | 
					
						
							|  |  |  |     # --with-dtrace | 
					
						
							|  |  |  |     if sysconfig.get_config_var('WITH_DTRACE'): | 
					
						
							|  |  |  |         build.append("dtrace") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return build |