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