django-stubs icon indicating copy to clipboard operation
django-stubs copied to clipboard

Add support for django-configurations

Open hishnash opened this issue 6 years ago • 16 comments

Add support for django-configurations.

This is enabled if you add a django_configuration value to the Plugins settings.

hishnash avatar Sep 23 '19 21:09 hishnash

I'm with @sobolevn on that. I can extract code for settings initialization to make it more pluggable. We can design some kind of hooks to be able to extend library. @sobolevn @hishnash Could you think of any other examples of django third party apps for which we'd need hooks?

mkurnikov avatar Sep 23 '19 22:09 mkurnikov

@mkurnikov @sobolevn more pluggable settings initialisation would be the best option yes.

hishnash avatar Sep 23 '19 22:09 hishnash

@mkurnikov I use https://github.com/sobolevn/django-split-settings, it almost works with django-stubs as is, but sometimes requires extra env vars:

from split_settings.tools import include
from os import environ

ENV = environ.get('DJANGO_ENV') or 'development'  # here

base_settings = [
    'components/common.py',
    'components/database.py',

    # Select the right env:
    'environments/{0}.py'.format(ENV),
]

# Include settings:
include(*base_settings)

sobolevn avatar Sep 23 '19 22:09 sobolevn

@hishnash I tried different refactorings a bit, but I don't really know what would work best. If you have bandwidth, could you make a PR with refactoring you need? Like, extracting initialization into the separate pluggable class or smth.

mkurnikov avatar Sep 29 '19 23:09 mkurnikov

@mkurnikov I will give it a spin tomorrow, I will need to check how to ensure Mypy inits plugins in the correct order.

or we could have a config param in in the Django-stubs plugin config that points to an alternative package name for init?

hishnash avatar Oct 01 '19 02:10 hishnash

@hishnash @mkurnikov Has there been any progress here? This is an exciting feature.

Is there anything I (or others) could contribute to help?

brianhelba avatar Dec 17 '19 19:12 brianhelba

any news with this?

psdon avatar Sep 09 '20 06:09 psdon

We have decided to use some sort of a callback, like this:

[mypy.plugins.django-stubs]
django_settings_module = mysettings
django_setup_callback = path.to.your.function

And the function itself should look like so (probably we will call it from here):

# path/to/your.py
def function(settings_module: str) -> None:
    # By default it will do this:
    from django.conf import settings
    settings._setup()

This way, you will be able to support any configuration framework of your choice. And we will not have to add the support to the core library.

I will review and merge a PR with the described feature with great pleause. @hishnash are you still interested? 🙂

sobolevn avatar Sep 09 '20 07:09 sobolevn

Can be achieved without additional support and non intrusively with a custom plugin package

;setup.cfg
[mypy]
plugins = ./mypy_django_plugin.py
# mypy_django_plugin.py
from configurations import importer

from mypy_django_plugin.main import plugin

importer.install()

Like this, when the mypy django plugin initialize the settings, the import hook of django-configurations will be installed.

ticosax avatar Sep 29 '20 13:09 ticosax

the workaround by ticosax is great if you don't need multiple plugins, but in case anyone does, i've created a gist that returns a no-op plugin and sets up the importer

thanks ticosax, i used your snippet as a base :)

ghost avatar Nov 12 '20 23:11 ghost

Can be achieved without additional support and non intrusively with a custom plugin package

;setup.cfg
[mypy]
plugins = ./mypy_django_plugin.py
# mypy_django_plugin.py
from configurations import importer

from mypy_django_plugin.main import plugin

importer.install()

Like this, when the mypy django plugin initialize the settings, the import hook of django-configurations will be installed.

Thank you for sharing. It works well! For more specific:

# configurations_mypy_django_plugin.py
import os
from configurations.importer import install
from mypy.version import __version__

from mypy_django_plugin import main


def plugin(version):
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "django_project.config")
    os.environ.setdefault("DJANGO_CONFIGURATION", "Local")
    install()
    return main.plugin(version)
# mypy.ini
[mypy]
plugins = ./configurations_mypy_django_plugin.py
[mypy.plugins.django-stubs]
django_settings_module = "django_project.config"

Dimitri-WEI-Lingfeng avatar Apr 15 '21 03:04 Dimitri-WEI-Lingfeng

In case it's useful to anyone, @wlf100220 solution here worked for me with a couple tweaks.

Our top-level package is not at the repo root but instead in a src folder, and settings is at ./src/project_name/settings.py. I was getting path issues, resolved by specifying the mypy_path:

# pyproject.toml
[tool.mypy]
mypy_path = "./src"
plugins = ["./src/configurations_mypy_django_plugin.py"]

[tool.django-stubs]
django_settings_module = "project_name.settings"

john-sandall avatar Dec 22 '21 16:12 john-sandall

Will this ever get integrated?

Brodan avatar Mar 12 '24 07:03 Brodan

@Brodan this project is open-source. If you want something, you can provide a design description, get an approval and then send a PR.

sobolevn avatar Mar 12 '24 08:03 sobolevn

Hello everyone, I am stuck with this problem. I cannot make proposed solutions to work in my case, and I don't unserstand @ticosax solution. `

mypy_django_plugin.py

from configurations import importer

from mypy_django_plugin.main import plugin

importer.install()`

It seems like importing from mypy_django_plugin.main inside mypy_django_plugin.py. Can anyone explain to me what is going on here?

Matje1979 avatar Mar 21 '24 19:03 Matje1979

@Matje1979 just name your plugin something else.

For me, the proposed solution doesn't work, though.

bwo avatar Aug 28 '24 17:08 bwo