IDE set-up

Notes on setting up PyCharm for development with specific reference to working on a Mac

Set up run configurations:

  • PyCharm Run/Debug Configurations
  • Install the EnvFile plug-in so that the environment file can be read by your run configuration (see Stackoverflow Answer)
  • Set OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES as an environment variable in your run configuration to avoid errors on recent macos installs

Example configurations here - FastAPI - Plotly Dash

If you are using PyCharm or another IDE then ensure that the environment variables in .env are loaded. PyCharm has a plugin that can load these when unit testing with pytest or running the main application.

Notes on setting up VSCode for development

Because there are separate Python packages with separate interpreters you will need a ‘multiroot’ workspace. I found this note from StackOverFlow helpful.

One small problem with sharing a VS Code configuration is that it seems to require absolute paths from the settings.json and launch.json files. With that caveat in mind, then here are some examples below.

  1. Git clone the project as per usual
  2. Open the project in VSCode and save as a workspace
  3. Edit the root (HyUI) .vscode/settings.json file to exclude the folders holding the nested packages
{
    "files.exclude": {
        "**/.git": true,
        "**/.svn": true,
        "**/.hg": true,
        "**/CVS": true,
        "**/.DS_Store": true,
        "**/Thumbs.db": true,
        // exclude nested modules/packages below
        "api": true,
        "web": true,
        "initialise": true,
        "jupyter": true,
    }
}
  1. Add these folders back in via Workspaces >> Add folder to workspace … command (nested under the File menu). In my case, this means that my ‘workspace’ file, now looks like this (where I have used the name property to help me visually navigate my workspace).
{
    "folders": [
        {
            "path": ".",
            "name": "HyUi Project"
        },
        {
            "path": "api",
            "name": "HyUi FastAPI"
        },
        {
            "path": "web",
            "name": "HyUi Plotly Dash"
        }
    ]
}

And my sidebar in VS Code (with the web labelled as ‘HyUI Plotly Dash’)

  1. Then prepare nested .vscode/settings.json and .vscode/launch.json files etc (also visible in the screenshot above). For example, for the web module, you need to specify the interpreter, and a debug configuration (in launch.json).

Beware the absolute paths below ☹. You will need to change these unless your name is also ‘steve’.

settings.json:

{
    "python.defaultInterpreterPath": "${userHome}/.pyenv/hyui-web/bin/python3",
    "python.envFile": "${workspaceFolder}/.env",
    "python.testing.pytestArgs": [
        "src/web/"
    ],
    "python.testing.unittestEnabled": false,
    "python.testing.pytestEnabled": true
}

launch.json under web:

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "HyUi: Plotly Dash",
            "type": "python",
            "request": "launch",
            "module": "web.app",
            "args": [
                "--reload"
            ],
            "jinja": true,
            "justMyCode": true,
            "python": "/users/steve/.pyenv/versions/hyui-web/bin/python3",
            "cwd": "${workspaceFolder}/src",
            "envFile": "${workspaceFolder}/../.env",
            "env": {
                "OBJC_DISABLE_INITIALIZE_FORK_SAFETY": "YES",
                "PYTHONUNBUFFERED": "1",
        }
        }
    ]
}

launch.json under api:

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "hyui-api",
            "type": "python",
            "request": "launch",
            "module": "uvicorn",
            "args": [
                "api.main:app",
                "--reload",
                "--port",
                "8092",
            ],
            "jinja": true,
            "justMyCode": true,
            "python": "/users/steve/.pyenv/versions/hyui-api/bin/python3",
            "cwd": "${workspaceFolder}/src",
            "envFile": "${workspaceFolder}/../.env",
            "env": {
                "OBJC_DISABLE_INITIALIZE_FORK_SAFETY": "YES",
                "PYTHONUNBUFFERED": "1",
            }
        }
    ]
}

Developing and debugging with docker compose

Imagine you wish to debug the web container and its interactions with the other services. This specific issue arose when I was working with Plotly Dash’s background callbacks and experimenting with using Celery as the background callback manager.

The following eventually allowed me to run the web app as part of a docker compose configuration, and debug from VSCode.

  • I duplicated ./web/Dockerfile as ./web/Dockerfile.dev and swapped the ENTRYPOINT command for CMD which allowed me to override that gunicorn based command with python debugpy in the compose.dev.yml file
  • I duplicated ./compose.yml as ./compose.dev.yml and then …
    • mounted the models and the web modules as bind mounts
    • added the 5678 port mapping for debugpy
    • adjusted the default web port mapping to 8300 (from 8000) since that’s the development port specified in ./web/src/web/config.py
    • I added in an override COMMAND to run debugpy
    command: ["sh", "-c", "pip install debugpy -t /tmp && python /tmp/debugpy --wait-for-client --listen 0.0.0.0:5678 -m web.app"]
  • I opened a terminal and ran docker compose -f compose.dev.yml up -d for all the services except web (i.e. api, baserow, redis etc.)
  • I opened another terminal and ran docker compose -f compose.dev.yml up web
  • I created an entry in launch.json as follows and ensured that the localRoot mapped to the root of the web module (rather than the workspace)
        {
            "name": "Python: Remote Attach - web",
            "type": "python",
            "request": "attach",
            "connect": {
                "host": "localhost",
                "port": 5678
            },
            "pathMappings": [
                {
                    // adjust localRoot so VSCode breakpoints are recognised
                    "localRoot": "${workspaceFolder}/web/src",
                    "remoteRoot": "."
                }
            ],
            "justMyCode": true
        },
  • Set the Plotly Dash debug argument to debug=False else each code change means app restarts and the debugger is detached/broken
  • I then ran this debug configuration and it all worked ….!! 🥳

Troubleshooting

  • Follow all the setup instructions and check you can get everything running locally outside vscode first!
  • Check that the locations of python and your .env file are correct in your launch.json and settings.json file. You may need to write absolute paths in settings.json (even if launch.json uses the {workSpaceFolder} variables appropriately). For example, "python.envFile": "~/Github/HyUi/.env").