From 8a952b416e0ecd67dbdc8249c689832eec8afc91 Mon Sep 17 00:00:00 2001 From: Maxim Kurnikov Date: Wed, 30 Jan 2019 16:53:22 +0300 Subject: [PATCH] enable more test folders: db.functions --- django-stubs/db/models/expressions.pyi | 17 +++++--- django-stubs/db/models/functions/__init__.pyi | 41 +++++++++++++++++++ .../db/models/functions/comparison.pyi | 27 ++++-------- django-stubs/db/models/query.pyi | 10 +++-- django-stubs/db/models/query_utils.pyi | 1 + django-stubs/db/models/sql/__init__.pyi | 2 +- django-stubs/db/models/sql/compiler.pyi | 3 +- django-stubs/db/models/sql/constants.pyi | 14 +++++++ django-stubs/test/__init__.pyi | 1 + scripts/typecheck_tests.py | 35 +++++++++++++--- 10 files changed, 117 insertions(+), 34 deletions(-) create mode 100644 django-stubs/db/models/sql/constants.pyi diff --git a/django-stubs/db/models/expressions.pyi b/django-stubs/db/models/expressions.pyi index 76b2ad9..1a75e8b 100644 --- a/django-stubs/db/models/expressions.pyi +++ b/django-stubs/db/models/expressions.pyi @@ -1,13 +1,14 @@ from collections import OrderedDict from datetime import datetime, timedelta -from typing import Any, Callable, Dict, Iterator, List, Optional, Set, Tuple, Type, Union, Sequence +from typing import Any, Callable, Dict, Iterator, List, Optional, Sequence, Set, Tuple, Type, Union -from django.db.models import QuerySet, Q -from django.db.models.fields import Field from django.db.models.lookups import Lookup -from django.db.models.sql import Query from django.db.models.sql.compiler import SQLCompiler +from django.db.models import Q, QuerySet +from django.db.models.fields import Field +from django.db.models.sql import Query + _OutputField = Union[Field, str] class SQLiteNumericMixin: @@ -55,7 +56,6 @@ class BaseExpression: def get_db_converters(self, connection: Any) -> List[Callable]: ... def get_source_expressions(self) -> List[Any]: ... def set_source_expressions(self, exprs: List[Any]) -> None: ... - def as_sql(self, compiler: Any, connection: Any, **kwargs) -> None: ... def contains_aggregate(self) -> bool: ... def contains_over_clause(self) -> bool: ... def contains_column_references(self) -> bool: ... @@ -83,6 +83,12 @@ class BaseExpression: def reverse_ordering(self): ... def flatten(self) -> Iterator[Expression]: ... def __hash__(self) -> int: ... + def deconstruct(self) -> Any: ... + def as_sqlite(self, compiler: SQLCompiler, connection: Any) -> Any: ... + def as_sql(self, compiler: SQLCompiler, connection: Any, **extra_context: Any) -> Any: ... + def as_mysql(self, compiler: Any, connection: Any) -> Any: ... + def as_postgresql(self, compiler: Any, connection: Any) -> Any: ... + def as_oracle(self, compiler: Any, connection: Any): ... class Expression(BaseExpression, Combinable): ... @@ -117,6 +123,7 @@ class F(Combinable): ) -> Expression: ... def asc(self, **kwargs) -> OrderBy: ... def desc(self, **kwargs) -> OrderBy: ... + def deconstruct(self) -> Any: ... class OuterRef(F): ... diff --git a/django-stubs/db/models/functions/__init__.pyi b/django-stubs/db/models/functions/__init__.pyi index 4d1d7eb..6725deb 100644 --- a/django-stubs/db/models/functions/__init__.pyi +++ b/django-stubs/db/models/functions/__init__.pyi @@ -18,3 +18,44 @@ from .text import ( Replace as Replace, Substr as Substr, ) + +from .window import ( + CumeDist as CumeDist, + DenseRank as DenseRank, + FirstValue as FirstValue, + Lag as Lag, + LastValue as LastValue, + Lead as Lead, + NthValue as NthValue, + Ntile as Ntile, + PercentRank as PercentRank, + Rank as Rank, + RowNumber as RowNumber, +) + +from .datetime import ( + Extract as Extract, + ExtractDay as ExtractDay, + ExtractHour as ExtractHour, + ExtractMinute as ExtractMinute, + ExtractSecond as ExtractSecond, + ExtractMonth as ExtractMonth, + ExtractQuarter as ExtractQuarter, + ExtractWeek as ExtractWeek, + ExtractWeekDay as ExtractWeekDay, + ExtractYear as ExtractYear, + Trunc as Trunc, + TruncDate as TruncDate, + TruncDay as TruncDay, + TruncHour as TruncHour, + TruncMinute as TruncMinute, + TruncQuarter as TruncQuarter, + TruncMonth as TruncMonth, + TruncSecond as TruncSecond, + TruncTime as TruncTime, + TruncWeek as TruncWeek, + TruncYear as TruncYear, + Now as Now, +) + +from .comparison import Coalesce as Coalesce, Greatest as Greatest, Least as Least, Cast as Cast diff --git a/django-stubs/db/models/functions/comparison.pyi b/django-stubs/db/models/functions/comparison.pyi index fbc0655..fdd9b8d 100644 --- a/django-stubs/db/models/functions/comparison.pyi +++ b/django-stubs/db/models/functions/comparison.pyi @@ -1,12 +1,11 @@ -from datetime import date, datetime +from datetime import date from decimal import Decimal -from typing import Any, List, Optional, Tuple, Union +from typing import Any, Callable, Dict, List, Union + +from django.db.models.expressions import Combinable, Expression -from django.db.backends.sqlite3.base import DatabaseWrapper from django.db.models import Func -from django.db.models.expressions import Value from django.db.models.fields import Field -from django.db.models.sql.compiler import SQLCompiler class Cast(Func): contains_aggregate: bool @@ -14,15 +13,10 @@ class Cast(Func): extra: Dict[Any, Any] is_summary: bool output_field: Field - source_expressions: List[django.db.models.expressions.Combinable] + source_expressions: List[Combinable] function: str = ... template: str = ... - def __init__(self, expression: Union[date, Decimal, Value, str], output_field: Field) -> None: ... - def as_sql( - self, compiler: SQLCompiler, connection: DatabaseWrapper, **extra_context: Any - ) -> Tuple[str, Union[List[date], List[Decimal]]]: ... - def as_mysql(self, compiler: Any, connection: Any): ... - def as_postgresql(self, compiler: Any, connection: Any): ... + def __init__(self, expression: Union[date, Decimal, Expression, str], output_field: Union[str, Field]) -> None: ... class Coalesce(Func): contains_aggregate: bool @@ -30,10 +24,9 @@ class Coalesce(Func): extra: Dict[Any, Any] is_summary: bool output_field: Field - source_expressions: List[django.db.models.expressions.Combinable] + source_expressions: List[Combinable] function: str = ... def __init__(self, *expressions: Any, **extra: Any) -> None: ... - def as_oracle(self, compiler: Any, connection: Any): ... class Greatest(Func): contains_aggregate: bool @@ -42,10 +35,9 @@ class Greatest(Func): extra: Dict[Any, Any] is_summary: bool output_field: Field - source_expressions: List[django.db.models.expressions.Combinable] + source_expressions: List[Combinable] function: str = ... def __init__(self, *expressions: Any, **extra: Any) -> None: ... - def as_sqlite(self, compiler: SQLCompiler, connection: DatabaseWrapper) -> Tuple[str, List[datetime]]: ... class Least(Func): contains_aggregate: bool @@ -54,7 +46,6 @@ class Least(Func): extra: Dict[Any, Any] is_summary: bool output_field: Field - source_expressions: List[django.db.models.expressions.Combinable] + source_expressions: List[Combinable] function: str = ... def __init__(self, *expressions: Any, **extra: Any) -> None: ... - def as_sqlite(self, compiler: SQLCompiler, connection: DatabaseWrapper) -> Tuple[str, List[datetime]]: ... diff --git a/django-stubs/db/models/query.pyi b/django-stubs/db/models/query.pyi index b98d061..cfa1721 100644 --- a/django-stubs/db/models/query.pyi +++ b/django-stubs/db/models/query.pyi @@ -6,6 +6,8 @@ from django.db import models from django.db.models import Manager from django.db.models.sql.query import Query, RawQuery +from django.db.models.expressions import F, Combinable + _T = TypeVar("_T", bound=models.Model, covariant=True) class QuerySet(Iterable[_T], Sized): @@ -35,14 +37,14 @@ class QuerySet(Iterable[_T], Sized): def aggregate(self, *args: Any, **kwargs: Any) -> Dict[str, Any]: ... def get(self, *args: Any, **kwargs: Any) -> _T: ... def create(self, **kwargs: Any) -> _T: ... - def bulk_create(self, objs: Sequence[Model], batch_size: Optional[int] = ...) -> List[_T]: ... + def bulk_create(self, objs: Iterable[Model], batch_size: Optional[int] = ...) -> List[_T]: ... def get_or_create(self, defaults: Optional[Dict[str, Any]] = ..., **kwargs: Any) -> Tuple[_T, bool]: ... def update_or_create(self, defaults: Optional[Dict[str, Any]] = ..., **kwargs: Any) -> Tuple[_T, bool]: ... def earliest(self, *fields: Any, field_name: Optional[Any] = ...) -> _T: ... def latest(self, *fields: Any, field_name: Optional[Any] = ...) -> _T: ... def first(self) -> Optional[_T]: ... def last(self) -> Optional[_T]: ... - def in_bulk(self, id_list: Any = ..., *, field_name: str = ...) -> Dict[str, models.Model]: ... + def in_bulk(self, id_list: Any = ..., *, field_name: str = ...) -> Dict[Union[int, str], models.Model]: ... def delete(self) -> Tuple[int, Dict[str, int]]: ... def update(self, **kwargs: Any) -> int: ... def _update(self, values: Any) -> Optional[Any]: ... @@ -51,8 +53,8 @@ class QuerySet(Iterable[_T], Sized): def raw( self, raw_query: str, params: Any = ..., translations: Optional[Dict[str, str]] = ..., using: None = ... ) -> RawQuerySet: ... - def values(self, *fields: str, **expressions: Any) -> QuerySet: ... - def values_list(self, *fields: str, flat: bool = ..., named: bool = ...) -> QuerySet: ... + def values(self, *fields: Union[str, Combinable], **expressions: Any) -> QuerySet: ... + def values_list(self, *fields: Union[str, Combinable], flat: bool = ..., named: bool = ...) -> QuerySet: ... def dates(self, field_name: str, kind: str, order: str = ...) -> QuerySet: ... def datetimes(self, field_name: str, kind: str, order: str = ..., tzinfo: None = ...) -> QuerySet: ... def none(self) -> QuerySet[_T]: ... diff --git a/django-stubs/db/models/query_utils.pyi b/django-stubs/db/models/query_utils.pyi index c31331f..afc30c8 100644 --- a/django-stubs/db/models/query_utils.pyi +++ b/django-stubs/db/models/query_utils.pyi @@ -50,6 +50,7 @@ class DeferredAttribute: def __get__(self, instance: Optional[Model], cls: Type[Model] = ...) -> Any: ... class RegisterLookupMixin: + lookup_name: str @classmethod def get_lookups(cls) -> Dict[str, Any]: ... def get_lookup(self, lookup_name: str) -> Optional[Any]: ... diff --git a/django-stubs/db/models/sql/__init__.pyi b/django-stubs/db/models/sql/__init__.pyi index c90ae79..6797523 100644 --- a/django-stubs/db/models/sql/__init__.pyi +++ b/django-stubs/db/models/sql/__init__.pyi @@ -1 +1 @@ -from ..query import Query as Query, RawQuery as RawQuery +from .query import Query as Query, RawQuery as RawQuery diff --git a/django-stubs/db/models/sql/compiler.pyi b/django-stubs/db/models/sql/compiler.pyi index c245ed7..02a3907 100644 --- a/django-stubs/db/models/sql/compiler.pyi +++ b/django-stubs/db/models/sql/compiler.pyi @@ -6,7 +6,8 @@ from uuid import UUID from django.db.models.base import Model from django.db.models.expressions import BaseExpression, Expression -from django.db.models.sql import Query, RawQuery + +from django.db.models.sql.query import Query, RawQuery FORCE: Any diff --git a/django-stubs/db/models/sql/constants.pyi b/django-stubs/db/models/sql/constants.pyi new file mode 100644 index 0000000..70be2be --- /dev/null +++ b/django-stubs/db/models/sql/constants.pyi @@ -0,0 +1,14 @@ +from typing import Dict, Pattern, Tuple + +GET_ITERATOR_CHUNK_SIZE: int = ... + +MULTI: str = ... +SINGLE: str = ... +CURSOR: str = ... +NO_RESULTS: str = ... + +ORDER_PATTERN: Pattern = ... +ORDER_DIR: Dict[str, Tuple[str, str]] = ... + +INNER: str = ... +LOUTER: str = ... diff --git a/django-stubs/test/__init__.pyi b/django-stubs/test/__init__.pyi index 45106f2..9fec043 100644 --- a/django-stubs/test/__init__.pyi +++ b/django-stubs/test/__init__.pyi @@ -13,6 +13,7 @@ from .utils import ( modify_settings as modify_settings, override_script_prefix as override_script_prefix, override_system_checks as override_system_checks, + ignore_warnings as ignore_warnings, ) from .client import Client as Client, RequestFactory as RequestFactory diff --git a/scripts/typecheck_tests.py b/scripts/typecheck_tests.py index 6c98eae..26ffb9f 100644 --- a/scripts/typecheck_tests.py +++ b/scripts/typecheck_tests.py @@ -42,6 +42,8 @@ IGNORED_ERROR_PATTERNS = [ '"NullTranslations" has no attribute "_catalog"', 'Definition of "as_sql" in base class', 'expression has type "property"', + '"object" has no attribute "__iter__"', + 'Too few arguments for "dates" of "QuerySet"', re.compile(r'"Callable\[\[(Any(, )?)+\], Any\]" has no attribute'), re.compile(r'"HttpResponseBase" has no attribute "[A-Za-z_]+"'), re.compile(r'Incompatible types in assignment \(expression has type "Tuple\[\]", ' @@ -52,7 +54,7 @@ IGNORED_ERROR_PATTERNS = [ # TODO: remove when reassignment will be possible (in 0.670? ) re.compile(r'Incompatible types in assignment \(expression has type "(QuerySet|List){1}\[[A-Za-z, ]+\]", ' r'variable has type "(QuerySet|List){1}\[[A-Za-z, ]+\]"\)'), - re.compile(r'"MockRequest" has no attribute "[a-zA-Z_]+"'), + re.compile(r'"(MockRequest|DummyRequest|DummyUser)" has no attribute "[a-zA-Z_]+"'), ] # Test folders to typecheck @@ -64,20 +66,20 @@ TESTS_DIRS = [ 'admin_custom_urls', 'admin_default_site', 'admin_docs', - # # TODO: 'admin_filters', + # TODO: 'admin_filters', 'admin_inlines', 'admin_ordering', 'admin_registration', 'admin_scripts', - # # TODO: 'admin_utils', - # # TODO: 'admin_views', + # TODO: 'admin_utils', + # TODO: 'admin_views', 'admin_widgets', 'aggregation', 'aggregation_regress', 'annotations', 'app_loading', 'apps', - # # TODO: auth_tests + # TODO: auth_tests 'base', 'bash_completion', 'basic', @@ -92,6 +94,29 @@ TESTS_DIRS = [ 'csrf_tests', 'custom_columns', # TODO: 'custom_lookups', + # TODO: 'custom_managers', + 'custom_methods', + 'custom_migration_operations', + 'custom_pk', + 'datatypes', + 'dates', + 'datetimes', + 'db_functions', + 'db_typecasts', + 'db_utils', + 'dbshell', + # TODO: 'decorators', + 'defer', + # TODO: 'defer_regress', + 'delete', + 'delete_regress', + # TODO: 'deprecation', + # TODO: 'dispatch', + 'distinct_on_fields', + 'empty', + # TODO: 'expressions', + 'expressions_case', + # TODO: 'expressions_window' ]