move configuration to [mypy.plugins.django-stubs] inside mypy config file

This commit is contained in:
Maxim Kurnikov
2019-07-24 22:32:52 +03:00
parent e6d7a570e8
commit b6a5ccabdf
9 changed files with 63 additions and 61 deletions

View File

@@ -10,6 +10,7 @@ from django.db.models.fields.reverse_related import ForeignObjectRel
from django.db.models.sql.query import Query
from django.utils.functional import cached_property
from mypy.checker import TypeChecker
from mypy.errors import Errors
from mypy.types import Instance, Type as MypyType
from django.contrib.postgres.fields import ArrayField
@@ -139,13 +140,11 @@ class DjangoLookupsContext:
class DjangoContext:
def __init__(self, plugin_toml_config: Optional[Dict[str, Any]]) -> None:
def __init__(self, django_settings_module: str) -> None:
self.fields_context = DjangoFieldsContext(self)
self.lookups_context = DjangoLookupsContext(self)
self.django_settings_module = None
if plugin_toml_config:
self.django_settings_module = plugin_toml_config.get('django_settings_module', None)
self.django_settings_module = django_settings_module
self.apps_registry: Optional[Dict[str, str]] = None
self.settings: LazySettings = None

View File

@@ -1,9 +1,9 @@
import os
import configparser
from functools import partial
from typing import Callable, Dict, List, Optional, Tuple
import toml
from django.db.models.fields.related import RelatedField
from mypy.errors import Errors
from mypy.nodes import MypyFile, TypeInfo
from mypy.options import Options
from mypy.plugin import (
@@ -47,17 +47,33 @@ def add_new_manager_base(ctx: ClassDefContext) -> None:
helpers.get_django_metadata(sym.node)['manager_bases'][ctx.cls.fullname] = 1
def extract_django_settings_module(config_file_path: Optional[str]) -> 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)
if not parser.has_section('mypy.plugins.django-stubs'):
errors.report(0, None, "'django_settings_module' 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_settings_module'):
errors.report(0, None, "'django_settings_module' is not set: setting is not provided",
file=config_file_path)
errors.raise_error()
django_settings_module = parser.get('mypy.plugins.django-stubs', 'django_settings_module').strip('\'"')
return django_settings_module
class NewSemanalDjangoPlugin(Plugin):
def __init__(self, options: Options) -> None:
super().__init__(options)
plugin_toml_config = None
if os.path.exists('pyproject.toml'):
with open('pyproject.toml', 'r') as f:
pyproject_toml = toml.load(f)
plugin_toml_config = pyproject_toml.get('tool', {}).get('django-stubs')
self.django_context = DjangoContext(plugin_toml_config)
django_settings_module = extract_django_settings_module(options.config_file)
self.django_context = DjangoContext(django_settings_module)
def _get_current_queryset_bases(self) -> Dict[str, int]:
model_sym = self.lookup_fully_qualified(fullnames.QUERYSET_CLASS_FULLNAME)

View File

@@ -3,26 +3,24 @@ from pytest_mypy.item import YamlTestItem
def django_plugin_hook(test_item: YamlTestItem) -> None:
settings = {
'SECRET_KEY': '"1"',
}
additional_settings = test_item.parsed_test_data.get('additional_settings')
if additional_settings:
for item in additional_settings:
name, _, val = item.partition('=')
settings[name] = val
custom_settings = test_item.parsed_test_data.get('custom_settings', '')
installed_apps = test_item.parsed_test_data.get('installed_apps', None)
if installed_apps and custom_settings:
raise ValueError('"installed_apps" and "custom_settings" are not compatible, please use one or the other')
if installed_apps is not None:
# custom_settings is empty, add INSTALLED_APPS
installed_apps += ['django.contrib.contenttypes']
installed_apps_as_str = '(' + ','.join([repr(app) for app in installed_apps]) + ',)'
custom_settings += 'INSTALLED_APPS = ' + installed_apps_as_str
pyproject_toml_file = File(path='pyproject.toml',
content='[tool.django-stubs]\ndjango_settings_module=\'mysettings\'')
test_item.files.append(pyproject_toml_file)
if 'SECRET_KEY' not in custom_settings:
custom_settings = 'SECRET_KEY = "1"\n' + custom_settings
settings_contents = f'INSTALLED_APPS={installed_apps_as_str}\n'
settings_contents += '\n'.join([f'{key}={val}' for key, val in settings.items()])
if not test_item.additional_mypy_config:
test_item.additional_mypy_config = "[mypy.plugins.django-stubs]\n" \
"django_settings_module = mysettings"
mysettings_file = File(path='mysettings.py', content=settings_contents)
test_item.files.append(mysettings_file)
mysettings_file = File(path='mysettings.py', content=custom_settings)
test_item.files.append(mysettings_file)

View File

@@ -22,7 +22,6 @@ with open('README.md', 'r') as f:
dependencies = [
'mypy>=0.720,<0.730',
'typing-extensions',
'toml',
'django'
]

View File

@@ -435,10 +435,9 @@
from myapp.models import Book
book = Book()
reveal_type(book.publisher) # N: Revealed type is 'myapp.models.Publisher*'
installed_apps:
- myapp
additional_settings:
- BOOK_RELATED_MODEL='myapp.Publisher'
custom_settings: |
INSTALLED_APPS = ('django.contrib.contenttypes', 'myapp')
BOOK_RELATED_MODEL = 'myapp.Publisher'
files:
- path: myapp/__init__.py
- path: myapp/models.py

View File

@@ -5,15 +5,13 @@
reveal_type(mymodel.id) # N: Revealed type is 'builtins.int*'
reveal_type(mymodel.user) # N: Revealed type is 'django.contrib.auth.models.User*'
reveal_type(mymodel.objects) # N: Revealed type is 'django.db.models.manager.Manager[myapp.models.MyModel]'
mypy_config: |
[mypy.plugins.django-stubs]
django_settings_module = mysettings
custom_settings: |
SECRET_KEY = '1'
INSTALLED_APPS = ('django.contrib.contenttypes', 'django.contrib.auth', 'myapp')
files:
- path: pyproject.toml
content: |
[tool.django-stubs]
django_settings_module = 'mysettings'
- path: mysettings.py
content: |
SECRET_KEY = '1'
INSTALLED_APPS = ('django.contrib.contenttypes', 'django.contrib.auth', 'myapp')
- path: myapp/__init__.py
- path: myapp/models.py
content: |

View File

@@ -5,10 +5,9 @@
reveal_type(HttpRequest().user) # N: Revealed type is 'myapp.models.MyUser'
# check that other fields work ok
reveal_type(HttpRequest().method) # N: Revealed type is 'Union[builtins.str, None]'
installed_apps:
- myapp
additional_settings:
- AUTH_USER_MODEL='myapp.MyUser'
custom_settings: |
INSTALLED_APPS = ('django.contrib.contenttypes', 'myapp')
AUTH_USER_MODEL='myapp.MyUser'
files:
- path: myapp/__init__.py
- path: myapp/models.py

View File

@@ -8,17 +8,12 @@
reveal_type(settings.APPS_DIR) # N: Revealed type is 'pathlib.Path'
reveal_type(settings.NUMBERS) # N: Revealed type is 'builtins.list[builtins.str*]'
reveal_type(settings.DICT) # N: Revealed type is 'builtins.dict[Any, Any]'
custom_settings: |
from base import *
SECRET_KEY = 112233
NUMBERS = ['one', 'two']
DICT = {} # type: ignore
files:
- path: pyproject.toml
content: |
[tool.django-stubs]
django_settings_module = 'mysettings'
- path: mysettings.py
content: |
from base import *
SECRET_KEY = 112233
NUMBERS = ['one', 'two']
DICT = {} # type: ignore
- path: base.py
content: |
from pathlib import Path

View File

@@ -26,10 +26,9 @@
from django.contrib.auth import get_user_model
UserModel = get_user_model()
reveal_type(UserModel.objects) # N: Revealed type is 'django.db.models.manager.Manager[myapp.models.MyUser]'
additional_settings:
- AUTH_USER_MODEL='myapp.MyUser'
installed_apps:
- myapp
custom_settings: |
INSTALLED_APPS = ('django.contrib.contenttypes', 'myapp')
AUTH_USER_MODEL = 'myapp.MyUser'
files:
- path: myapp/__init__.py
- path: myapp/models.py