blob: 6eb9e875bd677291c89c56e7e7a4ba0c52573751 [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 Stinner9cb27412019-06-25 13:37:27 +0200164def collect_urandom(info_add):
165 import os
166
167 if hasattr(os, 'getrandom'):
168 # PEP 524: Check if system urandom is initialized
169 try:
170 try:
171 os.getrandom(1, os.GRND_NONBLOCK)
172 state = 'ready (initialized)'
173 except BlockingIOError as exc:
174 state = 'not seeded yet (%s)' % exc
175 info_add('os.getrandom', state)
176 except OSError as exc:
177 # Python was compiled on a more recent Linux version
178 # than the current Linux kernel: ignore OSError(ENOSYS)
179 if exc.errno != errno.ENOSYS:
180 raise
181
182
Victor Stinnerb907abc2017-08-17 16:40:51 +0200183def collect_os(info_add):
184 import os
185
Victor Stinnerad7eaed2017-08-18 12:08:47 +0200186 def format_attr(attr, value):
187 if attr in ('supports_follow_symlinks', 'supports_fd',
188 'supports_effective_ids'):
189 return str(sorted(func.__name__ for func in value))
190 else:
191 return value
192
193 attributes = (
194 'name',
195 'supports_bytes_environ',
196 'supports_effective_ids',
197 'supports_fd',
198 'supports_follow_symlinks',
199 )
200 copy_attributes(info_add, os, 'os.%s', attributes, formatter=format_attr)
Victor Stinnerb907abc2017-08-17 16:40:51 +0200201
Victor Stinner9cb27412019-06-25 13:37:27 +0200202 call_func(info_add, 'os.getcwd', os, 'getcwd')
Victor Stinnerb907abc2017-08-17 16:40:51 +0200203
Victor Stinner9cb27412019-06-25 13:37:27 +0200204 call_func(info_add, 'os.getuid', os, 'getuid')
205 call_func(info_add, 'os.getgid', os, 'getgid')
Victor Stinnerad7eaed2017-08-18 12:08:47 +0200206 call_func(info_add, 'os.uname', os, 'uname')
Victor Stinnerb907abc2017-08-17 16:40:51 +0200207
Victor Stinner5d39e042017-11-29 17:20:38 +0100208 def format_groups(groups):
209 return ', '.join(map(str, groups))
210
Victor Stinner9cb27412019-06-25 13:37:27 +0200211 call_func(info_add, 'os.getgroups', os, 'getgroups', formatter=format_groups)
Victor Stinnerb907abc2017-08-17 16:40:51 +0200212
213 if hasattr(os, 'getlogin'):
214 try:
215 login = os.getlogin()
216 except OSError:
217 # getlogin() fails with "OSError: [Errno 25] Inappropriate ioctl
218 # for device" on Travis CI
219 pass
220 else:
221 info_add("os.login", login)
222
Victor Stinner5d39e042017-11-29 17:20:38 +0100223 call_func(info_add, 'os.cpu_count', os, 'cpu_count')
Victor Stinner9cb27412019-06-25 13:37:27 +0200224 call_func(info_add, 'os.getloadavg', os, 'getloadavg')
Victor Stinnerb907abc2017-08-17 16:40:51 +0200225
Victor Stinner282c03d2018-11-26 17:03:16 +0100226 # Environment variables used by the stdlib and tests. Don't log the full
227 # environment: filter to list to not leak sensitive information.
228 #
229 # HTTP_PROXY is not logged because it can contain a password.
230 ENV_VARS = frozenset((
231 "APPDATA",
232 "AR",
233 "ARCHFLAGS",
234 "ARFLAGS",
235 "AUDIODEV",
Victor Stinnerb907abc2017-08-17 16:40:51 +0200236 "CC",
Victor Stinner282c03d2018-11-26 17:03:16 +0100237 "CFLAGS",
238 "COLUMNS",
239 "COMPUTERNAME",
Victor Stinnerb907abc2017-08-17 16:40:51 +0200240 "COMSPEC",
Victor Stinner282c03d2018-11-26 17:03:16 +0100241 "CPP",
242 "CPPFLAGS",
Victor Stinnerb907abc2017-08-17 16:40:51 +0200243 "DISPLAY",
Victor Stinner282c03d2018-11-26 17:03:16 +0100244 "DISTUTILS_DEBUG",
Victor Stinnerb907abc2017-08-17 16:40:51 +0200245 "DISTUTILS_USE_SDK",
246 "DYLD_LIBRARY_PATH",
Victor Stinner282c03d2018-11-26 17:03:16 +0100247 "ENSUREPIP_OPTIONS",
248 "HISTORY_FILE",
Victor Stinnerb907abc2017-08-17 16:40:51 +0200249 "HOME",
250 "HOMEDRIVE",
251 "HOMEPATH",
Victor Stinner282c03d2018-11-26 17:03:16 +0100252 "IDLESTARTUP",
Victor Stinnerb907abc2017-08-17 16:40:51 +0200253 "LANG",
Victor Stinner282c03d2018-11-26 17:03:16 +0100254 "LDFLAGS",
255 "LDSHARED",
Victor Stinnerb907abc2017-08-17 16:40:51 +0200256 "LD_LIBRARY_PATH",
Victor Stinner282c03d2018-11-26 17:03:16 +0100257 "LINES",
Victor Stinnerb907abc2017-08-17 16:40:51 +0200258 "MACOSX_DEPLOYMENT_TARGET",
Victor Stinner282c03d2018-11-26 17:03:16 +0100259 "MAILCAPS",
Victor Stinnerb907abc2017-08-17 16:40:51 +0200260 "MAKEFLAGS",
Victor Stinner282c03d2018-11-26 17:03:16 +0100261 "MIXERDEV",
Victor Stinnerb907abc2017-08-17 16:40:51 +0200262 "MSSDK",
263 "PATH",
Victor Stinner282c03d2018-11-26 17:03:16 +0100264 "PATHEXT",
265 "PIP_CONFIG_FILE",
266 "PLAT",
267 "POSIXLY_CORRECT",
268 "PY_SAX_PARSER",
269 "ProgramFiles",
270 "ProgramFiles(x86)",
271 "RUNNING_ON_VALGRIND",
Victor Stinnerb907abc2017-08-17 16:40:51 +0200272 "SDK_TOOLS_BIN",
Victor Stinner282c03d2018-11-26 17:03:16 +0100273 "SERVER_SOFTWARE",
Victor Stinnerb907abc2017-08-17 16:40:51 +0200274 "SHELL",
Victor Stinner282c03d2018-11-26 17:03:16 +0100275 "SOURCE_DATE_EPOCH",
276 "SYSTEMROOT",
Victor Stinnerb907abc2017-08-17 16:40:51 +0200277 "TEMP",
278 "TERM",
Victor Stinner282c03d2018-11-26 17:03:16 +0100279 "TILE_LIBRARY",
280 "TIX_LIBRARY",
Victor Stinnerb907abc2017-08-17 16:40:51 +0200281 "TMP",
282 "TMPDIR",
Victor Stinnerc11b3b12018-12-05 01:58:31 +0100283 "TRAVIS",
Victor Stinner282c03d2018-11-26 17:03:16 +0100284 "TZ",
Victor Stinnerb907abc2017-08-17 16:40:51 +0200285 "USERPROFILE",
Victor Stinner282c03d2018-11-26 17:03:16 +0100286 "VIRTUAL_ENV",
Victor Stinnerb907abc2017-08-17 16:40:51 +0200287 "WAYLAND_DISPLAY",
Victor Stinner282c03d2018-11-26 17:03:16 +0100288 "WINDIR",
289 "_PYTHON_HOST_PLATFORM",
290 "_PYTHON_PROJECT_BASE",
291 "_PYTHON_SYSCONFIGDATA_NAME",
292 "__PYVENV_LAUNCHER__",
293 ))
Victor Stinnerb907abc2017-08-17 16:40:51 +0200294 for name, value in os.environ.items():
295 uname = name.upper()
Victor Stinner5d39e042017-11-29 17:20:38 +0100296 if (uname in ENV_VARS
297 # Copy PYTHON* and LC_* variables
298 or uname.startswith(("PYTHON", "LC_"))
Victor Stinnerb907abc2017-08-17 16:40:51 +0200299 # Visual Studio: VS140COMNTOOLS
300 or (uname.startswith("VS") and uname.endswith("COMNTOOLS"))):
301 info_add('os.environ[%s]' % name, value)
302
Victor Stinnerad7eaed2017-08-18 12:08:47 +0200303 if hasattr(os, 'umask'):
304 mask = os.umask(0)
305 os.umask(mask)
306 info_add("os.umask", '%03o' % mask)
307
Victor Stinner9cb27412019-06-25 13:37:27 +0200308
309def collect_pwd(info_add):
310 try:
311 import pwd
312 except ImportError:
313 return
314 import os
315
316 uid = os.getuid()
317 try:
318 entry = pwd.getpwuid(uid)
319 except KeyError:
320 entry = None
321
322 info_add('pwd.getpwuid(%s)'% uid,
323 entry if entry is not None else '<KeyError>')
324
325 if entry is None:
326 # there is nothing interesting to read if the current user identifier
327 # is not the password database
328 return
329
330 if hasattr(os, 'getgrouplist'):
331 groups = os.getgrouplist(entry.pw_name, entry.pw_gid)
332 groups = ', '.join(map(str, groups))
333 info_add('os.getgrouplist', groups)
Victor Stinnerad7eaed2017-08-18 12:08:47 +0200334
Victor Stinnerb907abc2017-08-17 16:40:51 +0200335
336def collect_readline(info_add):
337 try:
338 import readline
339 except ImportError:
340 return
341
342 def format_attr(attr, value):
343 if isinstance(value, int):
344 return "%#x" % value
345 else:
346 return value
347
348 attributes = (
349 "_READLINE_VERSION",
350 "_READLINE_RUNTIME_VERSION",
351 "_READLINE_LIBRARY_VERSION",
352 )
353 copy_attributes(info_add, readline, 'readline.%s', attributes,
354 formatter=format_attr)
355
Victor Stinneref634b52018-06-01 11:04:29 +0200356 if not hasattr(readline, "_READLINE_LIBRARY_VERSION"):
357 # _READLINE_LIBRARY_VERSION has been added to CPython 3.7
358 doc = getattr(readline, '__doc__', '')
359 if 'libedit readline' in doc:
360 info_add('readline.library', 'libedit readline')
361 elif 'GNU readline' in doc:
362 info_add('readline.library', 'GNU readline')
363
Victor Stinnerb907abc2017-08-17 16:40:51 +0200364
365def collect_gdb(info_add):
366 import subprocess
367
368 try:
369 proc = subprocess.Popen(["gdb", "-nx", "--version"],
370 stdout=subprocess.PIPE,
371 stderr=subprocess.PIPE,
372 universal_newlines=True)
373 version = proc.communicate()[0]
374 except OSError:
375 return
376
377 # Only keep the first line
378 version = version.splitlines()[0]
379 info_add('gdb_version', version)
380
381
382def collect_tkinter(info_add):
383 try:
384 import _tkinter
385 except ImportError:
386 pass
387 else:
388 attributes = ('TK_VERSION', 'TCL_VERSION')
389 copy_attributes(info_add, _tkinter, 'tkinter.%s', attributes)
390
391 try:
392 import tkinter
393 except ImportError:
394 pass
395 else:
396 tcl = tkinter.Tcl()
397 patchlevel = tcl.call('info', 'patchlevel')
398 info_add('tkinter.info_patchlevel', patchlevel)
399
400
401def collect_time(info_add):
402 import time
403
Victor Stinner7d91c022018-01-17 16:35:45 +0100404 info_add('time.time', time.time())
405
Victor Stinnerad7eaed2017-08-18 12:08:47 +0200406 attributes = (
407 'altzone',
408 'daylight',
409 'timezone',
410 'tzname',
411 )
412 copy_attributes(info_add, time, 'time.%s', attributes)
413
Victor Stinner5d39e042017-11-29 17:20:38 +0100414 if hasattr(time, 'get_clock_info'):
Victor Stinnerddd7c422019-01-08 01:27:27 +0100415 for clock in ('clock', 'monotonic', 'perf_counter',
416 'process_time', 'thread_time', 'time'):
417 try:
418 # prevent DeprecatingWarning on get_clock_info('clock')
419 with warnings.catch_warnings(record=True):
420 clock_info = time.get_clock_info(clock)
421 except ValueError:
422 # missing clock like time.thread_time()
423 pass
424 else:
425 info_add('time.get_clock_info(%s)' % clock, clock_info)
Victor Stinner7d91c022018-01-17 16:35:45 +0100426
427
428def collect_datetime(info_add):
429 try:
430 import datetime
431 except ImportError:
432 return
433
434 info_add('datetime.datetime.now', datetime.datetime.now())
Victor Stinnerb907abc2017-08-17 16:40:51 +0200435
436
437def collect_sysconfig(info_add):
438 import sysconfig
439
440 for name in (
441 'ABIFLAGS',
442 'ANDROID_API_LEVEL',
443 'CC',
444 'CCSHARED',
445 'CFLAGS',
446 'CFLAGSFORSHARED',
Victor Stinnerb907abc2017-08-17 16:40:51 +0200447 'CONFIG_ARGS',
448 'HOST_GNU_TYPE',
449 'MACHDEP',
450 'MULTIARCH',
451 'OPT',
452 'PY_CFLAGS',
453 'PY_CFLAGS_NODIST',
stratakiscf10a752018-12-19 18:19:01 +0100454 'PY_CORE_LDFLAGS',
Victor Stinner5d39e042017-11-29 17:20:38 +0100455 'PY_LDFLAGS',
stratakiscf10a752018-12-19 18:19:01 +0100456 'PY_LDFLAGS_NODIST',
457 'PY_STDMODULE_CFLAGS',
Victor Stinnerb907abc2017-08-17 16:40:51 +0200458 'Py_DEBUG',
459 'Py_ENABLE_SHARED',
460 'SHELL',
461 'SOABI',
462 'prefix',
463 ):
464 value = sysconfig.get_config_var(name)
465 if name == 'ANDROID_API_LEVEL' and not value:
466 # skip ANDROID_API_LEVEL=0
467 continue
468 value = normalize_text(value)
469 info_add('sysconfig[%s]' % name, value)
470
471
472def collect_ssl(info_add):
473 try:
474 import ssl
475 except ImportError:
476 return
477
478 def format_attr(attr, value):
479 if attr.startswith('OP_'):
480 return '%#8x' % value
481 else:
Victor Stinnerad7eaed2017-08-18 12:08:47 +0200482 return value
Victor Stinnerb907abc2017-08-17 16:40:51 +0200483
484 attributes = (
485 'OPENSSL_VERSION',
486 'OPENSSL_VERSION_INFO',
487 'HAS_SNI',
488 'OP_ALL',
489 'OP_NO_TLSv1_1',
490 )
491 copy_attributes(info_add, ssl, 'ssl.%s', attributes, formatter=format_attr)
492
493
494def collect_socket(info_add):
495 import socket
496
497 hostname = socket.gethostname()
498 info_add('socket.hostname', hostname)
499
500
501def collect_sqlite(info_add):
502 try:
503 import sqlite3
504 except ImportError:
505 return
506
507 attributes = ('version', 'sqlite_version')
508 copy_attributes(info_add, sqlite3, 'sqlite3.%s', attributes)
509
510
511def collect_zlib(info_add):
512 try:
513 import zlib
514 except ImportError:
515 return
516
517 attributes = ('ZLIB_VERSION', 'ZLIB_RUNTIME_VERSION')
518 copy_attributes(info_add, zlib, 'zlib.%s', attributes)
519
520
Victor Stinnerf6ebd832017-08-17 22:13:11 +0200521def collect_expat(info_add):
522 try:
523 from xml.parsers import expat
524 except ImportError:
525 return
526
527 attributes = ('EXPAT_VERSION',)
528 copy_attributes(info_add, expat, 'expat.%s', attributes)
529
530
531def collect_decimal(info_add):
532 try:
533 import _decimal
534 except ImportError:
535 return
536
537 attributes = ('__libmpdec_version__',)
538 copy_attributes(info_add, _decimal, '_decimal.%s', attributes)
539
540
Victor Stinner5d39e042017-11-29 17:20:38 +0100541def collect_testcapi(info_add):
542 try:
543 import _testcapi
544 except ImportError:
545 return
546
547 call_func(info_add, 'pymem.allocator', _testcapi, 'pymem_getallocatorsname')
548 copy_attr(info_add, 'pymem.with_pymalloc', _testcapi, 'WITH_PYMALLOC')
549
550
Victor Stinner98146972017-12-13 17:27:40 +0100551def collect_resource(info_add):
552 try:
553 import resource
554 except ImportError:
555 return
556
557 limits = [attr for attr in dir(resource) if attr.startswith('RLIMIT_')]
558 for name in limits:
559 key = getattr(resource, name)
560 value = resource.getrlimit(key)
561 info_add('resource.%s' % name, value)
562
Victor Stinnerb2385452019-01-21 10:24:12 +0100563 call_func(info_add, 'resource.pagesize', resource, 'getpagesize')
564
Victor Stinner98146972017-12-13 17:27:40 +0100565
566def collect_test_socket(info_add):
567 try:
568 from test import test_socket
569 except ImportError:
570 return
571
572 # all check attributes like HAVE_SOCKET_CAN
573 attributes = [name for name in dir(test_socket)
574 if name.startswith('HAVE_')]
575 copy_attributes(info_add, test_socket, 'test_socket.%s', attributes)
576
577
578def collect_test_support(info_add):
579 try:
580 from test import support
581 except ImportError:
582 return
583
584 attributes = ('IPV6_ENABLED',)
585 copy_attributes(info_add, support, 'test_support.%s', attributes)
586
587 call_func(info_add, 'test_support._is_gui_available', support, '_is_gui_available')
588 call_func(info_add, 'test_support.python_is_optimized', support, 'python_is_optimized')
589
590
Victor Stinner56013212018-06-01 00:33:03 +0200591def collect_cc(info_add):
592 import subprocess
593 import sysconfig
594
595 CC = sysconfig.get_config_var('CC')
596 if not CC:
597 return
598
599 try:
600 import shlex
601 args = shlex.split(CC)
602 except ImportError:
603 args = CC.split()
604 args.append('--version')
xdegayea86e0642019-04-29 14:53:30 +0200605 try:
606 proc = subprocess.Popen(args,
607 stdout=subprocess.PIPE,
608 stderr=subprocess.STDOUT,
609 universal_newlines=True)
610 except OSError:
611 # Cannot run the compiler, for example when Python has been
612 # cross-compiled and installed on the target platform where the
613 # compiler is missing.
614 return
615
Victor Stinner56013212018-06-01 00:33:03 +0200616 stdout = proc.communicate()[0]
617 if proc.returncode:
618 # CC --version failed: ignore error
619 return
620
621 text = stdout.splitlines()[0]
622 text = normalize_text(text)
623 info_add('CC.version', text)
624
625
Victor Stinner00f9edb2018-06-19 23:29:22 +0200626def collect_gdbm(info_add):
627 try:
Xiang Zhangb248e952018-06-20 21:23:30 +0800628 from _gdbm import _GDBM_VERSION
Victor Stinner00f9edb2018-06-19 23:29:22 +0200629 except ImportError:
630 return
631
Xiang Zhangb248e952018-06-20 21:23:30 +0800632 info_add('gdbm.GDBM_VERSION', '.'.join(map(str, _GDBM_VERSION)))
Victor Stinner00f9edb2018-06-19 23:29:22 +0200633
634
Victor Stinner00b137c2018-11-13 19:59:26 +0100635def collect_get_config(info_add):
Victor Stinner5f38b842019-05-01 02:30:12 +0200636 # Get global configuration variables, _PyPreConfig and _PyCoreConfig
Victor Stinner2094c2b2018-09-03 17:06:39 +0200637 try:
Victor Stinner23bace22019-04-18 11:37:26 +0200638 from _testinternalcapi import get_configs
Victor Stinner2094c2b2018-09-03 17:06:39 +0200639 except ImportError:
Victor Stinner7ddd56f2018-11-14 00:24:28 +0100640 return
Victor Stinner2094c2b2018-09-03 17:06:39 +0200641
Victor Stinner1075d162019-03-25 23:19:57 +0100642 all_configs = get_configs()
643 for config_type in sorted(all_configs):
644 config = all_configs[config_type]
Victor Stinner00b137c2018-11-13 19:59:26 +0100645 for key in sorted(config):
Victor Stinner1075d162019-03-25 23:19:57 +0100646 info_add('%s[%s]' % (config_type, key), repr(config[key]))
Victor Stinner2094c2b2018-09-03 17:06:39 +0200647
648
Victor Stinner9daecf32019-01-16 00:02:35 +0100649def collect_subprocess(info_add):
650 import subprocess
Victor Stinner8c349562019-01-16 23:38:06 +0100651 copy_attributes(info_add, subprocess, 'subprocess.%s', ('_USE_POSIX_SPAWN',))
Victor Stinner9daecf32019-01-16 00:02:35 +0100652
653
Victor Stinnerb907abc2017-08-17 16:40:51 +0200654def collect_info(info):
655 error = False
656 info_add = info.add
657
658 for collect_func in (
Victor Stinner9cb27412019-06-25 13:37:27 +0200659 # collect_urandom() must be the first, to check the getrandom() status.
660 # Other functions may block on os.urandom() indirectly and so change
661 # its state.
662 collect_urandom,
Victor Stinnerb907abc2017-08-17 16:40:51 +0200663
Victor Stinner98146972017-12-13 17:27:40 +0100664 collect_builtins,
Victor Stinner9cb27412019-06-25 13:37:27 +0200665 collect_cc,
666 collect_datetime,
667 collect_decimal,
668 collect_expat,
Victor Stinnerb907abc2017-08-17 16:40:51 +0200669 collect_gdb,
Victor Stinner9cb27412019-06-25 13:37:27 +0200670 collect_gdbm,
671 collect_get_config,
Victor Stinnerb907abc2017-08-17 16:40:51 +0200672 collect_locale,
Victor Stinner9cb27412019-06-25 13:37:27 +0200673 collect_os,
Victor Stinnerb907abc2017-08-17 16:40:51 +0200674 collect_platform,
Victor Stinner9cb27412019-06-25 13:37:27 +0200675 collect_pwd,
Victor Stinnerb907abc2017-08-17 16:40:51 +0200676 collect_readline,
Victor Stinner9cb27412019-06-25 13:37:27 +0200677 collect_resource,
Victor Stinnerb907abc2017-08-17 16:40:51 +0200678 collect_socket,
679 collect_sqlite,
680 collect_ssl,
Victor Stinner9cb27412019-06-25 13:37:27 +0200681 collect_subprocess,
Victor Stinnerb907abc2017-08-17 16:40:51 +0200682 collect_sys,
683 collect_sysconfig,
Victor Stinner9cb27412019-06-25 13:37:27 +0200684 collect_testcapi,
Victor Stinnerb907abc2017-08-17 16:40:51 +0200685 collect_time,
686 collect_tkinter,
687 collect_zlib,
Victor Stinner98146972017-12-13 17:27:40 +0100688
689 # Collecting from tests should be last as they have side effects.
690 collect_test_socket,
691 collect_test_support,
Victor Stinnerb907abc2017-08-17 16:40:51 +0200692 ):
693 try:
694 collect_func(info_add)
695 except Exception as exc:
696 error = True
697 print("ERROR: %s() failed" % (collect_func.__name__),
698 file=sys.stderr)
699 traceback.print_exc(file=sys.stderr)
700 print(file=sys.stderr)
701 sys.stderr.flush()
702
703 return error
704
705
706def dump_info(info, file=None):
707 title = "Python debug information"
708 print(title)
709 print("=" * len(title))
710 print()
711
712 infos = info.get_infos()
713 infos = sorted(infos.items())
714 for key, value in infos:
715 value = value.replace("\n", " ")
716 print("%s: %s" % (key, value))
717 print()
718
719
720def main():
721 info = PythonInfo()
722 error = collect_info(info)
723 dump_info(info)
724
725 if error:
726 print("Collection failed: exit with error", file=sys.stderr)
727 sys.exit(1)
728
729
730if __name__ == "__main__":
731 main()