Skip to content

Add support for django-configurations #180

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,3 +74,18 @@ Otherwise, custom type will be created in mypy, named `MyUser__MyUserManager`, w
We have Gitter here: <https://gitter.im/mypy-django/Lobby>

If you think you have more generic typing issue, please refer to https://github.com/python/mypy and their Gitter.


### Django-configurations support

When using <https://django-configurations.readthedocs.io> you will need to set `django_configuration` in the `[mypy.plugins.django-stubs]` section.

```ini
[mypy]
strict_optional = True

; this one is new
[mypy.plugins.django-stubs]
django_settings_module = mysettings
django_configuration = ProductionConfiguration
```
18 changes: 14 additions & 4 deletions mypy_django_plugin/django/context.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,13 @@ def temp_environ():
os.environ.update(environ)


def initialize_django(settings_module: str) -> Tuple['Apps', 'LazySettings']:
def initialize_django(settings_module: str, configuration: Optional[str] = None) -> Tuple['Apps', 'LazySettings']:
with temp_environ():
os.environ['DJANGO_SETTINGS_MODULE'] = settings_module

if configuration is not None:
os.environ['DJANGO_CONFIGURATION'] = configuration

def noop_class_getitem(cls, key):
return cls

Expand All @@ -60,7 +63,13 @@ def noop_class_getitem(cls, key):
apps.get_swappable_settings_name.cache_clear() # type: ignore

if not settings.configured:
settings._setup()
# we are not using django configuration
if configuration is None:
settings._setup()
else:
from configurations import importer # type: ignore
importer.install(check_options=True)
settings._setup()

apps.populate(settings.INSTALLED_APPS)

Expand Down Expand Up @@ -182,13 +191,14 @@ def resolve_lookup(self, model_cls: Type[Model], lookup: str) -> Field:


class DjangoContext:
def __init__(self, django_settings_module: str) -> None:
def __init__(self, django_settings_module: str, django_configuration: Optional[str] = None) -> None:
self.fields_context = DjangoFieldsContext(self)
self.lookups_context = DjangoLookupsContext(self)

self.django_settings_module = django_settings_module
self.django_configuration = django_configuration

apps, settings = initialize_django(self.django_settings_module)
apps, settings = initialize_django(self.django_settings_module, self.django_configuration)
self.apps_registry = apps
self.settings = settings

Expand Down
26 changes: 25 additions & 1 deletion mypy_django_plugin/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,11 +69,35 @@ def extract_django_settings_module(config_file_path: Optional[str]) -> str:
return django_settings_module


def extract_django_configuration(config_file_path: Optional[str]) -> Optional[str]:
errors = Errors()
if config_file_path is None:
errors.report(0, None,
"'django_settings_module' is not set: no mypy config file specified")
errors.raise_error()

parser = configparser.ConfigParser()
parser.read(config_file_path) # type: ignore

if not parser.has_section('mypy.plugins.django-stubs'):
errors.report(0, None,
"'django_configuration' is not set: no section [mypy.plugins.django-stubs]",
file=config_file_path)
errors.raise_error()
if not parser.has_option('mypy.plugins.django-stubs', 'django_configuration'):
return None

django_configuration = parser.get('mypy.plugins.django-stubs',
'django_configuration').strip('\'"')
return django_configuration


class NewSemanalDjangoPlugin(Plugin):
def __init__(self, options: Options) -> None:
super().__init__(options)
django_settings_module = extract_django_settings_module(options.config_file)
self.django_context = DjangoContext(django_settings_module)
django_configuration = extract_django_configuration(options.config_file)
self.django_context = DjangoContext(django_settings_module, django_configuration)

def _get_current_queryset_bases(self) -> Dict[str, int]:
model_sym = self.lookup_fully_qualified(fullnames.QUERYSET_CLASS_FULLNAME)
Expand Down