mirror of
https://github.com/davidhalter/django-stubs.git
synced 2025-12-07 04:34:29 +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.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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
mysettings_file = File(path='mysettings.py', content=custom_settings)
|
||||
test_item.files.append(mysettings_file)
|
||||
|
||||
1
setup.py
1
setup.py
@@ -22,7 +22,6 @@ with open('README.md', 'r') as f:
|
||||
dependencies = [
|
||||
'mypy>=0.720,<0.730',
|
||||
'typing-extensions',
|
||||
'toml',
|
||||
'django'
|
||||
]
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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]'
|
||||
files:
|
||||
- path: pyproject.toml
|
||||
content: |
|
||||
[tool.django-stubs]
|
||||
django_settings_module = 'mysettings'
|
||||
- path: mysettings.py
|
||||
content: |
|
||||
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: myapp/__init__.py
|
||||
- path: myapp/models.py
|
||||
content: |
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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]'
|
||||
files:
|
||||
- path: pyproject.toml
|
||||
content: |
|
||||
[tool.django-stubs]
|
||||
django_settings_module = 'mysettings'
|
||||
- path: mysettings.py
|
||||
content: |
|
||||
custom_settings: |
|
||||
from base import *
|
||||
SECRET_KEY = 112233
|
||||
NUMBERS = ['one', 'two']
|
||||
DICT = {} # type: ignore
|
||||
files:
|
||||
- path: base.py
|
||||
content: |
|
||||
from pathlib import Path
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user