blob: e9edf675b9105af05e31810c2369ae6dbf61eff1 [file] [log] [blame]
Victor Stinnerb907abc2017-08-17 16:40:51 +02001"""
luzpaza5293b42017-11-05 07:37:50 -06002Collect various information about Python to help debugging test failures.
Victor Stinnerb907abc2017-08-17 16:40:51 +02003"""
4from __future__ import print_function
Victor Stinnera92941f2017-09-19 07:37:24 -07005import errno
Victor Stinnerb907abc2017-08-17 16:40:51 +02006import re
7import sys
8import traceback
Victor Stinnerddd7c422019-01-08 01:27:27 +01009import warnings
Victor Stinnerb907abc2017-08-17 16:40:51 +020010
11
12def normalize_text(text):
13 if text is None:
14 return None
15 text = str(text)
16 text = re.sub(r'\s+', ' ', text)
17 return text.strip()
18
19
20class PythonInfo:
21 def __init__(self):
22 self.info = {}
23
24 def add(self, key, value):
25 if key in self.info:
26 raise ValueError("duplicate key: %r" % key)
27
Victor Stinnerad7eaed2017-08-18 12:08:47 +020028 if value is None:
29 return
30
31 if not isinstance(value, int):
32 if not isinstance(value, str):
33 # convert other objects like sys.flags to string
34 value = str(value)
35
Victor Stinnerb907abc2017-08-17 16:40:51 +020036 value = value.strip()
37 if not value:
38 return
Victor Stinnerb907abc2017-08-17 16:40:51 +020039
40 self.info[key] = value
41
42 def get_infos(self):
43 """
luzpaza5293b42017-11-05 07:37:50 -060044 Get information as a key:value dictionary where values are strings.
Victor Stinnerb907abc2017-08-17 16:40:51 +020045 """
46 return {key: str(value) for key, value in self.info.items()}
47
48
49def copy_attributes(info_add, obj, name_fmt, attributes, *, formatter=None):
50 for attr in attributes:
51 value = getattr(obj, attr, None)
52 if value is None:
53 continue
54 name = name_fmt % attr
55 if formatter is not None:
56 value = formatter(attr, value)
57 info_add(name, value)
58
59
Victor Stinner5d39e042017-11-29 17:20:38 +010060def copy_attr(info_add, name, mod, attr_name):
61 try:
62 value = getattr(mod, attr_name)
63 except AttributeError:
64 return
65 info_add(name, value)
66
67
Victor Stinnerad7eaed2017-08-18 12:08:47 +020068def call_func(info_add, name, mod, func_name, *, formatter=None):
69 try:
70 func = getattr(mod, func_name)
71 except AttributeError:
72 return
73 value = func()
74 if formatter is not None:
75 value = formatter(value)
76 info_add(name, value)
Victor Stinnerb907abc2017-08-17 16:40:51 +020077
Victor Stinnerad7eaed2017-08-18 12:08:47 +020078
79def collect_sys(info_add):
Victor Stinnerb907abc2017-08-17 16:40:51 +020080 attributes = (
81 '_framework',
Victor Stinnerad7eaed2017-08-18 12:08:47 +020082 'abiflags',
83 'api_version',
84 'builtin_module_names',
Victor Stinnerb907abc2017-08-17 16:40:51 +020085 'byteorder',
Victor Stinnerad7eaed2017-08-18 12:08:47 +020086 'dont_write_bytecode',
Victor Stinnerb907abc2017-08-17 16:40:51 +020087 'executable',
88 'flags',
Victor Stinnerad7eaed2017-08-18 12:08:47 +020089 'float_info',
90 'float_repr_style',
91 'hash_info',
92 'hexversion',
93 'implementation',
94 'int_info',
Victor Stinnerb907abc2017-08-17 16:40:51 +020095 'maxsize',
96 'maxunicode',
Victor Stinnerad7eaed2017-08-18 12:08:47 +020097 'path',
98 'platform',
99 'prefix',
100 'thread_info',
Victor Stinnerb907abc2017-08-17 16:40:51 +0200101 'version',
Victor Stinnerad7eaed2017-08-18 12:08:47 +0200102 'version_info',
103 'winver',
Victor Stinnerb907abc2017-08-17 16:40:51 +0200104 )
Victor Stinnerad7eaed2017-08-18 12:08:47 +0200105 copy_attributes(info_add, sys, 'sys.%s', attributes)
106
107 call_func(info_add, 'sys.androidapilevel', sys, 'getandroidapilevel')
108 call_func(info_add, 'sys.windowsversion', sys, 'getwindowsversion')
Victor Stinnerb907abc2017-08-17 16:40:51 +0200109
110 encoding = sys.getfilesystemencoding()
111 if hasattr(sys, 'getfilesystemencodeerrors'):
112 encoding = '%s/%s' % (encoding, sys.getfilesystemencodeerrors())
113 info_add('sys.filesystem_encoding', encoding)
114
115 for name in ('stdin', 'stdout', 'stderr'):
116 stream = getattr(sys, name)
117 if stream is None:
118 continue
119 encoding = getattr(stream, 'encoding', None)
120 if not encoding:
121 continue
122 errors = getattr(stream, 'errors', None)
123 if errors:
124 encoding = '%s/%s' % (encoding, errors)
125 info_add('sys.%s.encoding' % name, encoding)
126
Victor Stinnerafd055a2017-10-31 08:41:10 -0700127 # Were we compiled --with-pydebug or with #define Py_DEBUG?
128 Py_DEBUG = hasattr(sys, 'gettotalrefcount')
129 if Py_DEBUG:
130 text = 'Yes (sys.gettotalrefcount() present)'
131 else:
132 text = 'No (sys.gettotalrefcount() missing)'
133 info_add('Py_DEBUG', text)
134
Victor Stinnerb907abc2017-08-17 16:40:51 +0200135
136def collect_platform(info_add):
137 import platform
138
139 arch = platform.architecture()
140 arch = ' '.join(filter(bool, arch))
141 info_add('platform.architecture', arch)
142
143 info_add('platform.python_implementation',
144 platform.python_implementation())
145 info_add('platform.platform',
146 platform.platform(aliased=True))
147
Victor Stinner848acf72018-12-05 23:21:54 +0100148 libc_ver = ('%s %s' % platform.libc_ver()).strip()
149 if libc_ver:
150 info_add('platform.libc_ver', libc_ver)
151
Victor Stinnerb907abc2017-08-17 16:40:51 +0200152
153def collect_locale(info_add):
154 import locale
155
156 info_add('locale.encoding', locale.getpreferredencoding(False))
157
158
Victor Stinner98146972017-12-13 17:27:40 +0100159def collect_builtins(info_add):
160 info_add('builtins.float.float_format', float.__getformat__("float"))
161 info_add('builtins.float.double_format', float.__getformat__("double"))
162
163
Victor Stinnerb907abc2017-08-17 16:40:51 +0200164def collect_os(info_add):
165 import os
166
Victor Stinnerad7eaed2017-08-18 12:08:47 +0200167 def format_attr(attr, value):
168 if attr in ('supports_follow_symlinks', 'supports_fd',
169 'supports_effective_ids'):
170 return str(sorted(func.__name__ for func in value))
171 else:
172 return value
173
174 attributes = (
175 'name',
176 'supports_bytes_environ',
177 'supports_effective_ids',
178 'supports_fd',
179 'supports_follow_symlinks',
180 )
181 copy_attributes(info_add, os, 'os.%s', attributes, formatter=format_attr)
Victor Stinnerb907abc2017-08-17 16:40:51 +0200182
Victor Stinner98146972017-12-13 17:27:40 +0100183 call_func(info_add, 'os.cwd', os, 'getcwd')
Victor Stinnerb907abc2017-08-17 16:40:51 +0200184
Victor Stinnerad7eaed2017-08-18 12:08:47 +0200185 call_func(info_add, 'os.uid', os, 'getuid')
186 call_func(info_add, 'os.gid', os, 'getgid')
187 call_func(info_add, 'os.uname', os, 'uname')
Victor Stinnerb907abc2017-08-17 16:40:51 +0200188
Victor Stinner5d39e042017-11-29 17:20:38 +0100189 def format_groups(groups):
190 return ', '.join(map(str, groups))
191
192 call_func(info_add, 'os.groups', os, 'getgroups', formatter=format_groups)
Victor Stinnerb907abc2017-08-17 16:40:51 +0200193
194 if hasattr(os, 'getlogin'):
195 try:
196 login = os.getlogin()
197 except OSError:
198 # getlogin() fails with "OSError: [Errno 25] Inappropriate ioctl
199 # for device" on Travis CI
200 pass
201 else:
202 info_add("os.login", login)
203
Victor Stinner5d39e042017-11-29 17:20:38 +0100204 call_func(info_add, 'os.cpu_count', os, 'cpu_count')
Victor Stinnerad7eaed2017-08-18 12:08:47 +0200205 call_func(info_add, 'os.loadavg', os, 'getloadavg')
Victor Stinnerb907abc2017-08-17 16:40:51 +0200206
Victor Stinner282c03d2018-11-26 17:03:16 +0100207 # Environment variables used by the stdlib and tests. Don't log the full
208 # environment: filter to list to not leak sensitive information.
209 #
210 # HTTP_PROXY is not logged because it can contain a password.
211 ENV_VARS = frozenset((
212 "APPDATA",
213 "AR",
214 "ARCHFLAGS",
215 "ARFLAGS",
216 "AUDIODEV",
Victor Stinnerb907abc2017-08-17 16:40:51 +0200217 "CC",
Victor Stinner282c03d2018-11-26 17:03:16 +0100218 "CFLAGS",
219 "COLUMNS",
220 "COMPUTERNAME",
Victor Stinnerb907abc2017-08-17 16:40:51 +0200221 "COMSPEC",
Victor Stinner282c03d2018-11-26 17:03:16 +0100222 "CPP",
223 "CPPFLAGS",
Victor Stinnerb907abc2017-08-17 16:40:51 +0200224 "DISPLAY",
Victor Stinner282c03d2018-11-26 17:03:16 +0100225 "DISTUTILS_DEBUG",
Victor Stinnerb907abc2017-08-17 16:40:51 +0200226 "DISTUTILS_USE_SDK",
227 "DYLD_LIBRARY_PATH",
Victor Stinner282c03d2018-11-26 17:03:16 +0100228 "ENSUREPIP_OPTIONS",
229 "HISTORY_FILE",
Victor Stinnerb907abc2017-08-17 16:40:51 +0200230 "HOME",
231 "HOMEDRIVE",
232 "HOMEPATH",
Victor Stinner282c03d2018-11-26 17:03:16 +0100233 "IDLESTARTUP",
Victor Stinnerb907abc2017-08-17 16:40:51 +0200234 "LANG",
Victor Stinner282c03d2018-11-26 17:03:16 +0100235 "LDFLAGS",
236 "LDSHARED",
Victor Stinnerb907abc2017-08-17 16:40:51 +0200237 "LD_LIBRARY_PATH",
Victor Stinner282c03d2018-11-26 17:03:16 +0100238 "LINES",
Victor Stinnerb907abc2017-08-17 16:40:51 +0200239 "MACOSX_DEPLOYMENT_TARGET",
Victor Stinner282c03d2018-11-26 17:03:16 +0100240 "MAILCAPS",
Victor Stinnerb907abc2017-08-17 16:40:51 +0200241 "MAKEFLAGS",
Victor Stinner282c03d2018-11-26 17:03:16 +0100242 "MIXERDEV",
Victor Stinnerb907abc2017-08-17 16:40:51 +0200243 "MSSDK",
244 "PATH",
Victor Stinner282c03d2018-11-26 17:03:16 +0100245 "PATHEXT",
246 "PIP_CONFIG_FILE",
247 "PLAT",
248 "POSIXLY_CORRECT",
249 "PY_SAX_PARSER",
250 "ProgramFiles",
251 "ProgramFiles(x86)",
252 "RUNNING_ON_VALGRIND",
Victor Stinnerb907abc2017-08-17 16:40:51 +0200253 "SDK_TOOLS_BIN",
Victor Stinner282c03d2018-11-26 17:03:16 +0100254 "SERVER_SOFTWARE",
Victor Stinnerb907abc2017-08-17 16:40:51 +0200255 "SHELL",
Victor Stinner282c03d2018-11-26 17:03:16 +0100256 "SOURCE_DATE_EPOCH",
257 "SYSTEMROOT",
Victor Stinnerb907abc2017-08-17 16:40:51 +0200258 "TEMP",
259 "TERM",
Victor Stinner282c03d2018-11-26 17:03:16 +0100260 "TILE_LIBRARY",
261 "TIX_LIBRARY",
Victor Stinnerb907abc2017-08-17 16:40:51 +0200262 "TMP",
263 "TMPDIR",
Victor Stinnerc11b3b12018-12-05 01:58:31 +0100264 "TRAVIS",
Victor Stinner282c03d2018-11-26 17:03:16 +0100265 "TZ",
Victor Stinnerb907abc2017-08-17 16:40:51 +0200266 "USERPROFILE",
Victor Stinner282c03d2018-11-26 17:03:16 +0100267 "VIRTUAL_ENV",
Victor Stinnerb907abc2017-08-17 16:40:51 +0200268 "WAYLAND_DISPLAY",
Victor Stinner282c03d2018-11-26 17:03:16 +0100269 "WINDIR",
270 "_PYTHON_HOST_PLATFORM",
271 "_PYTHON_PROJECT_BASE",
272 "_PYTHON_SYSCONFIGDATA_NAME",
273 "__PYVENV_LAUNCHER__",
274 ))
Victor Stinnerb907abc2017-08-17 16:40:51 +0200275 for name, value in os.environ.items():
276 uname = name.upper()
Victor Stinner5d39e042017-11-29 17:20:38 +0100277 if (uname in ENV_VARS
278 # Copy PYTHON* and LC_* variables
279 or uname.startswith(("PYTHON", "LC_"))
Victor Stinnerb907abc2017-08-17 16:40:51 +0200280 # Visual Studio: VS140COMNTOOLS
281 or (uname.startswith("VS") and uname.endswith("COMNTOOLS"))):
282 info_add('os.environ[%s]' % name, value)
283
Victor Stinnerad7eaed2017-08-18 12:08:47 +0200284 if hasattr(os, 'umask'):
285 mask = os.umask(0)
286 os.umask(mask)
287 info_add("os.umask", '%03o' % mask)
288
289 if hasattr(os, 'getrandom'):
290 # PEP 524: Check if system urandom is initialized
291 try:
Victor Stinnera92941f2017-09-19 07:37:24 -0700292 try:
293 os.getrandom(1, os.GRND_NONBLOCK)
294 state = 'ready (initialized)'
295 except BlockingIOError as exc:
296 state = 'not seeded yet (%s)' % exc
297 info_add('os.getrandom', state)
298 except OSError as exc:
299 # Python was compiled on a more recent Linux version
300 # than the current Linux kernel: ignore OSError(ENOSYS)
301 if exc.errno != errno.ENOSYS:
302 raise
Victor Stinnerad7eaed2017-08-18 12:08:47 +0200303
Victor Stinnerb907abc2017-08-17 16:40:51 +0200304
305def collect_readline(info_add):
306 try:
307 import readline
308 except ImportError:
309 return
310
311 def format_attr(attr, value):
312 if isinstance(value, int):
313 return "%#x" % value
314 else:
315 return value
316
317 attributes = (
318 "_READLINE_VERSION",
319 "_READLINE_RUNTIME_VERSION",
320 "_READLINE_LIBRARY_VERSION",
321 )
322 copy_attributes(info_add, readline, 'readline.%s', attributes,
323 formatter=format_attr)
324
Victor Stinneref634b52018-06-01 11:04:29 +0200325 if not hasattr(readline, "_READLINE_LIBRARY_VERSION"):
326 # _READLINE_LIBRARY_VERSION has been added to CPython 3.7
327 doc = getattr(readline, '__doc__', '')
328 if 'libedit readline' in doc:
329 info_add('readline.library', 'libedit readline')
330 elif 'GNU readline' in doc:
331 info_add('readline.library', 'GNU readline')
332
Victor Stinnerb907abc2017-08-17 16:40:51 +0200333
334def collect_gdb(info_add):
335 import subprocess
336
337 try:
338 proc = subprocess.Popen(["gdb", "-nx", "--version"],
339 stdout=subprocess.PIPE,
340 stderr=subprocess.PIPE,
341 universal_newlines=True)
342 version = proc.communicate()[0]
343 except OSError:
344 return
345
346 # Only keep the first line
347 version = version.splitlines()[0]
348 info_add('gdb_version', version)
349
350
351def collect_tkinter(info_add):
352 try:
353 import _tkinter
354 except ImportError:
355 pass
356 else:
357 attributes = ('TK_VERSION', 'TCL_VERSION')
358 copy_attributes(info_add, _tkinter, 'tkinter.%s', attributes)
359
360 try:
361 import tkinter
362 except ImportError:
363 pass
364 else:
365 tcl = tkinter.Tcl()
366 patchlevel = tcl.call('info', 'patchlevel')
367 info_add('tkinter.info_patchlevel', patchlevel)
368
369
370def collect_time(info_add):
371 import time
372
Victor Stinner7d91c022018-01-17 16:35:45 +0100373 info_add('time.time', time.time())
374
Victor Stinnerad7eaed2017-08-18 12:08:47 +0200375 attributes = (
376 'altzone',
377 'daylight',
378 'timezone',
379 'tzname',
380 )
381 copy_attributes(info_add, time, 'time.%s', attributes)
382
Victor Stinner5d39e042017-11-29 17:20:38 +0100383 if hasattr(time, 'get_clock_info'):
Victor Stinnerddd7c422019-01-08 01:27:27 +0100384 for clock in ('clock', 'monotonic', 'perf_counter',
385 'process_time', 'thread_time', 'time'):
386 try:
387 # prevent DeprecatingWarning on get_clock_info('clock')
388 with warnings.catch_warnings(record=True):
389 clock_info = time.get_clock_info(clock)
390 except ValueError:
391 # missing clock like time.thread_time()
392 pass
393 else:
394 info_add('time.get_clock_info(%s)' % clock, clock_info)
Victor Stinner7d91c022018-01-17 16:35:45 +0100395
396
397def collect_datetime(info_add):
398 try:
399 import datetime
400 except ImportError:
401 return
402
403 info_add('datetime.datetime.now', datetime.datetime.now())
Victor Stinnerb907abc2017-08-17 16:40:51 +0200404
405
406def collect_sysconfig(info_add):
407 import sysconfig
408
409 for name in (
410 'ABIFLAGS',
411 'ANDROID_API_LEVEL',
412 'CC',
413 'CCSHARED',
414 'CFLAGS',
415 'CFLAGSFORSHARED',
Victor Stinnerb907abc2017-08-17 16:40:51 +0200416 'CONFIG_ARGS',
417 'HOST_GNU_TYPE',
418 'MACHDEP',
419 'MULTIARCH',
420 'OPT',
421 'PY_CFLAGS',
422 'PY_CFLAGS_NODIST',
stratakiscf10a752018-12-19 18:19:01 +0100423 'PY_CORE_LDFLAGS',
Victor Stinner5d39e042017-11-29 17:20:38 +0100424 'PY_LDFLAGS',
stratakiscf10a752018-12-19 18:19:01 +0100425 'PY_LDFLAGS_NODIST',
426 'PY_STDMODULE_CFLAGS',
Victor Stinnerb907abc2017-08-17 16:40:51 +0200427 'Py_DEBUG',
428 'Py_ENABLE_SHARED',
429 'SHELL',
430 'SOABI',
431 'prefix',
432 ):
433 value = sysconfig.get_config_var(name)
434 if name == 'ANDROID_API_LEVEL' and not value:
435 # skip ANDROID_API_LEVEL=0
436 continue
437 value = normalize_text(value)
438 info_add('sysconfig[%s]' % name, value)
439
440
441def collect_ssl(info_add):
442 try:
443 import ssl
444 except ImportError:
445 return
446
447 def format_attr(attr, value):
448 if attr.startswith('OP_'):
449 return '%#8x' % value
450 else:
Victor Stinnerad7eaed2017-08-18 12:08:47 +0200451 return value
Victor Stinnerb907abc2017-08-17 16:40:51 +0200452
453 attributes = (
454 'OPENSSL_VERSION',
455 'OPENSSL_VERSION_INFO',
456 'HAS_SNI',
457 'OP_ALL',
458 'OP_NO_TLSv1_1',
459 )
460 copy_attributes(info_add, ssl, 'ssl.%s', attributes, formatter=format_attr)
461
462
463def collect_socket(info_add):
464 import socket
465
466 hostname = socket.gethostname()
467 info_add('socket.hostname', hostname)
468
469
470def collect_sqlite(info_add):
471 try:
472 import sqlite3
473 except ImportError:
474 return
475
476 attributes = ('version', 'sqlite_version')
477 copy_attributes(info_add, sqlite3, 'sqlite3.%s', attributes)
478
479
480def collect_zlib(info_add):
481 try:
482 import zlib
483 except ImportError:
484 return
485
486 attributes = ('ZLIB_VERSION', 'ZLIB_RUNTIME_VERSION')
487 copy_attributes(info_add, zlib, 'zlib.%s', attributes)
488
489
Victor Stinnerf6ebd832017-08-17 22:13:11 +0200490def collect_expat(info_add):
491 try:
492 from xml.parsers import expat
493 except ImportError:
494 return
495
496 attributes = ('EXPAT_VERSION',)
497 copy_attributes(info_add, expat, 'expat.%s', attributes)
498
499
500def collect_decimal(info_add):
501 try:
502 import _decimal
503 except ImportError:
504 return
505
506 attributes = ('__libmpdec_version__',)
507 copy_attributes(info_add, _decimal, '_decimal.%s', attributes)
508
509
Victor Stinner5d39e042017-11-29 17:20:38 +0100510def collect_testcapi(info_add):
511 try:
512 import _testcapi
513 except ImportError:
514 return
515
516 call_func(info_add, 'pymem.allocator', _testcapi, 'pymem_getallocatorsname')
517 copy_attr(info_add, 'pymem.with_pymalloc', _testcapi, 'WITH_PYMALLOC')
518
519
Victor Stinner98146972017-12-13 17:27:40 +0100520def collect_resource(info_add):
521 try:
522 import resource
523 except ImportError:
524 return
525
526 limits = [attr for attr in dir(resource) if attr.startswith('RLIMIT_')]
527 for name in limits:
528 key = getattr(resource, name)
529 value = resource.getrlimit(key)
530 info_add('resource.%s' % name, value)
531
Victor Stinnerb2385452019-01-21 10:24:12 +0100532 call_func(info_add, 'resource.pagesize', resource, 'getpagesize')
533
Victor Stinner98146972017-12-13 17:27:40 +0100534
535def collect_test_socket(info_add):
536 try:
537 from test import test_socket
538 except ImportError:
539 return
540
541 # all check attributes like HAVE_SOCKET_CAN
542 attributes = [name for name in dir(test_socket)
543 if name.startswith('HAVE_')]
544 copy_attributes(info_add, test_socket, 'test_socket.%s', attributes)
545
546
547def collect_test_support(info_add):
548 try:
549 from test import support
550 except ImportError:
551 return
552
553 attributes = ('IPV6_ENABLED',)
554 copy_attributes(info_add, support, 'test_support.%s', attributes)
555
556 call_func(info_add, 'test_support._is_gui_available', support, '_is_gui_available')
557 call_func(info_add, 'test_support.python_is_optimized', support, 'python_is_optimized')
558
559
Victor Stinner56013212018-06-01 00:33:03 +0200560def collect_cc(info_add):
561 import subprocess
562 import sysconfig
563
564 CC = sysconfig.get_config_var('CC')
565 if not CC:
566 return
567
568 try:
569 import shlex
570 args = shlex.split(CC)
571 except ImportError:
572 args = CC.split()
573 args.append('--version')
xdegayea86e0642019-04-29 14:53:30 +0200574 try:
575 proc = subprocess.Popen(args,
576 stdout=subprocess.PIPE,
577 stderr=subprocess.STDOUT,
578 universal_newlines=True)
579 except OSError:
580 # Cannot run the compiler, for example when Python has been
581 # cross-compiled and installed on the target platform where the
582 # compiler is missing.
583 return
584
Victor Stinner56013212018-06-01 00:33:03 +0200585 stdout = proc.communicate()[0]
586 if proc.returncode:
587 # CC --version failed: ignore error
588 return
589
590 text = stdout.splitlines()[0]
591 text = normalize_text(text)
592 info_add('CC.version', text)
593
594
Victor Stinner00f9edb2018-06-19 23:29:22 +0200595def collect_gdbm(info_add):
596 try:
Xiang Zhangb248e952018-06-20 21:23:30 +0800597 from _gdbm import _GDBM_VERSION
Victor Stinner00f9edb2018-06-19 23:29:22 +0200598 except ImportError:
599 return
600
Xiang Zhangb248e952018-06-20 21:23:30 +0800601 info_add('gdbm.GDBM_VERSION', '.'.join(map(str, _GDBM_VERSION)))
Victor Stinner00f9edb2018-06-19 23:29:22 +0200602
603
Victor Stinner00b137c2018-11-13 19:59:26 +0100604def collect_get_config(info_add):
Victor Stinner5f38b842019-05-01 02:30:12 +0200605 # Get global configuration variables, _PyPreConfig and _PyCoreConfig
Victor Stinner2094c2b2018-09-03 17:06:39 +0200606 try:
Victor Stinner23bace22019-04-18 11:37:26 +0200607 from _testinternalcapi import get_configs
Victor Stinner2094c2b2018-09-03 17:06:39 +0200608 except ImportError:
Victor Stinner7ddd56f2018-11-14 00:24:28 +0100609 return
Victor Stinner2094c2b2018-09-03 17:06:39 +0200610
Victor Stinner1075d162019-03-25 23:19:57 +0100611 all_configs = get_configs()
612 for config_type in sorted(all_configs):
613 config = all_configs[config_type]
Victor Stinner00b137c2018-11-13 19:59:26 +0100614 for key in sorted(config):
Victor Stinner1075d162019-03-25 23:19:57 +0100615 info_add('%s[%s]' % (config_type, key), repr(config[key]))
Victor Stinner2094c2b2018-09-03 17:06:39 +0200616
617
Victor Stinner9daecf32019-01-16 00:02:35 +0100618def collect_subprocess(info_add):
619 import subprocess
Victor Stinner8c349562019-01-16 23:38:06 +0100620 copy_attributes(info_add, subprocess, 'subprocess.%s', ('_USE_POSIX_SPAWN',))
Victor Stinner9daecf32019-01-16 00:02:35 +0100621
622
Victor Stinnerb907abc2017-08-17 16:40:51 +0200623def collect_info(info):
624 error = False
625 info_add = info.add
626
627 for collect_func in (
628 # collect_os() should be the first, to check the getrandom() status
629 collect_os,
630
Victor Stinner98146972017-12-13 17:27:40 +0100631 collect_builtins,
Victor Stinnerb907abc2017-08-17 16:40:51 +0200632 collect_gdb,
633 collect_locale,
634 collect_platform,
635 collect_readline,
636 collect_socket,
637 collect_sqlite,
638 collect_ssl,
639 collect_sys,
640 collect_sysconfig,
641 collect_time,
Victor Stinner7d91c022018-01-17 16:35:45 +0100642 collect_datetime,
Victor Stinnerb907abc2017-08-17 16:40:51 +0200643 collect_tkinter,
644 collect_zlib,
Victor Stinnerf6ebd832017-08-17 22:13:11 +0200645 collect_expat,
646 collect_decimal,
Victor Stinner5d39e042017-11-29 17:20:38 +0100647 collect_testcapi,
Victor Stinner98146972017-12-13 17:27:40 +0100648 collect_resource,
Victor Stinner56013212018-06-01 00:33:03 +0200649 collect_cc,
Victor Stinner00f9edb2018-06-19 23:29:22 +0200650 collect_gdbm,
Victor Stinner00b137c2018-11-13 19:59:26 +0100651 collect_get_config,
Victor Stinner9daecf32019-01-16 00:02:35 +0100652 collect_subprocess,
Victor Stinner98146972017-12-13 17:27:40 +0100653
654 # Collecting from tests should be last as they have side effects.
655 collect_test_socket,
656 collect_test_support,
Victor Stinnerb907abc2017-08-17 16:40:51 +0200657 ):
658 try:
659 collect_func(info_add)
660 except Exception as exc:
661 error = True
662 print("ERROR: %s() failed" % (collect_func.__name__),
663 file=sys.stderr)
664 traceback.print_exc(file=sys.stderr)
665 print(file=sys.stderr)
666 sys.stderr.flush()
667
668 return error
669
670
671def dump_info(info, file=None):
672 title = "Python debug information"
673 print(title)
674 print("=" * len(title))
675 print()
676
677 infos = info.get_infos()
678 infos = sorted(infos.items())
679 for key, value in infos:
680 value = value.replace("\n", " ")
681 print("%s: %s" % (key, value))
682 print()
683
684
685def main():
686 info = PythonInfo()
687 error = collect_info(info)
688 dump_info(info)
689
690 if error:
691 print("Collection failed: exit with error", file=sys.stderr)
692 sys.exit(1)
693
694
695if __name__ == "__main__":
696 main()