mirror of
https://github.com/davidhalter/django-stubs.git
synced 2025-12-06 20:24:31 +08:00
82 lines
3.0 KiB
Python
82 lines
3.0 KiB
Python
from typing import TYPE_CHECKING, List, Optional, cast
|
|
|
|
from mypy.checkexpr import FunctionContext
|
|
from mypy.checkmember import AttributeContext
|
|
from mypy.nodes import NameExpr, StrExpr, SymbolTableNode, TypeInfo
|
|
from mypy.types import AnyType, Instance, Type, TypeOfAny, TypeType
|
|
|
|
from mypy_django_plugin.lib import helpers
|
|
|
|
if TYPE_CHECKING:
|
|
from mypy.checker import TypeChecker
|
|
|
|
|
|
def get_setting_sym(name: str, api: 'TypeChecker', settings_modules: List[str]) -> Optional[SymbolTableNode]:
|
|
for settings_mod_name in settings_modules:
|
|
if settings_mod_name not in api.modules:
|
|
continue
|
|
|
|
file = api.modules[settings_mod_name]
|
|
sym = file.names.get(name)
|
|
if sym is not None:
|
|
return sym
|
|
|
|
return None
|
|
|
|
|
|
def get_type_of_setting(ctx: AttributeContext, setting_name: str,
|
|
settings_modules: List[str], ignore_missing_settings: bool) -> Type:
|
|
setting_sym = get_setting_sym(setting_name, ctx.api, settings_modules)
|
|
if setting_sym:
|
|
if setting_sym.type is None:
|
|
# TODO: defer till setting_sym.type is not None
|
|
return AnyType(TypeOfAny.implementation_artifact)
|
|
|
|
return setting_sym.type
|
|
|
|
if not ignore_missing_settings:
|
|
ctx.api.fail(f"'Settings' object has no attribute {setting_name!r}", ctx.context)
|
|
|
|
return ctx.default_attr_type
|
|
|
|
|
|
def return_user_model_hook(ctx: FunctionContext, settings_modules: List[str]) -> Type:
|
|
from mypy.checker import TypeChecker
|
|
|
|
api = cast(TypeChecker, ctx.api)
|
|
|
|
setting_sym = get_setting_sym('AUTH_USER_MODEL', api, settings_modules)
|
|
if setting_sym is None:
|
|
return ctx.default_return_type
|
|
|
|
setting_module_name, _, _ = setting_sym.fullname.rpartition('.')
|
|
setting_module = api.modules[setting_module_name]
|
|
|
|
model_path = None
|
|
for name_expr, rvalue_expr in helpers.iter_over_assignments_in_class(setting_module):
|
|
if isinstance(name_expr, NameExpr) and isinstance(rvalue_expr, StrExpr):
|
|
if name_expr.name == 'AUTH_USER_MODEL':
|
|
model_path = rvalue_expr.value
|
|
break
|
|
|
|
if not model_path:
|
|
return ctx.default_return_type
|
|
|
|
app_label, _, model_class_name = model_path.rpartition('.')
|
|
if app_label is None:
|
|
return ctx.default_return_type
|
|
|
|
model_fullname = helpers.get_model_fullname(app_label, model_class_name,
|
|
all_modules=api.modules)
|
|
if model_fullname is None:
|
|
api.fail(f'"{app_label}.{model_class_name}" model class is not imported so far. Try to import it '
|
|
f'(under if TYPE_CHECKING) at the beginning of the current file',
|
|
context=ctx.context)
|
|
return ctx.default_return_type
|
|
|
|
model_info = helpers.lookup_fully_qualified_generic(model_fullname,
|
|
all_modules=api.modules)
|
|
if model_info is None or not isinstance(model_info, TypeInfo):
|
|
return ctx.default_return_type
|
|
return TypeType(Instance(model_info, []))
|