1"""Module containing bug report helper(s).""" 2from __future__ import print_function 3 4import json 5import platform 6import sys 7import ssl 8 9import idna 10import urllib3 11import chardet 12 13from . import __version__ as requests_version 14 15try: 16 from urllib3.contrib import pyopenssl 17except ImportError: 18 pyopenssl = None 19 OpenSSL = None 20 cryptography = None 21else: 22 import OpenSSL 23 import cryptography 24 25 26def _implementation(): 27 """Return a dict with the Python implementation and version. 28 29 Provide both the name and the version of the Python implementation 30 currently running. For example, on CPython 2.7.5 it will return 31 {'name': 'CPython', 'version': '2.7.5'}. 32 33 This function works best on CPython and PyPy: in particular, it probably 34 doesn't work for Jython or IronPython. Future investigation should be done 35 to work out the correct shape of the code for those platforms. 36 """ 37 implementation = platform.python_implementation() 38 39 if implementation == 'CPython': 40 implementation_version = platform.python_version() 41 elif implementation == 'PyPy': 42 implementation_version = '%s.%s.%s' % (sys.pypy_version_info.major, 43 sys.pypy_version_info.minor, 44 sys.pypy_version_info.micro) 45 if sys.pypy_version_info.releaselevel != 'final': 46 implementation_version = ''.join([ 47 implementation_version, sys.pypy_version_info.releaselevel 48 ]) 49 elif implementation == 'Jython': 50 implementation_version = platform.python_version() # Complete Guess 51 elif implementation == 'IronPython': 52 implementation_version = platform.python_version() # Complete Guess 53 else: 54 implementation_version = 'Unknown' 55 56 return {'name': implementation, 'version': implementation_version} 57 58 59def info(): 60 """Generate information for a bug report.""" 61 try: 62 platform_info = { 63 'system': platform.system(), 64 'release': platform.release(), 65 } 66 except IOError: 67 platform_info = { 68 'system': 'Unknown', 69 'release': 'Unknown', 70 } 71 72 implementation_info = _implementation() 73 urllib3_info = {'version': urllib3.__version__} 74 chardet_info = {'version': chardet.__version__} 75 76 pyopenssl_info = { 77 'version': None, 78 'openssl_version': '', 79 } 80 if OpenSSL: 81 pyopenssl_info = { 82 'version': OpenSSL.__version__, 83 'openssl_version': '%x' % OpenSSL.SSL.OPENSSL_VERSION_NUMBER, 84 } 85 cryptography_info = { 86 'version': getattr(cryptography, '__version__', ''), 87 } 88 idna_info = { 89 'version': getattr(idna, '__version__', ''), 90 } 91 92 system_ssl = ssl.OPENSSL_VERSION_NUMBER 93 system_ssl_info = { 94 'version': '%x' % system_ssl if system_ssl is not None else '' 95 } 96 97 return { 98 'platform': platform_info, 99 'implementation': implementation_info, 100 'system_ssl': system_ssl_info, 101 'using_pyopenssl': pyopenssl is not None, 102 'pyOpenSSL': pyopenssl_info, 103 'urllib3': urllib3_info, 104 'chardet': chardet_info, 105 'cryptography': cryptography_info, 106 'idna': idna_info, 107 'requests': { 108 'version': requests_version, 109 }, 110 } 111 112 113def main(): 114 """Pretty-print the bug information as JSON.""" 115 print(json.dumps(info(), sort_keys=True, indent=2)) 116 117 118if __name__ == '__main__': 119 main() 120