Skip to content

PyCharm debugging

Remote debugging on PyCharm works only on the Professional Edition. Community edition does not support remote debugging in any capacity.

Frontend Debugging

Frontend debugging is available only for Chrome-based browsers.

  1. SSH into frontend dev container: docker exec -it frontend-dev bash
  2. Run: make run
  3. Run the Attach to frontend development server in the Run configurations dropdown. Browser will launch with the debugger attached.

Backend Debugging

PyCharm's remote debugging requires the run configuration to be configured with the localhost's filepaths mapped to the container's filepaths. Inside the configuration of the Attach to backend development server, you can see the Path mappings section.

The default configuration allows you to set breakpoints and debug within the Whitebox core, libraries that Poetry has installed, as well as plugins installed in editable mode that reside in $PROJECT_PATH$/plugins directory.

The default configuration will allow you to set breakpoints in the Whitebox core, as well as any of the dependencies that Poetry has installed.

Understanding path mappings

In short, path mappings allow the PyCharm debugger to correctly tell the Whitebox process where exactly should the breakpoint be set. For example, if you want to set a breakpoint in the file that is on your host machine located in $PROJECT_PATH$/backend/whitebox/manage.py, PyCharm will need to know that that file is located at /app/whitebox/manage.py in the dev container.

The above case is covered with the mapping $PROJECT_PATH/backend -> /app.

Similarly, for every file that you would like to be able to debug, it needs to be contained within the specified path mappings.

Standard library debugging support

Standard library is not covered by the default configuration as the appropriate configuration may greatly differ from machine to machine. For this reason, you will need to add the path mapping from where the stdlib is located for the interpreter that is setup in your PyCharm interpreters, to the stdlib location inside the container (this one is static, and is located at /usr/local/lib/python3.10).

  • On Linux, depending on the distro and setup, the mapping could look like this:

/TODO/PATH -> /usr/local/lib/python3.10

  • On MacOS, for Python3.10 installed via Brew, the mapping could look like this:

/opt/homebrew/Cellar/python@3.10/3.10.14_1/Frameworks/Python.framework/Versions/3.10/lib/python3.10 -> /usr/local/lib/python3.10

Setting up appropriate Poetry version

While technically you can work with any supported Python interpreter version, it is recommended to use the same version as the one installed in the container. This will ensure that standard library, as well as 3rd party packages, are always the same ones installed in the container.

You can check the Python version running the virtualenv by running:

cd backend/
poetry run python --version

and check the version of the Python interpreter installed in the container by running:

docker exec -it backend-dev poetry run python --version

If your virtualenv version is different from the container one, you can setup the correct version by running:

cd backend/  # First ensure that you are inside the `backend` directory!

rm -rf .venv  # Remove the existing virtualenv
poetry env use TARGET_VERSION  # Replace TARGET_VERSION with the version from the container
                               # with the minor and major numbers only for the executable
                               # e.g. if the container has Python 3.10.14, run:
                               # poetry env use 3.10

poetry install  # Install the dependencies

After this, your environment is all set!

Debugging plugins

When you develop a plugin that you'd like to debug, you will need to ensure that it lives within $PROJECT_PATH$/plugins directory. This directory is mapped to /plugins inside the container, and there's also a path mapping set up for it: $PROJECT_PATH$/plugins -> /plugins.

As the plugins/ directory is not part of the Whitebox core, and is contained in .gitignore, you can freely clone any repository in there, and it will be picked up by the dev container.

For example, if you'd like to debug a whitebox-plugin-gps-display plugin, you can clone it into the plugins/ directory on the host machine:

cd plugins/
git clone git@gitlab.com:whitebox-aero/whitebox-plugin-gps-display.git

Then, you can enter the container and install the plugin in editable mode:

docker exec -it backend-dev bash
poetry add -e /plugins/whitebox-plugin-gps-display

After this, you can set breakpoints in the plugin code, and the debugger will pick them up. Note that symlinks are not supported, and might cause the debugger not to recognize the breakpoints.

Ensuring pydevd is installed

Additionally, PyCharm requires a specific version of pydevd_pycharm to be installed on the backend container, matching the version of PyCharm's installation itself. As this is impossible to detect this and bundle the appropriate version within the project itself, you will need to install the package manually. To ensure that pydevd_pycharm is installed inside the container, but not also added to project's dependencies, we will be using pip for this (do not use pip for any other package operations, always use Poetry!):

  1. Open the Attach to backend development server run configuration
  2. Check which pydevd_pycharm version your PyCharm expects
    • In the modal, you should see something like: pip install pydevd-pycharm~=242.21829.153
    • Copy that line
  3. SSH into backend dev container: docker exec -it backend-dev bash
  4. Inside the container, run: poetry run COPIED_LINE
  5. e.g. poetry run pip install pydevd-pycharm~=242.21829.153

You will need to install this every time you rebuild the container image.

Running the debugger

Voila!~ At this point, you should be all set to start debugging the development container backend server. Once everything above is set up, going forward, you can just do the following:

  1. In PyCharm, run the Attach to backend development server in the Run configurations dropdown
  2. You should now see "Waiting for process connection..." in the console
  3. In a terminal, SSH into backend dev container: docker exec -it backend-dev bash
  4. Run: make debug_pycharm
  5. This will start the server in debug mode
  6. Debugger should be attached to PyCharm, suspending the server at the line where the pydevd has connected
  7. You can now set breakpoints, inspect variables, etc. as you would in a local debugging session. Click on Resume Program (green play button) to start the server.

Troubleshooting

  • If you see an error about missing pydevd, it means that the pydevd package is not installed in the container. Follow the steps above to install it.

  • If you see an error about pydevd version mismatch, it means that the version of pydevd installed in the container does not match the version expected by PyCharm. Follow the steps above to install the correct version.

  • If the backend process cannot reach your PyCharm debugger, ensure that either:

  • from inside the container, host.docker.internal resolves to your host machine's IP address, or
  • set a PYDEVD_SERVER environment variable to your host machine's IP address before starting the server, e.g.:

    export PYDEVD_SERVER=172.0.0.1
    make debug_pycharm
    
    You can also set PYDEVD_PORT if needed, but make sure that the run configuration in PyCharm matches the port you set.

  • If you see an error looking like:

    pydev debugger: warning: trying to add breakpoint to file that does not exist: /path/to/file.py (will have no effect)
    

    it means that you have set a breakpoint inside the file located on your host machine at /path/to/some/library_name/module.py, but the file does not exist inside the container. To fix this, you'll need to add the appropriate parent directory to the file mapping. For example, if that file on the container is located at /some/other/path/library_name/module.py, you will need to add a mapping similar to one of these:

    • /path/to/some/library_name -> /some/other/path/library_name, or,

    • /path/to/some -> /some/other/path, depending on what makes more sense in your case

Final notes

Changing the run configurations locally will also make changes in the IDE files located in the .idea directory that are tracked by Git.

To prevent them from being committed, you can mark them to be skipped by Git:

git update-index --skip-worktree .idea/runConfigurations/*

After this, changes will not be tracked, and git status will not show them.

This will prevent the changes from being committed, but you will still be able to make changes locally, and safely. If you at some point want to commit some changes, you can un-skip the files:

git update-index --no-skip-worktree .idea/runConfigurations/*

Happy debugging!