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