mirror of
https://github.com/davidhalter/django-stubs.git
synced 2025-12-06 20:24:31 +08:00
move configuration to [mypy.plugins.django-stubs] inside mypy config file
This commit is contained in:
@@ -10,6 +10,7 @@ from django.db.models.fields.reverse_related import ForeignObjectRel
|
|||||||
from django.db.models.sql.query import Query
|
from django.db.models.sql.query import Query
|
||||||
from django.utils.functional import cached_property
|
from django.utils.functional import cached_property
|
||||||
from mypy.checker import TypeChecker
|
from mypy.checker import TypeChecker
|
||||||
|
from mypy.errors import Errors
|
||||||
from mypy.types import Instance, Type as MypyType
|
from mypy.types import Instance, Type as MypyType
|
||||||
|
|
||||||
from django.contrib.postgres.fields import ArrayField
|
from django.contrib.postgres.fields import ArrayField
|
||||||
@@ -139,13 +140,11 @@ class DjangoLookupsContext:
|
|||||||
|
|
||||||
|
|
||||||
class DjangoContext:
|
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.fields_context = DjangoFieldsContext(self)
|
||||||
self.lookups_context = DjangoLookupsContext(self)
|
self.lookups_context = DjangoLookupsContext(self)
|
||||||
|
|
||||||
self.django_settings_module = None
|
self.django_settings_module = django_settings_module
|
||||||
if plugin_toml_config:
|
|
||||||
self.django_settings_module = plugin_toml_config.get('django_settings_module', None)
|
|
||||||
|
|
||||||
self.apps_registry: Optional[Dict[str, str]] = None
|
self.apps_registry: Optional[Dict[str, str]] = None
|
||||||
self.settings: LazySettings = None
|
self.settings: LazySettings = None
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import os
|
import configparser
|
||||||
from functools import partial
|
from functools import partial
|
||||||
from typing import Callable, Dict, List, Optional, Tuple
|
from typing import Callable, Dict, List, Optional, Tuple
|
||||||
|
|
||||||
import toml
|
|
||||||
from django.db.models.fields.related import RelatedField
|
from django.db.models.fields.related import RelatedField
|
||||||
|
from mypy.errors import Errors
|
||||||
from mypy.nodes import MypyFile, TypeInfo
|
from mypy.nodes import MypyFile, TypeInfo
|
||||||
from mypy.options import Options
|
from mypy.options import Options
|
||||||
from mypy.plugin import (
|
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
|
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):
|
class NewSemanalDjangoPlugin(Plugin):
|
||||||
def __init__(self, options: Options) -> None:
|
def __init__(self, options: Options) -> None:
|
||||||
super().__init__(options)
|
super().__init__(options)
|
||||||
|
django_settings_module = extract_django_settings_module(options.config_file)
|
||||||
plugin_toml_config = None
|
self.django_context = DjangoContext(django_settings_module)
|
||||||
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)
|
|
||||||
|
|
||||||
def _get_current_queryset_bases(self) -> Dict[str, int]:
|
def _get_current_queryset_bases(self) -> Dict[str, int]:
|
||||||
model_sym = self.lookup_fully_qualified(fullnames.QUERYSET_CLASS_FULLNAME)
|
model_sym = self.lookup_fully_qualified(fullnames.QUERYSET_CLASS_FULLNAME)
|
||||||
|
|||||||
@@ -3,26 +3,24 @@ from pytest_mypy.item import YamlTestItem
|
|||||||
|
|
||||||
|
|
||||||
def django_plugin_hook(test_item: YamlTestItem) -> None:
|
def django_plugin_hook(test_item: YamlTestItem) -> None:
|
||||||
settings = {
|
custom_settings = test_item.parsed_test_data.get('custom_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
|
|
||||||
|
|
||||||
installed_apps = test_item.parsed_test_data.get('installed_apps', None)
|
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:
|
if installed_apps is not None:
|
||||||
|
# custom_settings is empty, add INSTALLED_APPS
|
||||||
installed_apps += ['django.contrib.contenttypes']
|
installed_apps += ['django.contrib.contenttypes']
|
||||||
installed_apps_as_str = '(' + ','.join([repr(app) for app in installed_apps]) + ',)'
|
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',
|
if 'SECRET_KEY' not in custom_settings:
|
||||||
content='[tool.django-stubs]\ndjango_settings_module=\'mysettings\'')
|
custom_settings = 'SECRET_KEY = "1"\n' + custom_settings
|
||||||
test_item.files.append(pyproject_toml_file)
|
|
||||||
|
|
||||||
settings_contents = f'INSTALLED_APPS={installed_apps_as_str}\n'
|
if not test_item.additional_mypy_config:
|
||||||
settings_contents += '\n'.join([f'{key}={val}' for key, val in settings.items()])
|
test_item.additional_mypy_config = "[mypy.plugins.django-stubs]\n" \
|
||||||
|
"django_settings_module = mysettings"
|
||||||
|
|
||||||
mysettings_file = File(path='mysettings.py', content=settings_contents)
|
mysettings_file = File(path='mysettings.py', content=custom_settings)
|
||||||
test_item.files.append(mysettings_file)
|
test_item.files.append(mysettings_file)
|
||||||
|
|||||||
1
setup.py
1
setup.py
@@ -22,7 +22,6 @@ with open('README.md', 'r') as f:
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
'mypy>=0.720,<0.730',
|
'mypy>=0.720,<0.730',
|
||||||
'typing-extensions',
|
'typing-extensions',
|
||||||
'toml',
|
|
||||||
'django'
|
'django'
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@@ -435,10 +435,9 @@
|
|||||||
from myapp.models import Book
|
from myapp.models import Book
|
||||||
book = Book()
|
book = Book()
|
||||||
reveal_type(book.publisher) # N: Revealed type is 'myapp.models.Publisher*'
|
reveal_type(book.publisher) # N: Revealed type is 'myapp.models.Publisher*'
|
||||||
installed_apps:
|
custom_settings: |
|
||||||
- myapp
|
INSTALLED_APPS = ('django.contrib.contenttypes', 'myapp')
|
||||||
additional_settings:
|
BOOK_RELATED_MODEL = 'myapp.Publisher'
|
||||||
- BOOK_RELATED_MODEL='myapp.Publisher'
|
|
||||||
files:
|
files:
|
||||||
- path: myapp/__init__.py
|
- path: myapp/__init__.py
|
||||||
- path: myapp/models.py
|
- path: myapp/models.py
|
||||||
|
|||||||
@@ -5,15 +5,13 @@
|
|||||||
reveal_type(mymodel.id) # N: Revealed type is 'builtins.int*'
|
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.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]'
|
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:
|
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/__init__.py
|
||||||
- path: myapp/models.py
|
- path: myapp/models.py
|
||||||
content: |
|
content: |
|
||||||
|
|||||||
@@ -5,10 +5,9 @@
|
|||||||
reveal_type(HttpRequest().user) # N: Revealed type is 'myapp.models.MyUser'
|
reveal_type(HttpRequest().user) # N: Revealed type is 'myapp.models.MyUser'
|
||||||
# check that other fields work ok
|
# check that other fields work ok
|
||||||
reveal_type(HttpRequest().method) # N: Revealed type is 'Union[builtins.str, None]'
|
reveal_type(HttpRequest().method) # N: Revealed type is 'Union[builtins.str, None]'
|
||||||
installed_apps:
|
custom_settings: |
|
||||||
- myapp
|
INSTALLED_APPS = ('django.contrib.contenttypes', 'myapp')
|
||||||
additional_settings:
|
AUTH_USER_MODEL='myapp.MyUser'
|
||||||
- AUTH_USER_MODEL='myapp.MyUser'
|
|
||||||
files:
|
files:
|
||||||
- path: myapp/__init__.py
|
- path: myapp/__init__.py
|
||||||
- path: myapp/models.py
|
- path: myapp/models.py
|
||||||
|
|||||||
@@ -8,17 +8,12 @@
|
|||||||
reveal_type(settings.APPS_DIR) # N: Revealed type is 'pathlib.Path'
|
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.NUMBERS) # N: Revealed type is 'builtins.list[builtins.str*]'
|
||||||
reveal_type(settings.DICT) # N: Revealed type is 'builtins.dict[Any, Any]'
|
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:
|
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
|
- path: base.py
|
||||||
content: |
|
content: |
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|||||||
@@ -26,10 +26,9 @@
|
|||||||
from django.contrib.auth import get_user_model
|
from django.contrib.auth import get_user_model
|
||||||
UserModel = get_user_model()
|
UserModel = get_user_model()
|
||||||
reveal_type(UserModel.objects) # N: Revealed type is 'django.db.models.manager.Manager[myapp.models.MyUser]'
|
reveal_type(UserModel.objects) # N: Revealed type is 'django.db.models.manager.Manager[myapp.models.MyUser]'
|
||||||
additional_settings:
|
custom_settings: |
|
||||||
- AUTH_USER_MODEL='myapp.MyUser'
|
INSTALLED_APPS = ('django.contrib.contenttypes', 'myapp')
|
||||||
installed_apps:
|
AUTH_USER_MODEL = 'myapp.MyUser'
|
||||||
- myapp
|
|
||||||
files:
|
files:
|
||||||
- path: myapp/__init__.py
|
- path: myapp/__init__.py
|
||||||
- path: myapp/models.py
|
- path: myapp/models.py
|
||||||
|
|||||||
Reference in New Issue
Block a user