emmett-framework / granian

A Rust HTTP server for Python applications
BSD 3-Clause "New" or "Revised" License
2.86k stars 83 forks source link

Package with project code is not added to PYTHONPATH if it is run from package #214

Closed illagrenan closed 8 months ago

illagrenan commented 9 months ago

Thanks for a great project. I am currently testing the available ASGI servers and I found that granian behaves differently than other ASGI servers. I have no idea if this is correct because the directory structure of my application is a bit non-standard, but I'll describe it here anyway, maybe it will help someone.

My use-case is as follows: My project has the following stucture: C:\project_root\tests\django_test_application, where:

But under granian my application crashes on ModuleNotFoundError: no module named 'django_test_application'. I think it's because the prepare_import function (https://github.com/emmett-framework/granian/blob/master/granian/_internal.py#L13-L35) doesn't add django_test_application to PYTHONPATH when it's part of a package. I've prepared a minimal working project here that demonstrates the described problem: https://github.com/illagrenan/granian-app-in-package.

I tested uvicorn, hypercorn and daphne and they add the package django_test_application to PYTHONPATH.

A little background on why my project is structured this way: I'm writing a package that adds ASGI lifespan protocol support for Django. I'd like to have all the major ASGI servers running as part of the integration tests to make sure my code is compatible with all of them.

gi0baro commented 9 months ago

Hi @illagrenan, thank you for reporting this.

Would you be able to run Granian using the Python interface? If so, you can define a custom loader:

import importlib

def target_loader(target: str):
    mods, _, attrs = target.partition(":")
    instance = importlib.import_module(mods)
    for attr in attrs.split("."):
        instance = getattr(instance, attr)
    return instance

and pass it to the Granian.serve method.

I'm not able to test the upper code immediately: if you manage to, then I'll be happy to publish a patch revision of granian later this week with the loader upgraded.

illagrenan commented 8 months ago

Sorry for the late reply. I can confirm that the latest version https://github.com/emmett-framework/granian/releases/tag/v1.1.1 works perfectly. 🚀 Thanks a lot for the great work!