From d43cb1fcd7961ca620aaf1d67949baf2e3c040f3 Mon Sep 17 00:00:00 2001 From: Maxim Kurnikov Date: Wed, 6 Feb 2019 22:20:12 +0300 Subject: [PATCH] fixes --- django-stubs/contrib/auth/base_user.pyi | 1 + django-stubs/contrib/auth/decorators.pyi | 2 + django-stubs/contrib/messages/__init__.pyi | 25 +++++++++- django-stubs/core/validators.pyi | 1 + django-stubs/db/models/__init__.pyi | 7 +++ django-stubs/db/models/fields/__init__.pyi | 55 ++++++++++++++++++---- django-stubs/db/models/fields/files.pyi | 4 +- django-stubs/db/models/fields/related.pyi | 1 + django-stubs/db/models/options.pyi | 4 +- django-stubs/http/multipartparser.pyi | 2 + django-stubs/template/loader.pyi | 1 + django-stubs/utils/encoding.pyi | 15 ++---- django-stubs/utils/functional.pyi | 1 + django-stubs/utils/html.pyi | 2 +- django-stubs/utils/termcolors.pyi | 4 +- mypy_django_plugin/plugins/models.py | 10 ++-- 16 files changed, 105 insertions(+), 30 deletions(-) diff --git a/django-stubs/contrib/auth/base_user.pyi b/django-stubs/contrib/auth/base_user.pyi index 268e99261..934944800 100644 --- a/django-stubs/contrib/auth/base_user.pyi +++ b/django-stubs/contrib/auth/base_user.pyi @@ -13,6 +13,7 @@ class AbstractBaseUser(models.Model): last_login: Optional[models.DateTimeField] = ... is_active: models.BooleanField = ... REQUIRED_FIELDS: List[str] = ... + class Meta: ... def get_username(self) -> str: ... def clean(self) -> None: ... def save(self, *args: Any, **kwargs: Any) -> None: ... diff --git a/django-stubs/contrib/auth/decorators.pyi b/django-stubs/contrib/auth/decorators.pyi index ed8d1dc8e..e2cdd0f04 100644 --- a/django-stubs/contrib/auth/decorators.pyi +++ b/django-stubs/contrib/auth/decorators.pyi @@ -1,5 +1,7 @@ from typing import Any, Callable, List, Optional, Set, Union +from django.contrib.auth import REDIRECT_FIELD_NAME as REDIRECT_FIELD_NAME + def user_passes_test( test_func: Callable, login_url: Optional[str] = ..., redirect_field_name: str = ... ) -> Callable: ... diff --git a/django-stubs/contrib/messages/__init__.pyi b/django-stubs/contrib/messages/__init__.pyi index 6386c1178..1ff9c7d09 100644 --- a/django-stubs/contrib/messages/__init__.pyi +++ b/django-stubs/contrib/messages/__init__.pyi @@ -1 +1,24 @@ -from .api import get_level as get_level, set_level as set_level +from .api import ( + get_level as get_level, + set_level as set_level, + add_message as add_message, + debug as debug, + error as error, + success as success, + get_messages as get_messages, + MessageFailure as MessageFailure, + info as info, + warning as warning, +) + +from .constants import ( + DEBUG as DEBUG, + DEFAULT_LEVELS as DEFAULT_LEVELS, + DEFAULT_TAGS as DEFAULT_TAGS, + ERROR as ERROR, + INFO as INFO, + SUCCESS as SUCCESS, + WARNING as WARNING, +) + +default_app_config: str = ... diff --git a/django-stubs/core/validators.pyi b/django-stubs/core/validators.pyi index f7760a714..093867f93 100644 --- a/django-stubs/core/validators.pyi +++ b/django-stubs/core/validators.pyi @@ -5,6 +5,7 @@ from typing import Any, Dict, List, Optional, Union, Pattern from uuid import UUID from django.core.files.base import File +from django.core.exceptions import ValidationError as ValidationError EMPTY_VALUES: Any diff --git a/django-stubs/db/models/__init__.pyi b/django-stubs/db/models/__init__.pyi index 2d4037844..8f4d224bc 100644 --- a/django-stubs/db/models/__init__.pyi +++ b/django-stubs/db/models/__init__.pyi @@ -12,6 +12,7 @@ from .aggregates import ( ) from .fields import ( + FieldDoesNotExist as FieldDoesNotExist, AutoField as AutoField, IntegerField as IntegerField, PositiveIntegerField as PositiveIntegerField, @@ -38,6 +39,8 @@ from .fields import ( BinaryField as BinaryField, DurationField as DurationField, BigAutoField as BigAutoField, + FileField as FileField, + CommaSeparatedIntegerField as CommaSeparatedIntegerField, ) from .fields.related import ( @@ -45,6 +48,10 @@ from .fields.related import ( OneToOneField as OneToOneField, ManyToManyField as ManyToManyField, ForeignObject as ForeignObject, + ManyToManyRel as ManyToManyRel, + ManyToOneRel as ManyToOneRel, + OneToOneRel as OneToOneRel, + ForeignObjectRel as ForeignObjectRel, ) from .fields.files import ImageField as ImageField, FileField as FileField from .fields.proxy import OrderWrt as OrderWrt diff --git a/django-stubs/db/models/fields/__init__.pyi b/django-stubs/db/models/fields/__init__.pyi index 04628153e..0e942b157 100644 --- a/django-stubs/db/models/fields/__init__.pyi +++ b/django-stubs/db/models/fields/__init__.pyi @@ -1,15 +1,17 @@ from typing import Any, Optional, Tuple, Iterable, Callable, Dict, Union, Type import decimal +from django.core.files.storage import Storage from django.db.models import Model from django.db.models.query_utils import RegisterLookupMixin from django.db.models.expressions import F, Combinable +from django.core.exceptions import FieldDoesNotExist as FieldDoesNotExist from django.forms import Widget, Field as FormField from .mixins import NOT_PROVIDED as NOT_PROVIDED _Choice = Tuple[Any, str] -_ChoiceNamedGroup = Tuple[str, Iterable[_Choice]] +_ChoiceNamedGroup = Union[Tuple[str, Iterable[_Choice]], Tuple[str, Any]] _FieldChoices = Iterable[Union[_Choice, _ChoiceNamedGroup]] _ValidatorCallable = Callable[..., None] @@ -20,11 +22,12 @@ class Field(RegisterLookupMixin): help_text: str db_table: str remote_field: Field + max_length: Optional[int] model: Type[Model] name: str def __init__( self, - verbose_name: Optional[str] = ..., + verbose_name: Optional[Union[str, bytes]] = ..., name: Optional[str] = ..., primary_key: bool = ..., max_length: Optional[int] = ..., @@ -52,6 +55,7 @@ class Field(RegisterLookupMixin): def db_type(self, connection: Any) -> str: ... def db_parameters(self, connection: Any) -> Dict[str, str]: ... def get_prep_value(self, value: Any) -> Any: ... + def get_internal_type(self) -> str: ... def formfield(self, **kwargs) -> FormField: ... def contribute_to_class(self, cls: Type[Model], name: str, private_only: bool = ...) -> None: ... @@ -71,7 +75,7 @@ class FloatField(Field): ... class DecimalField(Field): def __init__( self, - verbose_name: Optional[str] = ..., + verbose_name: Optional[Union[str, bytes]] = ..., name: Optional[str] = ..., max_digits: Optional[int] = ..., decimal_places: Optional[int] = ..., @@ -99,7 +103,7 @@ class AutoField(Field): class CharField(Field): def __init__( self, - verbose_name: Optional[str] = ..., + verbose_name: Optional[Union[str, bytes]] = ..., name: Optional[str] = ..., primary_key: bool = ..., max_length: Optional[int] = ..., @@ -127,7 +131,7 @@ class CharField(Field): class SlugField(CharField): def __init__( self, - verbose_name: Optional[str] = ..., + verbose_name: Optional[Union[str, bytes]] = ..., name: Optional[str] = ..., primary_key: bool = ..., max_length: Optional[int] = ..., @@ -166,7 +170,34 @@ class NullBooleanField(Field): def __set__(self, instance, value: Optional[bool]) -> None: ... def __get__(self, instance, owner) -> Optional[bool]: ... -class FileField(Field): ... +class FileField(Field): + def __init__( + self, + verbose_name: Optional[Union[str, bytes]] = ..., + name: Optional[str] = ..., + upload_to: str = ..., + storage: Optional[Storage] = ..., + primary_key: bool = ..., + max_length: Optional[int] = ..., + unique: bool = ..., + blank: bool = ..., + null: bool = ..., + db_index: bool = ..., + default: Any = ..., + editable: bool = ..., + auto_created: bool = ..., + serialize: bool = ..., + unique_for_date: Optional[str] = ..., + unique_for_month: Optional[str] = ..., + unique_for_year: Optional[str] = ..., + choices: Optional[_FieldChoices] = ..., + help_text: str = ..., + db_column: Optional[str] = ..., + db_tablespace: Optional[str] = ..., + validators: Iterable[_ValidatorCallable] = ..., + error_messages: Optional[_ErrorMessagesToOverride] = ..., + ): ... + class IPAddressField(Field): ... class GenericIPAddressField(Field): @@ -201,7 +232,7 @@ class DateTimeCheckMixin: ... class DateField(DateTimeCheckMixin, Field): def __init__( self, - verbose_name: Optional[str] = ..., + verbose_name: Optional[Union[str, bytes]] = ..., name: Optional[str] = ..., auto_now: bool = ..., auto_now_add: bool = ..., @@ -226,7 +257,7 @@ class DateField(DateTimeCheckMixin, Field): class TimeField(DateTimeCheckMixin, Field): def __init__( self, - verbose_name: Optional[str] = ..., + verbose_name: Optional[Union[str, bytes]] = ..., name: Optional[str] = ..., auto_now: bool = ..., auto_now_add: bool = ..., @@ -251,9 +282,14 @@ class DateTimeField(DateField): ... class UUIDField(Field): ... class FilePathField(Field): + path: str = ... + match: Optional[Any] = ... + recursive: bool = ... + allow_files: bool = ... + allow_folders: bool = ... def __init__( self, - verbose_name: Optional[str] = ..., + verbose_name: Optional[Union[str, bytes]] = ..., name: Optional[str] = ..., path: str = ..., match: Optional[Any] = ..., @@ -281,3 +317,4 @@ class FilePathField(Field): class BinaryField(Field): ... class DurationField(Field): ... class BigAutoField(AutoField): ... +class CommaSeparatedIntegerField(CharField): ... diff --git a/django-stubs/db/models/fields/files.pyi b/django-stubs/db/models/fields/files.pyi index bb53d5944..9d031a53f 100644 --- a/django-stubs/db/models/fields/files.pyi +++ b/django-stubs/db/models/fields/files.pyi @@ -1,4 +1,4 @@ -from typing import Any, Callable, List, Optional, Type, Union +from typing import Any, Callable, List, Optional, Type, Union, Tuple from django.core.checks.messages import Error from django.core.files.base import File @@ -9,6 +9,8 @@ from django.db.models.base import Model from django.db.models.fields import Field from django.forms import fields as form_fields +BLANK_CHOICE_DASH: List[Tuple[str, str]] = ... + class FieldFile(File): instance: Model = ... field: FileField = ... diff --git a/django-stubs/db/models/fields/related.pyi b/django-stubs/db/models/fields/related.pyi index 2cb971a22..5d7ffe3cf 100644 --- a/django-stubs/db/models/fields/related.pyi +++ b/django-stubs/db/models/fields/related.pyi @@ -29,6 +29,7 @@ from django.db.models.fields.reverse_related import ( ForeignObjectRel as ForeignObjectRel, ManyToManyRel as ManyToManyRel, ManyToOneRel as ManyToOneRel, + OneToOneRel as OneToOneRel, ) from django.db.models.query_utils import PathInfo, Q diff --git a/django-stubs/db/models/options.pyi b/django-stubs/db/models/options.pyi index 7c58a08ef..1b58182b7 100644 --- a/django-stubs/db/models/options.pyi +++ b/django-stubs/db/models/options.pyi @@ -20,7 +20,7 @@ from django.db.models.fields import Field, mixins, AutoField PROXY_PARENTS: Any EMPTY_RELATION_TREE: Any IMMUTABLE_WARNING: str -DEFAULT_NAMES: Any +DEFAULT_NAMES: Tuple[str, ...] def normalize_together( option_together: Any @@ -102,7 +102,7 @@ class Options: def swapped(self) -> Optional[str]: ... def many_to_many(self) -> ImmutableList: ... def fields_map(self) -> Dict[str, ForeignObjectRel]: ... - def get_field(self, field_name: Union[Callable, str]) -> Union[Field, mixins.FieldCacheMixin]: ... + def get_field(self, field_name: Union[Callable, str]) -> Field: ... def get_base_chain(self, model: Type[Model]) -> List[Type[Model]]: ... def get_parent_list(self) -> List[Type[Model]]: ... def get_ancestor_link(self, ancestor: Type[Model]) -> Optional[OneToOneField]: ... diff --git a/django-stubs/http/multipartparser.pyi b/django-stubs/http/multipartparser.pyi index b94fdcb3c..e55283cc4 100644 --- a/django-stubs/http/multipartparser.pyi +++ b/django-stubs/http/multipartparser.pyi @@ -50,3 +50,5 @@ class BoundaryIter: class Parser: def __init__(self, stream: LazyStream, boundary: bytes) -> None: ... def __iter__(self) -> Iterator[Tuple[str, Dict[str, Tuple[str, Dict[str, Union[bytes, str]]]], LazyStream]]: ... + +def parse_header(line: bytes) -> Tuple[str, Dict[str, Any]]: ... diff --git a/django-stubs/template/loader.pyi b/django-stubs/template/loader.pyi index 693d8816a..b79861dec 100644 --- a/django-stubs/template/loader.pyi +++ b/django-stubs/template/loader.pyi @@ -1,4 +1,5 @@ from typing import Any, Dict, List, Optional, Union +from . import engines as engines from django.http.request import HttpRequest from django.template.exceptions import TemplateDoesNotExist as TemplateDoesNotExist diff --git a/django-stubs/utils/encoding.pyi b/django-stubs/utils/encoding.pyi index 976de9a53..5e44ae0e5 100644 --- a/django-stubs/utils/encoding.pyi +++ b/django-stubs/utils/encoding.pyi @@ -1,7 +1,4 @@ -from datetime import date -from typing import Any, Optional, Union - -from django.db.models.base import Model +from typing import Any, Optional class DjangoUnicodeDecodeError(UnicodeDecodeError): obj: bytes = ... @@ -9,13 +6,11 @@ class DjangoUnicodeDecodeError(UnicodeDecodeError): python_2_unicode_compatible: Any -def smart_text(s: Union[Model, int, str], encoding: str = ..., strings_only: bool = ..., errors: str = ...) -> str: ... +def smart_text(s: Any, encoding: str = ..., strings_only: bool = ..., errors: str = ...) -> str: ... def is_protected_type(obj: Any) -> bool: ... -def force_text( - s: Optional[Union[bytes, Model, int, str]], encoding: str = ..., strings_only: bool = ..., errors: str = ... -) -> Optional[Union[int, str]]: ... -def smart_bytes(s: Union[int, str], encoding: str = ..., strings_only: bool = ..., errors: str = ...) -> bytes: ... -def force_bytes(s: Any, encoding: str = ..., strings_only: bool = ..., errors: str = ...) -> Union[bytes, date]: ... +def force_text(s: Any, encoding: str = ..., strings_only: bool = ..., errors: str = ...) -> Optional[str]: ... +def smart_bytes(s: Any, encoding: str = ..., strings_only: bool = ..., errors: str = ...) -> bytes: ... +def force_bytes(s: Any, encoding: str = ..., strings_only: bool = ..., errors: str = ...) -> bytes: ... smart_str = smart_text force_str = force_text diff --git a/django-stubs/utils/functional.pyi b/django-stubs/utils/functional.pyi index 3bf9de2ca..d5695fd3f 100644 --- a/django-stubs/utils/functional.pyi +++ b/django-stubs/utils/functional.pyi @@ -1,4 +1,5 @@ from typing import Any, Callable, Dict, List, Optional, Tuple, Type, Union +from functools import wraps as wraps from django.db.models.base import Model diff --git a/django-stubs/utils/html.pyi b/django-stubs/utils/html.pyi index f77354cea..622327ab7 100644 --- a/django-stubs/utils/html.pyi +++ b/django-stubs/utils/html.pyi @@ -3,7 +3,7 @@ from typing import Any, Dict, Iterator, List, Optional, Tuple, Union from django.db.models.base import Model from django.db.models.fields.files import FieldFile -from django.utils.safestring import SafeText +from django.utils.safestring import SafeText, mark_safe as mark_safe TRAILING_PUNCTUATION_CHARS: str WRAPPING_PUNCTUATION: Any diff --git a/django-stubs/utils/termcolors.pyi b/django-stubs/utils/termcolors.pyi index 29449b6ac..ac176a423 100644 --- a/django-stubs/utils/termcolors.pyi +++ b/django-stubs/utils/termcolors.pyi @@ -1,4 +1,4 @@ -from typing import Any, Callable, Dict, Optional, Tuple, Union +from typing import Any, Callable, Dict, Optional, Tuple, Union, Sequence color_names: Any foreground: Any @@ -6,7 +6,7 @@ background: Any RESET: str opt_dict: Any -def colorize(text: Optional[str] = ..., opts: Union[Tuple, str] = ..., **kwargs: Any) -> str: ... +def colorize(text: Optional[str] = ..., opts: Sequence[str] = ..., **kwargs: Any) -> str: ... def make_style(opts: Tuple = ..., **kwargs: Any) -> Callable: ... NOCOLOR_PALETTE: str diff --git a/mypy_django_plugin/plugins/models.py b/mypy_django_plugin/plugins/models.py index 86e4b0e9f..4ab45977e 100644 --- a/mypy_django_plugin/plugins/models.py +++ b/mypy_django_plugin/plugins/models.py @@ -173,10 +173,12 @@ def get_related_field_type(rvalue: CallExpr, api: SemanticAnalyzerPass2, def is_related_field(expr: CallExpr, module_file: MypyFile) -> bool: if isinstance(expr.callee, MemberExpr) and isinstance(expr.callee.expr, NameExpr): - module = module_file.names[expr.callee.expr.name] - if module.fullname == 'django.db.models' and expr.callee.name in {'ForeignKey', - 'OneToOneField', - 'ManyToManyField'}: + module = module_file.names.get(expr.callee.expr.name) + if module \ + and module.fullname == 'django.db.models' \ + and expr.callee.name in {'ForeignKey', + 'OneToOneField', + 'ManyToManyField'}: return True return False