From: Victor Stinner Date: Wed, 13 Dec 2017 22:23:40 +0000 (+0100) Subject: pythoninfo: sync with master (#4843) X-Git-Tag: v2.7.15rc1~98 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=2316c686400841fe1131583820d5b14417a0e089;p=python pythoninfo: sync with master (#4843) --- diff --git a/Lib/test/pythoninfo.py b/Lib/test/pythoninfo.py index 8b029330a2..4ce06e00eb 100644 --- a/Lib/test/pythoninfo.py +++ b/Lib/test/pythoninfo.py @@ -1,7 +1,8 @@ """ -Collect various informations about Python to help debugging test failures. +Collect various information about Python to help debugging test failures. """ from __future__ import print_function +import errno import re import sys import traceback @@ -26,8 +27,8 @@ class PythonInfo: if value is None: return - if not isinstance(value, (int, long)): - if not isinstance(value, basestring): + if not isinstance(value, int): + if not isinstance(value, str): # convert other objects like sys.flags to string value = str(value) @@ -39,7 +40,7 @@ class PythonInfo: def get_infos(self): """ - Get informations as a key:value dictionary where values are strings. + Get information as a key:value dictionary where values are strings. """ return {key: str(value) for key, value in self.info.items()} @@ -55,6 +56,14 @@ def copy_attributes(info_add, obj, name_fmt, attributes, formatter=None): info_add(name, value) +def copy_attr(info_add, name, mod, attr_name): + try: + value = getattr(mod, attr_name) + except AttributeError: + return + info_add(name, value) + + def call_func(info_add, name, mod, func_name, formatter=None): try: func = getattr(mod, func_name) @@ -68,6 +77,8 @@ def call_func(info_add, name, mod, func_name, formatter=None): def collect_sys(info_add): attributes = ( + '_framework', + 'abiflags', 'api_version', 'builtin_module_names', 'byteorder', @@ -76,20 +87,28 @@ def collect_sys(info_add): 'flags', 'float_info', 'float_repr_style', + 'hash_info', 'hexversion', - 'maxint', + 'implementation', + 'int_info', 'maxsize', 'maxunicode', 'path', 'platform', 'prefix', + 'thread_info', 'version', 'version_info', 'winver', ) copy_attributes(info_add, sys, 'sys.%s', attributes) + call_func(info_add, 'sys.androidapilevel', sys, 'getandroidapilevel') + call_func(info_add, 'sys.windowsversion', sys, 'getwindowsversion') + encoding = sys.getfilesystemencoding() + if hasattr(sys, 'getfilesystemencodeerrors'): + encoding = '%s/%s' % (encoding, sys.getfilesystemencodeerrors()) info_add('sys.filesystem_encoding', encoding) for name in ('stdin', 'stdout', 'stderr'): @@ -129,26 +148,43 @@ def collect_platform(info_add): def collect_locale(info_add): import locale - info_add('locale.encoding', locale.getpreferredencoding(True)) + info_add('locale.encoding', locale.getpreferredencoding(False)) + + +def collect_builtins(info_add): + info_add('builtins.float.float_format', float.__getformat__("float")) + info_add('builtins.float.double_format', float.__getformat__("double")) def collect_os(info_add): import os - attributes = ('name',) - copy_attributes(info_add, os, 'os.%s', attributes) + def format_attr(attr, value): + if attr in ('supports_follow_symlinks', 'supports_fd', + 'supports_effective_ids'): + return str(sorted(func.__name__ for func in value)) + else: + return value - info_add("os.cwd", os.getcwd()) + attributes = ( + 'name', + 'supports_bytes_environ', + 'supports_effective_ids', + 'supports_fd', + 'supports_follow_symlinks', + ) + copy_attributes(info_add, os, 'os.%s', attributes, formatter=format_attr) + + call_func(info_add, 'os.cwd', os, 'getcwd') call_func(info_add, 'os.uid', os, 'getuid') call_func(info_add, 'os.gid', os, 'getgid') call_func(info_add, 'os.uname', os, 'uname') - if hasattr(os, 'getgroups'): - groups = os.getgroups() - groups = map(str, groups) - groups = ', '.join(groups) - info_add("os.groups", groups) + def format_groups(groups): + return ', '.join(map(str, groups)) + + call_func(info_add, 'os.groups', os, 'getgroups', formatter=format_groups) if hasattr(os, 'getlogin'): try: @@ -160,6 +196,7 @@ def collect_os(info_add): else: info_add("os.login", login) + call_func(info_add, 'os.cpu_count', os, 'cpu_count') call_func(info_add, 'os.loadavg', os, 'getloadavg') # Get environment variables: filter to list @@ -190,7 +227,9 @@ def collect_os(info_add): ) for name, value in os.environ.items(): uname = name.upper() - if (uname in ENV_VARS or uname.startswith(("PYTHON", "LC_")) + if (uname in ENV_VARS + # Copy PYTHON* and LC_* variables + or uname.startswith(("PYTHON", "LC_")) # Visual Studio: VS140COMNTOOLS or (uname.startswith("VS") and uname.endswith("COMNTOOLS"))): info_add('os.environ[%s]' % name, value) @@ -200,13 +239,20 @@ def collect_os(info_add): os.umask(mask) info_add("os.umask", '%03o' % mask) - try: - cpu_count = os.sysconf('SC_NPROCESSORS_ONLN') - except (AttributeError, ValueError): - pass - else: - if cpu_count: - info_add('os.sysconf(SC_NPROCESSORS_ONLN)', cpu_count) + if hasattr(os, 'getrandom'): + # PEP 524: Check if system urandom is initialized + try: + try: + os.getrandom(1, os.GRND_NONBLOCK) + state = 'ready (initialized)' + except BlockingIOError as exc: + state = 'not seeded yet (%s)' % exc + info_add('os.getrandom', state) + except OSError as exc: + # Python was compiled on a more recent Linux version + # than the current Linux kernel: ignore OSError(ENOSYS) + if exc.errno != errno.ENOSYS: + raise def collect_readline(info_add): @@ -216,7 +262,7 @@ def collect_readline(info_add): return def format_attr(attr, value): - if isinstance(value, (int, long)): + if isinstance(value, int): return "%#x" % value else: return value @@ -224,6 +270,7 @@ def collect_readline(info_add): attributes = ( "_READLINE_VERSION", "_READLINE_RUNTIME_VERSION", + "_READLINE_LIBRARY_VERSION", ) copy_attributes(info_add, readline, 'readline.%s', attributes, formatter=format_attr) @@ -256,11 +303,11 @@ def collect_tkinter(info_add): copy_attributes(info_add, _tkinter, 'tkinter.%s', attributes) try: - import Tkinter + import tkinter except ImportError: pass else: - tcl = Tkinter.Tcl() + tcl = tkinter.Tcl() patchlevel = tcl.call('info', 'patchlevel') info_add('tkinter.info_patchlevel', patchlevel) @@ -276,6 +323,11 @@ def collect_time(info_add): ) copy_attributes(info_add, time, 'time.%s', attributes) + if hasattr(time, 'get_clock_info'): + for clock in ('time', 'perf_counter'): + tinfo = time.get_clock_info(clock) + info_add('time.%s' % clock, tinfo) + def collect_sysconfig(info_add): import sysconfig @@ -287,7 +339,6 @@ def collect_sysconfig(info_add): 'CCSHARED', 'CFLAGS', 'CFLAGSFORSHARED', - 'PY_LDFLAGS', 'CONFIG_ARGS', 'HOST_GNU_TYPE', 'MACHDEP', @@ -295,6 +346,7 @@ def collect_sysconfig(info_add): 'OPT', 'PY_CFLAGS', 'PY_CFLAGS_NODIST', + 'PY_LDFLAGS', 'Py_DEBUG', 'Py_ENABLE_SHARED', 'SHELL', @@ -368,15 +420,62 @@ def collect_expat(info_add): copy_attributes(info_add, expat, 'expat.%s', attributes) -def collect_multiprocessing(info_add): +def collect_decimal(info_add): + try: + import _decimal + except ImportError: + return + + attributes = ('__libmpdec_version__',) + copy_attributes(info_add, _decimal, '_decimal.%s', attributes) + + +def collect_testcapi(info_add): + try: + import _testcapi + except ImportError: + return + + call_func(info_add, 'pymem.allocator', _testcapi, 'pymem_getallocatorsname') + copy_attr(info_add, 'pymem.with_pymalloc', _testcapi, 'WITH_PYMALLOC') + + +def collect_resource(info_add): + try: + import resource + except ImportError: + return + + limits = [attr for attr in dir(resource) if attr.startswith('RLIMIT_')] + for name in limits: + key = getattr(resource, name) + value = resource.getrlimit(key) + info_add('resource.%s' % name, value) + + +def collect_test_socket(info_add): try: - import multiprocessing + from test import test_socket except ImportError: return - cpu_count = multiprocessing.cpu_count() - if cpu_count: - info_add('multiprocessing.cpu_count', cpu_count) + # all check attributes like HAVE_SOCKET_CAN + attributes = [name for name in dir(test_socket) + if name.startswith('HAVE_')] + copy_attributes(info_add, test_socket, 'test_socket.%s', attributes) + + +def collect_test_support(info_add): + try: + from test import support + except ImportError: + return + + attributes = ('IPV6_ENABLED',) + copy_attributes(info_add, support, 'test_support.%s', attributes) + + call_func(info_add, 'test_support._is_gui_available', support, '_is_gui_available') + call_func(info_add, 'test_support.python_is_optimized', support, 'python_is_optimized') def collect_info(info): @@ -384,10 +483,12 @@ def collect_info(info): info_add = info.add for collect_func in ( - collect_expat, + # collect_os() should be the first, to check the getrandom() status + collect_os, + + collect_builtins, collect_gdb, collect_locale, - collect_os, collect_platform, collect_readline, collect_socket, @@ -398,7 +499,14 @@ def collect_info(info): collect_time, collect_tkinter, collect_zlib, - collect_multiprocessing, + collect_expat, + collect_decimal, + collect_testcapi, + collect_resource, + + # Collecting from tests should be last as they have side effects. + collect_test_socket, + collect_test_support, ): try: collect_func(info_add) diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py index 1126fc2b77..ca53899418 100644 --- a/Lib/test/test_socket.py +++ b/Lib/test/test_socket.py @@ -35,7 +35,7 @@ def try_address(host, port=0, family=socket.AF_INET): HOST = test_support.HOST MSG = b'Michael Gilfix was here\n' -SUPPORTS_IPV6 = socket.has_ipv6 and try_address('::1', family=socket.AF_INET6) +SUPPORTS_IPV6 = test_support.IPV6_ENABLED try: import thread