Jellyfin(8096), OrbStack(8097) 포트 충돌으로 변경. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
228 lines
7.1 KiB
Python
228 lines
7.1 KiB
Python
"""Module containing bug report helper(s)."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import json
|
|
import platform
|
|
|
|
try:
|
|
import ssl
|
|
except ImportError:
|
|
ssl = None # type: ignore
|
|
|
|
import sys
|
|
import warnings
|
|
from json import JSONDecodeError
|
|
|
|
import charset_normalizer
|
|
import h11
|
|
|
|
try:
|
|
import idna # type: ignore[import-not-found]
|
|
except ImportError:
|
|
idna = None # type: ignore[assignment]
|
|
|
|
import jh2 # type: ignore
|
|
import wassima
|
|
|
|
from . import HTTPError, RequestException, Session
|
|
from . import __version__ as niquests_version
|
|
from ._compat import HAS_LEGACY_URLLIB3
|
|
|
|
if HAS_LEGACY_URLLIB3 is True:
|
|
import urllib3_future as urllib3
|
|
|
|
try:
|
|
from urllib3 import __version__ as __legacy_urllib3_version__
|
|
except (ImportError, AttributeError):
|
|
__legacy_urllib3_version__ = None # type: ignore[assignment]
|
|
else:
|
|
import urllib3 # type: ignore[no-redef]
|
|
|
|
__legacy_urllib3_version__ = None # type: ignore[assignment]
|
|
|
|
try:
|
|
import qh3 # type: ignore
|
|
except ImportError:
|
|
qh3 = None # type: ignore
|
|
|
|
try:
|
|
import certifi # type: ignore
|
|
except ImportError:
|
|
certifi = None # type: ignore
|
|
|
|
try:
|
|
from .extensions.revocation._ocsp import verify as ocsp_verify
|
|
except ImportError:
|
|
ocsp_verify = None # type: ignore
|
|
|
|
try:
|
|
import wsproto # type: ignore[import-not-found]
|
|
except ImportError:
|
|
wsproto = None # type: ignore
|
|
|
|
|
|
_IS_GIL_DISABLED: bool = hasattr(sys, "_is_gil_enabled") and sys._is_gil_enabled() is False
|
|
|
|
|
|
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 = (
|
|
f"{sys.pypy_version_info.major}" # type: ignore[attr-defined]
|
|
f".{sys.pypy_version_info.minor}" # type: ignore[attr-defined]
|
|
f".{sys.pypy_version_info.micro}" # type: ignore[attr-defined]
|
|
)
|
|
if sys.pypy_version_info.releaselevel != "final": # type: ignore[attr-defined]
|
|
implementation_version = "".join(
|
|
[implementation_version, sys.pypy_version_info.releaselevel] # type: ignore[attr-defined]
|
|
)
|
|
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__,
|
|
"cohabitation_version": __legacy_urllib3_version__,
|
|
}
|
|
|
|
charset_normalizer_info = {"version": charset_normalizer.__version__}
|
|
|
|
idna_info = {
|
|
"version": getattr(idna, "__version__", "N/A"),
|
|
}
|
|
|
|
if ssl is not None:
|
|
system_ssl = ssl.OPENSSL_VERSION_NUMBER
|
|
|
|
system_ssl_info = {
|
|
"version": f"{system_ssl:x}" if system_ssl is not None else "N/A",
|
|
"name": ssl.OPENSSL_VERSION,
|
|
}
|
|
else:
|
|
system_ssl_info = {"version": "N/A", "name": "N/A"}
|
|
|
|
return {
|
|
"platform": platform_info,
|
|
"implementation": implementation_info,
|
|
"system_ssl": system_ssl_info,
|
|
"gil": not _IS_GIL_DISABLED,
|
|
"urllib3.future": urllib3_info,
|
|
"charset_normalizer": charset_normalizer_info,
|
|
"idna": idna_info,
|
|
"niquests": {
|
|
"version": niquests_version,
|
|
},
|
|
"http3": {
|
|
"enabled": qh3 is not None,
|
|
"qh3": qh3.__version__ if qh3 is not None else None,
|
|
},
|
|
"http2": {
|
|
"jh2": jh2.__version__,
|
|
},
|
|
"http1": {
|
|
"h11": h11.__version__,
|
|
},
|
|
"wassima": {
|
|
"version": wassima.__version__,
|
|
},
|
|
"ocsp": {"enabled": ocsp_verify is not None},
|
|
"websocket": {
|
|
"enabled": wsproto is not None,
|
|
"wsproto": wsproto.__version__ if wsproto is not None else None,
|
|
},
|
|
}
|
|
|
|
|
|
pypi_session = Session()
|
|
|
|
|
|
def check_update(package_name: str, actual_version: str) -> None:
|
|
"""
|
|
Small and concise utility to check for updates.
|
|
"""
|
|
try:
|
|
response = pypi_session.get(f"https://pypi.org/pypi/{package_name}/json")
|
|
package_info = response.raise_for_status().json()
|
|
|
|
if isinstance(package_info, dict) and "info" in package_info and "version" in package_info["info"]:
|
|
if package_info["info"]["version"] != actual_version:
|
|
warnings.warn(
|
|
f"You are using {package_name} {actual_version} and "
|
|
f"PyPI yield version ({package_info['info']['version']}) as the stable one. "
|
|
"We invite you to install this version as soon as possible. "
|
|
f"Run `python -m pip install {package_name} -U`.",
|
|
UserWarning,
|
|
)
|
|
except (RequestException, JSONDecodeError, HTTPError):
|
|
pass
|
|
|
|
|
|
PACKAGE_TO_CHECK_FOR_UPGRADE = {
|
|
"niquests": niquests_version,
|
|
"urllib3-future": urllib3.__version__,
|
|
"qh3": qh3.__version__ if qh3 is not None else None,
|
|
"jh2": jh2.__version__,
|
|
"h11": h11.__version__,
|
|
"charset-normalizer": charset_normalizer.__version__,
|
|
"wassima": wassima.__version__,
|
|
"idna": idna.__version__ if idna is not None else None,
|
|
"wsproto": wsproto.__version__ if wsproto is not None else None,
|
|
}
|
|
|
|
|
|
def main() -> None:
|
|
"""Pretty-print the bug information as JSON."""
|
|
for package, actual_version in PACKAGE_TO_CHECK_FOR_UPGRADE.items():
|
|
if actual_version is None:
|
|
continue
|
|
check_update(package, actual_version)
|
|
|
|
if __legacy_urllib3_version__ is not None:
|
|
warnings.warn(
|
|
"urllib3-future is installed alongside (legacy) urllib3. This may cause compatibility issues. "
|
|
"Some (Requests) 3rd parties may be bound to urllib3, therefor the plugins may wrongfully invoke "
|
|
"urllib3 (legacy) instead of urllib3-future. To remediate this, run "
|
|
"`python -m pip uninstall -y urllib3 urllib3-future`, then run `python -m pip install urllib3-future`.",
|
|
UserWarning,
|
|
)
|
|
|
|
print(json.dumps(info(), sort_keys=True, indent=2))
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|