From d00249de71a87abfcfec7bf32d90b6edb71e398d Mon Sep 17 00:00:00 2001 From: ievgenii vdovenko Date: Wed, 11 Jun 2025 10:09:19 +0200 Subject: [PATCH] remote debugger: adds pycharm remote debugger --- requirements_debug.txt | 3 ++ rhodecode/config/constants.py | 2 + rhodecode/config/middleware.py | 13 +++++++ .../lib/middleware/pycharm_remote_debugger.py | 37 +++++++++++++++++++ 4 files changed, 55 insertions(+) create mode 100644 rhodecode/config/constants.py create mode 100644 rhodecode/lib/middleware/pycharm_remote_debugger.py diff --git a/requirements_debug.txt b/requirements_debug.txt index 57f1d02d..be3fb446 100644 --- a/requirements_debug.txt +++ b/requirements_debug.txt @@ -25,3 +25,6 @@ types-sqlalchemy types-psutil types-pycurl types-ujson + +#remote debugger +pydevd-pycharm~=251.25410.159 diff --git a/rhodecode/config/constants.py b/rhodecode/config/constants.py new file mode 100644 index 00000000..e8d0e984 --- /dev/null +++ b/rhodecode/config/constants.py @@ -0,0 +1,2 @@ +PYCHARM_DEBUG = "PYCHARM_DEBUG" +PYCHARM_DEBUG_PAUSE_AT_STARTUP = "PYCHARM_DEBUG_PAUSE_AT_STARTUP" diff --git a/rhodecode/config/middleware.py b/rhodecode/config/middleware.py index 40e77751..2cd20d31 100644 --- a/rhodecode/config/middleware.py +++ b/rhodecode/config/middleware.py @@ -31,6 +31,8 @@ from pyramid.settings import asbool, aslist from pyramid.httpexceptions import HTTPException, HTTPError, HTTPInternalServerError, HTTPFound, HTTPNotFound from pyramid.renderers import render_to_response +from rhodecode.config.constants import PYCHARM_DEBUG +from rhodecode.lib.middleware.pycharm_remote_debugger import PyCharmDebugMiddleware from rhodecode.model import meta from rhodecode.config import patches @@ -420,6 +422,16 @@ def includeme(config, auth_resources=None): config.add_view(error_handler, context=HTTPError) +def wrap_app_in_pycharm_remote_debugger_if_enabled(pyramid_app): + pycharm_debugger_enabled = os.getenv(PYCHARM_DEBUG, "0") == "1" + log.debug(f"Pycharm remote debugger enabled: {pycharm_debugger_enabled}") + + if pycharm_debugger_enabled: + return PyCharmDebugMiddleware(pyramid_app) + + return pyramid_app + + def wrap_app_in_wsgi_middlewares(pyramid_app, config): """ Apply outer WSGI middlewares around the application. @@ -429,6 +441,7 @@ def wrap_app_in_wsgi_middlewares(pyramid_app, config): # enable https redirects based on HTTP_X_URL_SCHEME set by proxy pyramid_app = HttpsFixup(pyramid_app, settings) + pyramid_app = wrap_app_in_pycharm_remote_debugger_if_enabled(pyramid_app) pyramid_app, _ae_client = wrap_in_appenlight_if_enabled(pyramid_app, settings) registry.ae_client = _ae_client diff --git a/rhodecode/lib/middleware/pycharm_remote_debugger.py b/rhodecode/lib/middleware/pycharm_remote_debugger.py new file mode 100644 index 00000000..fab71ec8 --- /dev/null +++ b/rhodecode/lib/middleware/pycharm_remote_debugger.py @@ -0,0 +1,37 @@ +import os +import logging +import socket + +from rhodecode.config.constants import PYCHARM_DEBUG_PAUSE_AT_STARTUP + +log = logging.getLogger(__name__) + + +class PyCharmDebugMiddleware: + def __init__(self, handler): + self.handler = handler + self._start_debugger() + + def _start_debugger(self): + try: + import pydevd_pycharm + + suspend = os.getenv(PYCHARM_DEBUG_PAUSE_AT_STARTUP, "0") == "1" + host = "host.docker.internal" # assuming that app is running inside docker, and the debug server is on the same machine + + pydevd_pycharm.settrace( + host, + suspend=suspend, + stdoutToServer=True, + stderrToServer=True, + ) + log.debug("PyCharm debugger attached successfully!") + except ImportError: + log.warning("pydevd_pycharm not installed. Debugging disabled.") + except ConnectionRefusedError: + ip = socket.gethostbyname(host) + log.warning(f"debug server is not running on host[ip]: {host}[{ip}], shutdown remote debugger.") + pydevd_pycharm.stoptrace() + + def __call__(self, environ, start_response): + return self.handler(environ, start_response)