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