mmdanziger
mmdanziger

Reputation: 4648

How to import FastAPI app folder to satisfy pycharm and pylint?

I am trying to figure out the best way to manage relative vs absolute imports in my project so that the testing and linting tools from pylint, pytest, vscode and pycharm are all happy and so that the app will run correctly in production.

I have not packaged the app with setup.py because it is installed into a docker image and run from its working directory. My project directory structure is like this:

app
 ┣ app
 ┃ ┣ static
 ┃ ┃ ┗ myfrontend.js
 ┃ ┣ templates
 ┃ ┃ ┗ index.html
 ┃ ┣ tests
 ┃ ┃ ┣ __init__.py
 ┃ ┃ ┗ test_server.py
 ┃ ┣ __init__.py
 ┃ ┣ main.py
 ┃ ┗ utils.py
 ┣ Dockerfile
 ┗ requirements.txt

In app/app/main.py imports are:

from app.utils import prepare_file

app = FastAPI()

and in app/app/tests/test_server.py imports are:

from app.main import app
from app.utils import prepare_file

And the whole thing is run from a docker image built off tiangolo/uvicorn-gunicorn-fastapi by copying the files in and setting the workdir:

COPY ./app/app /app/app/
WORKDIR /app

This works with VSCode linting and testing, and with the QA toolchain:

pylint -E app/app # processes with no errors
pytest app/app/tests # correctly runs tests
docker build . -f app/Dockerfile -t myapp && docker container run myapp # app runs

However, PyCharm chokes on the imports:

Unresolved reference 'app'
Cannot find reference 'main' in 'imported module app'
Cannot find reference 'utils' in 'imported module app'

The PyCharm project has two submodules (the library with core "business logic" and the webapp that wraps it).

Pycharm can be made happy by changing app/app/main.py to:

from ..app.utils import prepare_file

and app/app/tests/test_server.py to:

from ...app.main import app
from ...app.utils import prepare_file

but this triggers pylint:

$ pylint -E app/app
************* Module app.main
app/app/main.py:18:0: E0402: Attempted relative import beyond top-level package (relative-beyond-top-level)
************* Module app.tests.test_server
app/app/tests/test_server.py:2:0: E0402: Attempted relative import beyond top-level package (relative-beyond-top-level)
app/app/tests/test_server.py:3:0: E0402: Attempted relative import beyond top-level package (relative-beyond-top-level)

I can think of two possible explanations:

  1. PyCharm has a switch hidden somewhere that needs to be flipped to make it compatible. I tried marking app/app as "sources root" but it did not help.
  2. The whole approach violates the correct structuring of a python web app and the whole thing should be restructured.

What do you think? Is this a PyCharm compatibility issue? Or a square peg round whole design problem?

Upvotes: 0

Views: 1938

Answers (1)

mmdanziger
mmdanziger

Reputation: 4648

Solution: Mark the app as "sources root" not app/app. Then pycharm sees what the other linters see.

Thanks @lsabi and @mx0 for the pointers.

Upvotes: 1

Related Questions