"""Module containing bug report helper(s).""" import json import platform import ssl import sys import idna import urllib3 from . import __version__ as requests_version try: import charset_normalizer except ImportError: charset_normalizer = None try: import chardet except ImportError: chardet = None try: from urllib3.contrib import pyopenssl except ImportError: pyopenssl = None OpenSSL = None cryptography = None else: import cryptography import OpenSSL def _implementation(): """Return a dict with the Python implementation and version. Provide both the name and the version of the Python implementation currently running. For example, on CPython 3.10.3 it will return {'name': 'CPython', 'version': '3.10.3'}. This function works best on CPython and PyPy: in particular, it probably doesn't work for Jython or IronPython. Future investigation should be done to work out the correct shape of the code for those platforms. """ implementation = platform.python_implementation() if implementation == "CPython": implementation_version = platform.python_version() elif implementation == "PyPy": implementation_version = "{}.{}.{}".format( sys.pypy_version_info.major, sys.pypy_version_info.minor, sys.pypy_version_info.micro, ) if sys.pypy_version_info.releaselevel != "final": implementation_version = "".join( [implementation_version, sys.pypy_version_info.releaselevel] ) elif implementation == "Jython": implementation_version = platform.python_version() # Complete Guess elif implementation == "IronPython": implementation_version = platform.python_version() # Complete Guess else: implementation_version = "Unknown" return {"name": implementation, "version": implementation_version} def info(): """Generate information for a bug report.""" try: platform_info = { "system": platform.system(), "release": platform.release(), } except OSError: platform_info = { "system": "Unknown", "release": "Unknown", } implementation_info = _implementation() urllib3_info = {"version": urllib3.__version__} charset_normalizer_info = {"version": None} chardet_info = {"version": None} if charset_normalizer: charset_normalizer_info = {"version": charset_normalizer.__version__} if chardet: chardet_info = {"version": chardet.__version__} pyopenssl_info = { "version": None, "openssl_version": "", } if OpenSSL: pyopenssl_info = { "version": OpenSSL.__version__, "openssl_version": f"{OpenSSL.SSL.OPENSSL_VERSION_NUMBER:x}", } cryptography_info = { "version": getattr(cryptography, "__version__", ""), } idna_info = { "version": getattr(idna, "__version__", ""), } system_ssl = ssl.OPENSSL_VERSION_NUMBER system_ssl_info = {"version": f"{system_ssl:x}" if system_ssl is not None else ""} return { "platform": platform_info, "implementation": implementation_info, "system_ssl": system_ssl_info, "using_pyopenssl": pyopenssl is not None, "using_charset_normalizer": chardet is None, "pyOpenSSL": pyopenssl_info, "urllib3": urllib3_info, "chardet": chardet_info, "charset_normalizer": charset_normalizer_info, "cryptography": cryptography_info, "idna": idna_info, "requests": { "version": requests_version, }, } def main(): """Pretty-print the bug information as JSON.""" print(json.dumps(info(), sort_keys=True, indent=2)) if __name__ == "__main__": main()