diff --git a/django-stubs/db/__init__.pyi b/django-stubs/db/__init__.pyi index 7427ad91f..d8f9e3e9e 100644 --- a/django-stubs/db/__init__.pyi +++ b/django-stubs/db/__init__.pyi @@ -1,12 +1,9 @@ from typing import Any -from django.db.backends.utils import CursorWrapper - -from . import migrations as migrations -from .utils import DEFAULT_DB_ALIAS as DEFAULT_DB_ALIAS +from .backends.base.base import BaseDatabaseWrapper +from .utils import DEFAULT_DB_ALIAS as DEFAULT_DB_ALIAS # Not exported in __all__ from .utils import DJANGO_VERSION_PICKLE_KEY as DJANGO_VERSION_PICKLE_KEY -from .utils import ConnectionDoesNotExist as ConnectionDoesNotExist -from .utils import ConnectionHandler as ConnectionHandler +from .utils import ConnectionHandler, ConnectionRouter from .utils import DatabaseError as DatabaseError from .utils import DataError as DataError from .utils import Error as Error @@ -18,14 +15,28 @@ from .utils import OperationalError as OperationalError from .utils import ProgrammingError as ProgrammingError connections: ConnectionHandler -router: Any -connection: DefaultConnectionProxy - -class DefaultConnectionProxy: - def cursor(self) -> CursorWrapper: ... - def __getattr__(self, item: str) -> Any: ... - def __setattr__(self, name: str, value: Any) -> None: ... - def __delattr__(self, name: str) -> None: ... +router: ConnectionRouter +# Actually ConnectionProxy, but quacks exactly like BaseDatabaseWrapper, it's not worth distinguishing the two. +connection: BaseDatabaseWrapper def close_old_connections(**kwargs: Any) -> None: ... def reset_queries(**kwargs: Any) -> None: ... + +__all__ = [ + "DEFAULT_DB_ALIAS", + "DJANGO_VERSION_PICKLE_KEY", + "DataError", + "DatabaseError", + "Error", + "IntegrityError", + "InterfaceError", + "InternalError", + "NotSupportedError", + "OperationalError", + "ProgrammingError", + "close_old_connections", + "connection", + "connections", + "reset_queries", + "router", +] diff --git a/django-stubs/db/backends/base/operations.pyi b/django-stubs/db/backends/base/operations.pyi index 6029d0895..05b1923b9 100644 --- a/django-stubs/db/backends/base/operations.pyi +++ b/django-stubs/db/backends/base/operations.pyi @@ -4,7 +4,6 @@ from decimal import Decimal from typing import Any, TypeAlias from django.core.management.color import Style -from django.db import DefaultConnectionProxy from django.db.backends.base.base import BaseDatabaseWrapper from django.db.backends.utils import CursorWrapper from django.db.models.base import Model @@ -12,7 +11,7 @@ from django.db.models.expressions import Case, Expression from django.db.models.fields import Field from django.db.models.sql.compiler import SQLCompiler -_Connection: TypeAlias = DefaultConnectionProxy | BaseDatabaseWrapper +_Connection: TypeAlias = BaseDatabaseWrapper class BaseDatabaseOperations: compiler_module: str = ... diff --git a/django-stubs/db/migrations/executor.pyi b/django-stubs/db/migrations/executor.pyi index cb6bba9d0..44a7ff98b 100644 --- a/django-stubs/db/migrations/executor.pyi +++ b/django-stubs/db/migrations/executor.pyi @@ -1,7 +1,6 @@ -from collections.abc import Callable -from typing import Any +from collections.abc import Sequence +from typing import Protocol, type_check_only -from django.db import DefaultConnectionProxy from django.db.backends.base.base import BaseDatabaseWrapper from django.db.migrations.migration import Migration @@ -9,38 +8,36 @@ from .loader import MigrationLoader from .recorder import MigrationRecorder from .state import ProjectState +@type_check_only +class _ProgressCallbackT(Protocol): + def __call__(self, action: str, migration: Migration | None = ..., fake: bool | None = ..., /) -> None: ... + class MigrationExecutor: - connection: Any = ... - loader: MigrationLoader = ... - recorder: MigrationRecorder = ... - progress_callback: Callable[..., Any] = ... + connection: BaseDatabaseWrapper + loader: MigrationLoader + recorder: MigrationRecorder + progress_callback: _ProgressCallbackT | None def __init__( self, - connection: DefaultConnectionProxy | BaseDatabaseWrapper | None, - progress_callback: Callable[..., Any] | None = ..., + connection: BaseDatabaseWrapper | None, + progress_callback: _ProgressCallbackT | None = None, ) -> None: ... def migration_plan( - self, - targets: list[tuple[str, str | None]] | set[tuple[str, str]], - clean_start: bool = ..., + self, targets: Sequence[tuple[str, str | None]] | set[tuple[str, str]], clean_start: bool = False ) -> list[tuple[Migration, bool]]: ... def migrate( self, - targets: list[tuple[str, str | None]] | None, - plan: list[tuple[Migration, bool]] | None = ..., - state: ProjectState | None = ..., - fake: bool = ..., - fake_initial: bool = ..., + targets: Sequence[tuple[str, str | None]] | None, + plan: Sequence[tuple[Migration, bool]] | None = None, + state: ProjectState | None = None, + fake: bool = False, + fake_initial: bool = False, ) -> ProjectState: ... - def collect_sql(self, plan: list[tuple[Migration, bool]]) -> list[str]: ... def apply_migration( - self, - state: ProjectState, - migration: Migration, - fake: bool = ..., - fake_initial: bool = ..., + self, state: ProjectState, migration: Migration, fake: bool = False, fake_initial: bool = False ) -> ProjectState: ... - def unapply_migration(self, state: ProjectState, migration: Migration, fake: bool = ...) -> ProjectState: ... + def record_migration(self, app_label: str, name: str, forward: bool = True) -> None: ... + def unapply_migration(self, state: ProjectState, migration: Migration, fake: bool = False) -> ProjectState: ... def check_replacements(self) -> None: ... def detect_soft_applied( self, project_state: ProjectState | None, migration: Migration diff --git a/django-stubs/db/models/__init__.pyi b/django-stubs/db/models/__init__.pyi index c26750d57..651463131 100644 --- a/django-stubs/db/models/__init__.pyi +++ b/django-stubs/db/models/__init__.pyi @@ -3,6 +3,7 @@ from django.core.exceptions import ObjectDoesNotExist as ObjectDoesNotExist from . import lookups as lookups from . import signals as signals from .aggregates import Aggregate as Aggregate +from .aggregates import AnyValue as AnyValue from .aggregates import Avg as Avg from .aggregates import Count as Count from .aggregates import Max as Max @@ -11,6 +12,7 @@ from .aggregates import StdDev as StdDev from .aggregates import StringAgg as StringAgg from .aggregates import Sum as Sum from .aggregates import Variance as Variance +from .base import DEFERRED as DEFERRED from .base import Model as Model from .constraints import BaseConstraint as BaseConstraint from .constraints import CheckConstraint as CheckConstraint @@ -44,6 +46,7 @@ from .expressions import ValueRange as ValueRange from .expressions import When as When from .expressions import Window as Window from .expressions import WindowFrame as WindowFrame +from .expressions import WindowFrameExclusion as WindowFrameExclusion from .fields import BLANK_CHOICE_DASH as BLANK_CHOICE_DASH from .fields import NOT_PROVIDED as NOT_PROVIDED from .fields import AutoField as AutoField @@ -52,17 +55,20 @@ from .fields import BigIntegerField as BigIntegerField from .fields import BinaryField as BinaryField from .fields import BooleanField as BooleanField from .fields import CharField as CharField +from .fields import CommaSeparatedIntegerField as CommaSeparatedIntegerField from .fields import DateField as DateField from .fields import DateTimeField as DateTimeField from .fields import DecimalField as DecimalField from .fields import DurationField as DurationField from .fields import EmailField as EmailField +from .fields import Empty as Empty from .fields import Field as Field from .fields import FilePathField as FilePathField from .fields import FloatField as FloatField from .fields import GenericIPAddressField as GenericIPAddressField from .fields import IntegerField as IntegerField from .fields import IPAddressField as IPAddressField +from .fields import NullBooleanField as NullBooleanField from .fields import PositiveBigIntegerField as PositiveBigIntegerField from .fields import PositiveIntegerField as PositiveIntegerField from .fields import PositiveSmallIntegerField as PositiveSmallIntegerField @@ -101,6 +107,7 @@ from .query_utils import Q as Q __all__ = [ "BLANK_CHOICE_DASH", "CASCADE", + "DEFERRED", "DO_NOTHING", "NOT_PROVIDED", "PROTECT", @@ -109,6 +116,7 @@ __all__ = [ "SET_DEFAULT", "SET_NULL", "Aggregate", + "AnyValue", "AutoField", "Avg", "BaseConstraint", @@ -120,6 +128,7 @@ __all__ = [ "CharField", "CheckConstraint", "Choices", + "CommaSeparatedIntegerField", "CompositePrimaryKey", "Count", "DateField", @@ -128,6 +137,7 @@ __all__ = [ "Deferrable", "DurationField", "EmailField", + "Empty", "Exists", "Expression", "ExpressionList", @@ -158,6 +168,7 @@ __all__ = [ "Max", "Min", "Model", + "NullBooleanField", "ObjectDoesNotExist", "OneToOneField", "OneToOneRel", @@ -193,6 +204,7 @@ __all__ = [ "When", "Window", "WindowFrame", + "WindowFrameExclusion", "aprefetch_related_objects", "prefetch_related_objects", "signals", diff --git a/django-stubs/db/models/aggregates.pyi b/django-stubs/db/models/aggregates.pyi index fe8759d5d..191df47dc 100644 --- a/django-stubs/db/models/aggregates.pyi +++ b/django-stubs/db/models/aggregates.pyi @@ -1,21 +1,98 @@ -from typing import Any +from collections.abc import Sequence +from typing import Any, ClassVar +from django.db.backends.base.base import BaseDatabaseWrapper from django.db.models.expressions import Combinable, Func +from django.db.models.fields import IntegerField +from django.db.models.functions.mixins import FixDurationInputMixin, NumericOutputFieldMixin +from django.db.models.query import _OrderByFieldName +from django.db.models.query_utils import Q +from django.db.models.sql.compiler import SQLCompiler, _AsSqlType +from typing_extensions import override class Aggregate(Func): - filter_template: str = ... - filter: Any = ... - allow_distinct: bool = ... - def __init__(self, *expressions: Any, distinct: bool = ..., filter: Any | None = ..., **extra: Any) -> None: ... + name: str + filter: Any + allow_distinct: bool + allow_order_by: bool + empty_result_set_value: int | None + def __init__( + self, + *expressions: Any, + distinct: bool = False, + filter: Q | None = None, + default: Any | None = None, + order_by: _OrderByFieldName | Sequence[_OrderByFieldName] | None = None, + **extra: Any, + ) -> None: ... + @property + def default_alias(self) -> str: ... + @override + def as_sql( # type: ignore[override] + self, compiler: SQLCompiler, connection: BaseDatabaseWrapper, **extra_context: Any + ) -> _AsSqlType: ... + +class AnyValue(Aggregate): + @override + def as_sql( # type: ignore[override] + self, compiler: SQLCompiler, connection: BaseDatabaseWrapper, **extra_context: Any + ) -> _AsSqlType: ... + +class Avg(FixDurationInputMixin, NumericOutputFieldMixin, Aggregate): ... + +class Count(Aggregate): + output_field: ClassVar[IntegerField[Any]] + def __init__( + self, + expression: Combinable | str, + filter: Q | None = None, + *, + distinct: bool = False, + **extra: Any, + ) -> None: ... -class Avg(Aggregate): ... -class Count(Aggregate): ... class Max(Aggregate): ... class Min(Aggregate): ... -class StdDev(Aggregate): ... + +class StdDev(NumericOutputFieldMixin, Aggregate): + def __init__( + self, + expression: Combinable | str, + sample: bool = False, + *, + filter: Q | None = None, + default: Any | None = None, + **extra: Any, + ) -> None: ... class StringAgg(Aggregate): - def __init__(self, expression: Combinable | str, delimiter: Combinable | str, **extra: Any) -> None: ... + def __init__( + self, + expression: Combinable | str, + delimiter: str | Combinable, + *, + distinct: bool = False, + filter: Q | None = None, + default: Any | None = None, + order_by: _OrderByFieldName | Sequence[_OrderByFieldName] | None = None, + **extra: Any, + ) -> None: ... + def as_oracle(self, compiler: SQLCompiler, connection: BaseDatabaseWrapper, **extra_context: Any) -> _AsSqlType: ... + def as_mysql(self, compiler: SQLCompiler, connection: BaseDatabaseWrapper, **extra_context: Any) -> _AsSqlType: ... + @override + def as_sqlite(self, compiler: SQLCompiler, connection: BaseDatabaseWrapper, **extra_context: Any) -> _AsSqlType: ... # type: ignore[override] + +class Sum(FixDurationInputMixin, Aggregate): ... + +class Variance(NumericOutputFieldMixin, Aggregate): + def __init__( + self, + expression: Combinable | str, + sample: bool = False, + *, + filter: Q | None = None, + default: Any | None = None, + **extra: Any, + ) -> None: ... -class Sum(Aggregate): ... -class Variance(Aggregate): ... +__all__ = ["Aggregate", "AnyValue", "Avg", "Count", "Max", "Min", "StdDev", "StringAgg", "Sum", "Variance"] diff --git a/django-stubs/db/models/base.pyi b/django-stubs/db/models/base.pyi index 873af6d05..1a21036f7 100644 --- a/django-stubs/db/models/base.pyi +++ b/django-stubs/db/models/base.pyi @@ -9,6 +9,10 @@ from django.db.models.options import Options from django.db.models.query import QuerySet from typing_extensions import Self +class Deferred: ... + +DEFERRED: Deferred + class ModelStateFieldsCacheDescriptor: ... class ModelState: diff --git a/django-stubs/db/models/expressions.pyi b/django-stubs/db/models/expressions.pyi index 160ea03cc..7bc1e76cb 100644 --- a/django-stubs/db/models/expressions.pyi +++ b/django-stubs/db/models/expressions.pyi @@ -1,6 +1,7 @@ from collections.abc import Callable, Iterable, Iterator, Sequence from datetime import datetime, timedelta from decimal import Decimal +from enum import Enum from typing import Any, TypeAlias from django.db.models import Q, QuerySet @@ -225,6 +226,12 @@ class Window(Expression): output_field: _OutputField | None = ..., ) -> None: ... +class WindowFrameExclusion(Enum): + CURRENT_ROW = "CURRENT ROW" + GROUP = "GROUP" + TIES = "TIES" + NO_OTHERS = "NO OTHERS" + class WindowFrame(Expression): template: str = ... frame_type: str = ... diff --git a/django-stubs/db/models/fields/__init__.pyi b/django-stubs/db/models/fields/__init__.pyi index 44c4a3ffe..004dabb05 100644 --- a/django-stubs/db/models/fields/__init__.pyi +++ b/django-stubs/db/models/fields/__init__.pyi @@ -30,6 +30,7 @@ _ST = TypeVar("_ST") # __get__ return type _GT = TypeVar("_GT") +class Empty: ... class NOT_PROVIDED: ... class Field(RegisterLookupMixin, Generic[_ST, _GT]): @@ -761,6 +762,8 @@ class CharField(Field[_C | Combinable, _C], Generic[_C]): error_messages: _ErrorMessagesToOverride | None = ..., ) -> CharField[str | None]: ... +class CommaSeparatedIntegerField(CharField[_C]): ... + class SlugField(CharField[_C]): @overload def __new__( @@ -1065,6 +1068,8 @@ class BooleanField(Field[_B | Combinable, _B], Generic[_B]): error_messages: _ErrorMessagesToOverride | None = ..., ) -> BooleanField[bool | None]: ... +NullBooleanField: TypeAlias = BooleanField[bool | None] + class IPAddressField(Field[_C | Combinable, _C], Generic[_C]): @overload def __new__( diff --git a/django-stubs/db/models/functions/__init__.pyi b/django-stubs/db/models/functions/__init__.pyi index 8dd3e0407..e9d295c25 100644 --- a/django-stubs/db/models/functions/__init__.pyi +++ b/django-stubs/db/models/functions/__init__.pyi @@ -2,12 +2,12 @@ from .comparison import Cast as Cast from .comparison import Coalesce as Coalesce from .comparison import Collate as Collate from .comparison import Greatest as Greatest -from .comparison import JSONObject as JSONObject from .comparison import Least as Least from .comparison import NullIf as NullIf from .datetime import Extract as Extract from .datetime import ExtractDay as ExtractDay from .datetime import ExtractHour as ExtractHour +from .datetime import ExtractIsoWeekDay as ExtractIsoWeekDay from .datetime import ExtractIsoYear as ExtractIsoYear from .datetime import ExtractMinute as ExtractMinute from .datetime import ExtractMonth as ExtractMonth @@ -28,6 +28,8 @@ from .datetime import TruncSecond as TruncSecond from .datetime import TruncTime as TruncTime from .datetime import TruncWeek as TruncWeek from .datetime import TruncYear as TruncYear +from .json import JSONArray as JSONArray +from .json import JSONObject as JSONObject from .math import Abs as Abs from .math import ACos as ACos from .math import ASin as ASin @@ -45,11 +47,13 @@ from .math import Mod as Mod from .math import Pi as Pi from .math import Power as Power from .math import Radians as Radians +from .math import Random as Random from .math import Round as Round from .math import Sign as Sign from .math import Sin as Sin from .math import Sqrt as Sqrt from .math import Tan as Tan +from .text import MD5 as MD5 from .text import SHA1 as SHA1 from .text import SHA224 as SHA224 from .text import SHA256 as SHA256 @@ -85,3 +89,103 @@ from .window import Ntile as Ntile from .window import PercentRank as PercentRank from .window import Rank as Rank from .window import RowNumber as RowNumber + +__all__ = [ + # text + "MD5", + "SHA1", + "SHA224", + "SHA256", + "SHA384", + "SHA512", + "ACos", + "ASin", + "ATan", + "ATan2", + # math + "Abs", + # comparison and conversion + "Cast", + "Ceil", + "Chr", + "Coalesce", + "Collate", + "Concat", + "ConcatPair", + "Cos", + "Cot", + # window + "CumeDist", + "Degrees", + "DenseRank", + "Exp", + # datetime + "Extract", + "ExtractDay", + "ExtractHour", + "ExtractIsoWeekDay", + "ExtractIsoYear", + "ExtractMinute", + "ExtractMonth", + "ExtractQuarter", + "ExtractSecond", + "ExtractWeek", + "ExtractWeekDay", + "ExtractYear", + "FirstValue", + "Floor", + "Greatest", + # json + "JSONArray", + "JSONObject", + "LPad", + "LTrim", + "Lag", + "LastValue", + "Lead", + "Least", + "Left", + "Length", + "Ln", + "Log", + "Lower", + "Mod", + "Now", + "NthValue", + "Ntile", + "NullIf", + "Ord", + "PercentRank", + "Pi", + "Power", + "RPad", + "RTrim", + "Radians", + "Random", + "Rank", + "Repeat", + "Replace", + "Reverse", + "Right", + "Round", + "RowNumber", + "Sign", + "Sin", + "Sqrt", + "StrIndex", + "Substr", + "Tan", + "Trim", + "Trunc", + "TruncDate", + "TruncDay", + "TruncHour", + "TruncMinute", + "TruncMonth", + "TruncQuarter", + "TruncSecond", + "TruncTime", + "TruncWeek", + "TruncYear", + "Upper", +] diff --git a/django-stubs/db/models/functions/comparison.pyi b/django-stubs/db/models/functions/comparison.pyi index efd1e5340..0ec3aeacd 100644 --- a/django-stubs/db/models/functions/comparison.pyi +++ b/django-stubs/db/models/functions/comparison.pyi @@ -1,20 +1,36 @@ +import re from typing import Any +from django.db.backends.base.base import BaseDatabaseWrapper from django.db.models import Func +from django.db.models.expressions import Combinable from django.db.models.fields import Field +from django.db.models.sql.compiler import SQLCompiler, _AsSqlType +from typing_extensions import override class Cast(Func): - def __init__(self, expression: Any, output_field: str | Field[Any, Any]) -> None: ... + def __init__(self, expression: Combinable | str, output_field: str | Field[Any, Any]) -> None: ... + @override + def as_sql(self, compiler: SQLCompiler, connection: BaseDatabaseWrapper, **extra_context: Any) -> _AsSqlType: ... # type: ignore[override] + def as_mysql(self, compiler: SQLCompiler, connection: BaseDatabaseWrapper, **extra_context: Any) -> _AsSqlType: ... + def as_postgresql( + self, compiler: SQLCompiler, connection: BaseDatabaseWrapper, **extra_context: Any + ) -> _AsSqlType: ... + def as_oracle(self, compiler: SQLCompiler, connection: BaseDatabaseWrapper, **extra_context: Any) -> _AsSqlType: ... -class Coalesce(Func): ... +class Coalesce(Func): + @property + def empty_result_set_value(self) -> Any: ... + def as_oracle(self, compiler: SQLCompiler, connection: BaseDatabaseWrapper, **extra_context: Any) -> _AsSqlType: ... class Collate(Func): - def __init__(self, expression: Any, collation: str) -> None: ... + collation_re: re.Pattern[str] + def __init__(self, expression: Combinable | str, collation: str) -> None: ... + @override + def as_sql(self, compiler: SQLCompiler, connection: BaseDatabaseWrapper, **extra_context: Any) -> _AsSqlType: ... # type: ignore[override] class Greatest(Func): ... - -class JSONObject(Func): - def __init__(self, **fields: Any) -> None: ... - class Least(Func): ... -class NullIf(Func): ... + +class NullIf(Func): + def as_oracle(self, compiler: SQLCompiler, connection: BaseDatabaseWrapper, **extra_context: Any) -> _AsSqlType: ... diff --git a/django-stubs/db/models/functions/datetime.pyi b/django-stubs/db/models/functions/datetime.pyi index dedeb12b1..527169926 100644 --- a/django-stubs/db/models/functions/datetime.pyi +++ b/django-stubs/db/models/functions/datetime.pyi @@ -1,32 +1,83 @@ -from typing import Any +import datetime +from typing import Any, ClassVar +from django.db import models +from django.db.backends.base.base import BaseDatabaseWrapper from django.db.models import Func, Transform +from django.db.models.expressions import Combinable +from django.db.models.fields import Field +from django.db.models.sql.compiler import SQLCompiler, _AsSqlType +from typing_extensions import override class TimezoneMixin: - tzinfo: Any = ... + tzinfo: Any def get_tzname(self) -> str | None: ... -class Extract(TimezoneMixin, Transform): ... +class Extract(TimezoneMixin, Transform): + lookup_name: str | None # type: ignore[assignment] + output_field: ClassVar[models.IntegerField[Any]] + def __init__( + self, expression: Combinable | str, lookup_name: str | None = None, tzinfo: Any | None = None, **extra: Any + ) -> None: ... + @override + def as_sql(self, compiler: SQLCompiler, connection: BaseDatabaseWrapper) -> _AsSqlType: ... # type: ignore[override] + class ExtractYear(Extract): ... class ExtractIsoYear(Extract): ... class ExtractMonth(Extract): ... class ExtractDay(Extract): ... class ExtractWeek(Extract): ... class ExtractWeekDay(Extract): ... +class ExtractIsoWeekDay(Extract): ... class ExtractQuarter(Extract): ... class ExtractHour(Extract): ... class ExtractMinute(Extract): ... class ExtractSecond(Extract): ... -class Now(Func): ... -class TruncBase(TimezoneMixin, Transform): ... -class Trunc(TruncBase): ... + +class Now(Func): + output_field: ClassVar[models.DateTimeField[Any]] + def as_postgresql( + self, compiler: SQLCompiler, connection: BaseDatabaseWrapper, **extra_context: Any + ) -> _AsSqlType: ... + def as_mysql(self, compiler: SQLCompiler, connection: BaseDatabaseWrapper, **extra_context: Any) -> _AsSqlType: ... + def as_oracle(self, compiler: SQLCompiler, connection: BaseDatabaseWrapper, **extra_context: Any) -> _AsSqlType: ... + +class TruncBase(TimezoneMixin, Transform): + kind: str | None + tzinfo: Any + + def __init__( + self, + expression: Combinable | str, + output_field: Field[Any, Any] | None = None, + tzinfo: datetime.tzinfo | None = None, + **extra: Any, + ) -> None: ... + @override + def as_sql(self, compiler: SQLCompiler, connection: BaseDatabaseWrapper) -> _AsSqlType: ... # type: ignore[override] + +class Trunc(TruncBase): + def __init__( + self, + expression: Combinable | str, + kind: str, + output_field: Field[Any, Any] | None = None, + tzinfo: datetime.tzinfo | None = None, + **extra: Any, + ) -> None: ... + class TruncYear(TruncBase): ... class TruncQuarter(TruncBase): ... class TruncMonth(TruncBase): ... class TruncWeek(TruncBase): ... class TruncDay(TruncBase): ... -class TruncDate(TruncBase): ... -class TruncTime(TruncBase): ... + +class TruncDate(TruncBase): + output_field: ClassVar[models.DateField[Any]] + +class TruncTime(TruncBase): + output_field: ClassVar[models.TimeField[Any]] + class TruncHour(TruncBase): ... class TruncMinute(TruncBase): ... class TruncSecond(TruncBase): ... diff --git a/django-stubs/db/models/functions/json.pyi b/django-stubs/db/models/functions/json.pyi new file mode 100644 index 000000000..21464f8d0 --- /dev/null +++ b/django-stubs/db/models/functions/json.pyi @@ -0,0 +1,34 @@ +from collections.abc import Sequence +from typing import Any, ClassVar + +from django.db.backends.base.base import BaseDatabaseWrapper +from django.db.models.expressions import Func +from django.db.models.fields.json import JSONField +from django.db.models.sql.compiler import SQLCompiler, _AsSqlType +from typing_extensions import override + +class JSONArray(Func): + output_field: ClassVar[JSONField[Any]] + @override + def as_sql(self, compiler: SQLCompiler, connection: BaseDatabaseWrapper, **extra_context: Any) -> _AsSqlType: ... # type: ignore [override] + def as_native( + self, compiler: SQLCompiler, connection: BaseDatabaseWrapper, *, returning: str, **extra_context: Any + ) -> _AsSqlType: ... + def as_postgresql( + self, compiler: SQLCompiler, connection: BaseDatabaseWrapper, **extra_context: Any + ) -> _AsSqlType: ... + def as_oracle(self, compiler: SQLCompiler, connection: BaseDatabaseWrapper, **extra_context: Any) -> _AsSqlType: ... + +class JSONObject(Func): + output_field: ClassVar[JSONField[Any]] + def __init__(self, **fields: Any) -> None: ... + @override + def as_sql(self, compiler: SQLCompiler, connection: BaseDatabaseWrapper, **extra_context: Any) -> _AsSqlType: ... # type: ignore [override] + def as_native( + self, compiler: SQLCompiler, connection: BaseDatabaseWrapper, *, returning: str, **extra_context: Any + ) -> _AsSqlType: ... + def as_postgresql( + self, compiler: SQLCompiler, connection: BaseDatabaseWrapper, **extra_context: Any + ) -> _AsSqlType: ... + def as_oracle(self, compiler: SQLCompiler, connection: BaseDatabaseWrapper, **extra_context: Any) -> _AsSqlType: ... + def join(self, args: Sequence[Any]) -> str: ... diff --git a/django-stubs/db/models/functions/math.pyi b/django-stubs/db/models/functions/math.pyi index 36adeb0d4..63e210ad3 100644 --- a/django-stubs/db/models/functions/math.pyi +++ b/django-stubs/db/models/functions/math.pyi @@ -1,25 +1,49 @@ -from django.db.models.expressions import Func +from typing import Any + +from django.db.backends.base.base import BaseDatabaseWrapper +from django.db.models.expressions import Combinable, Func from django.db.models.functions.mixins import FixDecimalInputMixin, NumericOutputFieldMixin from django.db.models.lookups import Transform +from django.db.models.sql.compiler import SQLCompiler, _AsSqlType class Abs(Transform): ... class ACos(NumericOutputFieldMixin, Transform): ... class ASin(NumericOutputFieldMixin, Transform): ... class ATan(NumericOutputFieldMixin, Transform): ... class ATan2(NumericOutputFieldMixin, Func): ... -class Ceil(Transform): ... + +class Ceil(Transform): + def as_oracle(self, compiler: SQLCompiler, connection: BaseDatabaseWrapper, **extra_context: Any) -> _AsSqlType: ... + class Cos(NumericOutputFieldMixin, Transform): ... -class Cot(NumericOutputFieldMixin, Transform): ... -class Degrees(NumericOutputFieldMixin, Transform): ... + +class Cot(NumericOutputFieldMixin, Transform): + def as_oracle(self, compiler: SQLCompiler, connection: BaseDatabaseWrapper, **extra_context: Any) -> _AsSqlType: ... + +class Degrees(NumericOutputFieldMixin, Transform): + def as_oracle(self, compiler: SQLCompiler, connection: BaseDatabaseWrapper, **extra_context: Any) -> _AsSqlType: ... + class Exp(NumericOutputFieldMixin, Transform): ... class Floor(Transform): ... class Ln(NumericOutputFieldMixin, Transform): ... class Log(FixDecimalInputMixin, NumericOutputFieldMixin, Func): ... class Mod(FixDecimalInputMixin, NumericOutputFieldMixin, Func): ... -class Pi(NumericOutputFieldMixin, Func): ... + +class Pi(NumericOutputFieldMixin, Func): + def as_oracle(self, compiler: SQLCompiler, connection: BaseDatabaseWrapper, **extra_context: Any) -> _AsSqlType: ... + class Power(NumericOutputFieldMixin, Func): ... -class Radians(NumericOutputFieldMixin, Transform): ... -class Round(Transform): ... + +class Radians(NumericOutputFieldMixin, Transform): + def as_oracle(self, compiler: SQLCompiler, connection: BaseDatabaseWrapper, **extra_context: Any) -> _AsSqlType: ... + +class Random(NumericOutputFieldMixin, Func): + def as_mysql(self, compiler: SQLCompiler, connection: BaseDatabaseWrapper, **extra_context: Any) -> _AsSqlType: ... + def as_oracle(self, compiler: SQLCompiler, connection: BaseDatabaseWrapper, **extra_context: Any) -> _AsSqlType: ... + +class Round(FixDecimalInputMixin, Transform): + def __init__(self, expression: Combinable | str, precision: int = 0, **extra: Any) -> None: ... + class Sin(NumericOutputFieldMixin, Transform): ... class Sqrt(NumericOutputFieldMixin, Transform): ... class Tan(NumericOutputFieldMixin, Transform): ... diff --git a/django-stubs/db/models/functions/text.pyi b/django-stubs/db/models/functions/text.pyi index f812b256b..56bdb461e 100644 --- a/django-stubs/db/models/functions/text.pyi +++ b/django-stubs/db/models/functions/text.pyi @@ -1,58 +1,117 @@ -from typing import Any +from typing import Any, ClassVar -from django.db.backends.sqlite3.base import DatabaseWrapper +from django.db import models +from django.db.backends.base.base import BaseDatabaseWrapper from django.db.models import Func, Transform -from django.db.models.expressions import Combinable, Expression, Value -from django.db.models.sql.compiler import SQLCompiler +from django.db.models.expressions import Combinable, Expression, Value, _OutputField +from django.db.models.sql.compiler import SQLCompiler, _AsSqlType +from typing_extensions import override -class BytesToCharFieldConversionMixin: ... -class Chr(Transform): ... +class MySQLSHA2Mixin: + def as_mysql(self, compiler: SQLCompiler, connection: BaseDatabaseWrapper, **extra_context: Any) -> _AsSqlType: ... + +class OracleHashMixin: + def as_oracle(self, compiler: SQLCompiler, connection: BaseDatabaseWrapper, **extra_context: Any) -> _AsSqlType: ... + +class PostgreSQLSHAMixin: + def as_postgresql( + self, compiler: SQLCompiler, connection: BaseDatabaseWrapper, **extra_context: Any + ) -> _AsSqlType: ... + +class Chr(Transform): + def as_mysql(self, compiler: SQLCompiler, connection: BaseDatabaseWrapper, **extra_context: Any) -> _AsSqlType: ... + def as_oracle(self, compiler: SQLCompiler, connection: BaseDatabaseWrapper, **extra_context: Any) -> _AsSqlType: ... class ConcatPair(Func): + def pipes_concat_sql( + self, compiler: SQLCompiler, connection: BaseDatabaseWrapper, **extra_context: Any + ) -> _AsSqlType: ... + def as_sqlite(self, compiler: SQLCompiler, connection: BaseDatabaseWrapper, **extra_context: Any) -> _AsSqlType: ... # type: ignore[override] + def as_postgresql( + self, compiler: SQLCompiler, connection: BaseDatabaseWrapper, **extra_context: Any + ) -> _AsSqlType: ... + def as_mysql(self, compiler: SQLCompiler, connection: BaseDatabaseWrapper, **extra_context: Any) -> _AsSqlType: ... def coalesce(self) -> ConcatPair: ... -class Concat(Func): ... +class Concat(Func): + def __init__(self, *expressions: Any, **extra: Any) -> None: ... class Left(Func): - def __init__(self, expression: str, length: Value | int, **extra: Any) -> None: ... + output_field: ClassVar[models.CharField[Any]] + def __init__( + self, + expression: Combinable | str, + length: Expression | int, + *, + output_field: _OutputField | None = None, + **extra: Any, + ) -> None: ... def get_substr(self) -> Substr: ... - def use_substr( - self, compiler: SQLCompiler, connection: DatabaseWrapper, **extra_context: Any - ) -> tuple[str, list[int]]: ... + def as_oracle(self, compiler: SQLCompiler, connection: BaseDatabaseWrapper, **extra_context: Any) -> _AsSqlType: ... + +class Length(Transform): + output_field: ClassVar[models.IntegerField[Any]] + def as_mysql(self, compiler: SQLCompiler, connection: BaseDatabaseWrapper, **extra_context: Any) -> _AsSqlType: ... -class Length(Transform): ... class Lower(Transform): ... -class LPad(BytesToCharFieldConversionMixin, Func): - def __init__(self, expression: str, length: Length | int | None, fill_text: Value = ..., **extra: Any) -> None: ... +class LPad(Func): + output_field: ClassVar[models.CharField[Any]] + def __init__( + self, expression: Combinable | str, length: Expression | int | None, fill_text: Expression = ..., **extra: Any + ) -> None: ... class LTrim(Transform): ... -class Ord(Transform): ... +class MD5(OracleHashMixin, Transform): ... + +class Ord(Transform): + output_field: ClassVar[models.IntegerField[Any]] + def as_mysql(self, compiler: SQLCompiler, connection: BaseDatabaseWrapper, **extra_context: Any) -> _AsSqlType: ... -class Repeat(BytesToCharFieldConversionMixin, Func): - def __init__(self, expression: Value | str, number: Length | int | None, **extra: Any) -> None: ... +class Repeat(Func): + output_field: ClassVar[models.CharField[Any]] + def __init__(self, expression: Combinable | str, number: Expression | int | None, **extra: Any) -> None: ... + def as_oracle(self, compiler: SQLCompiler, connection: BaseDatabaseWrapper, **extra_context: Any) -> _AsSqlType: ... class Replace(Func): - def __init__(self, expression: Combinable, text: Value, replacement: Value = ..., **extra: Any) -> None: ... + def __init__(self, expression: Combinable | str, text: Value, replacement: Value = ..., **extra: Any) -> None: ... + +class Reverse(Transform): + def as_oracle(self, compiler: SQLCompiler, connection: BaseDatabaseWrapper, **extra_context: Any) -> _AsSqlType: ... + +class Right(Left): + @override + def get_substr(self) -> Substr: ... -class Right(Left): ... class RPad(LPad): ... class RTrim(Transform): ... -class StrIndex(Func): ... +class SHA1(OracleHashMixin, PostgreSQLSHAMixin, Transform): ... + +class SHA224(MySQLSHA2Mixin, PostgreSQLSHAMixin, Transform): + def as_oracle(self, compiler: SQLCompiler, connection: BaseDatabaseWrapper, **extra_context: Any) -> _AsSqlType: ... + +class SHA256(MySQLSHA2Mixin, OracleHashMixin, PostgreSQLSHAMixin, Transform): ... +class SHA384(MySQLSHA2Mixin, OracleHashMixin, PostgreSQLSHAMixin, Transform): ... +class SHA512(MySQLSHA2Mixin, OracleHashMixin, PostgreSQLSHAMixin, Transform): ... + +class StrIndex(Func): + output_field: ClassVar[models.IntegerField[Any]] + def as_postgresql( + self, compiler: SQLCompiler, connection: BaseDatabaseWrapper, **extra_context: Any + ) -> _AsSqlType: ... class Substr(Func): + output_field: ClassVar[models.CharField[Any]] def __init__( - self, expression: Expression | str, pos: Expression | int, length: Value | int | None = ..., **extra: Any + self, + expression: Combinable | str, + pos: Expression | int, + length: Expression | int | None = None, + *, + output_field: _OutputField | None = None, + **extra: Any, ) -> None: ... + def as_oracle(self, compiler: SQLCompiler, connection: BaseDatabaseWrapper, **extra_context: Any) -> _AsSqlType: ... class Trim(Transform): ... class Upper(Transform): ... -class Reverse(Transform): ... -class MySQLSHA2Mixin: ... -class OracleHashMixin: ... -class PostgreSQLSHAMixin: ... -class SHA1(OracleHashMixin, PostgreSQLSHAMixin, Transform): ... -class SHA224(MySQLSHA2Mixin, PostgreSQLSHAMixin, Transform): ... -class SHA256(MySQLSHA2Mixin, OracleHashMixin, PostgreSQLSHAMixin, Transform): ... -class SHA384(MySQLSHA2Mixin, OracleHashMixin, PostgreSQLSHAMixin, Transform): ... -class SHA512(MySQLSHA2Mixin, OracleHashMixin, PostgreSQLSHAMixin, Transform): ... diff --git a/django-stubs/db/models/sql/__init__.pyi b/django-stubs/db/models/sql/__init__.pyi index ee2ea4874..796a8991d 100644 --- a/django-stubs/db/models/sql/__init__.pyi +++ b/django-stubs/db/models/sql/__init__.pyi @@ -4,3 +4,8 @@ from .subqueries import AggregateQuery as AggregateQuery from .subqueries import DeleteQuery as DeleteQuery from .subqueries import InsertQuery as InsertQuery from .subqueries import UpdateQuery as UpdateQuery +from .where import AND as AND +from .where import OR as OR +from .where import XOR as XOR + +__all__ = ["AND", "OR", "XOR", "Query"] diff --git a/django-stubs/db/models/sql/compiler.pyi b/django-stubs/db/models/sql/compiler.pyi index d9acbc401..c0ba8e276 100644 --- a/django-stubs/db/models/sql/compiler.pyi +++ b/django-stubs/db/models/sql/compiler.pyi @@ -1,134 +1,187 @@ -from collections.abc import Callable, Iterator +from collections.abc import Callable, Iterable, Iterator, Sequence from datetime import date, datetime from decimal import Decimal -from itertools import chain -from typing import Any +from typing import Any, Literal, TypeAlias, overload from uuid import UUID +from django.db.backends.base.base import BaseDatabaseWrapper +from django.db.backends.utils import CursorWrapper +from django.db.models import Field from django.db.models.base import Model -from django.db.models.expressions import BaseExpression, Expression -from django.db.models.sql.query import Query, RawQuery +from django.db.models.expressions import BaseExpression, Expression, Ref +from django.db.models.sql.query import Query +from django.db.models.sql.subqueries import AggregateQuery, DeleteQuery, InsertQuery, UpdateQuery +from django.utils.functional import cached_property +from typing_extensions import override -FORCE: Any +_ParamT: TypeAlias = str | int +_ParamsT: TypeAlias = list[_ParamT] | tuple[_ParamT, ...] | tuple[()] +_AsSqlType: TypeAlias = tuple[str, _ParamsT] + +class PositionRef(Ref): + def __init__(self, ordinal: str, refs: str, source: Expression) -> None: ... class SQLCompiler: - query: Any = ... - connection: Any = ... - using: Any = ... - quote_cache: Any = ... - select: Any = ... - annotation_col_map: Any = ... - klass_info: Any = ... - ordering_parts: Any = ... - def __init__(self, query: Query | RawQuery, connection: Any, using: str | None) -> None: ... - col_count: Any = ... - def setup_query(self) -> None: ... - has_extra_select: Any = ... + query: Any + connection: BaseDatabaseWrapper + using: str | None + quote_cache: Any + select: Any + annotation_col_map: Any + klass_info: Any + ordering_parts: Any + def __init__( + self, query: Query, connection: BaseDatabaseWrapper, using: str | None, elide_empty: bool = True + ) -> None: ... + col_count: Any + def setup_query(self, with_col_aliases: bool = False) -> None: ... + has_extra_select: Any def pre_sql_setup( self, + with_col_aliases: bool = False, ) -> tuple[ - list[tuple[Expression, tuple[str, list[Any] | tuple[str, str]], None]], - list[tuple[Expression, tuple[str, list[int | str], bool]]], - list[tuple[str, list[float]]], + list[tuple[Expression, _AsSqlType, None]], + list[tuple[Expression, tuple[str, _ParamsT, bool]]], + list[_AsSqlType], ]: ... def get_group_by( self, - select: list[tuple[BaseExpression, tuple[str, list[float]], str | None]], - order_by: list[tuple[Expression, tuple[str, list[int | str], bool]]], - ) -> list[tuple[str, list[float]]]: ... + select: list[tuple[BaseExpression, _AsSqlType, str | None]], + order_by: list[tuple[Expression, tuple[str, _ParamsT, bool]]], + ) -> list[_AsSqlType]: ... def collapse_group_by( - self, - expressions: list[Expression], - having: list[Expression] | tuple[Any, ...], + self, expressions: list[Expression], having: list[Expression] | tuple[Expression, ...] ) -> list[Expression]: ... def get_select( self, - ) -> tuple[ - list[tuple[Expression, tuple[str, list[int | str]], str | None]], - dict[str, Any] | None, - dict[str, int], - ]: ... - def get_order_by(self) -> list[tuple[Expression, tuple[str, list[Any], bool]]]: ... + with_col_aliases: bool = False, + ) -> tuple[list[tuple[Expression, _AsSqlType, str | None]], dict[str, Any] | None, dict[str, int]]: ... + def _order_by_pairs(self) -> None: ... + def get_order_by(self) -> list[tuple[Expression, tuple[str, _ParamsT, bool]]]: ... def get_extra_select( self, - order_by: list[tuple[Expression, tuple[str, list[Any], bool]]], - select: list[tuple[Expression, tuple[str, list[float]], str | None]], - ) -> list[tuple[Expression, tuple[str, list[Any]], None]]: ... + order_by: list[tuple[Expression, tuple[str, _ParamsT, bool]]], + select: list[tuple[Expression, _AsSqlType, str | None]], + ) -> list[tuple[Expression, _AsSqlType, None]]: ... def quote_name_unless_alias(self, name: str) -> str: ... - def compile(self, node: Any, select_format: Any = ...) -> tuple[str, list[int | None] | tuple[int, int]]: ... + def compile(self, node: BaseExpression) -> _AsSqlType: ... def get_combinator_sql(self, combinator: str, all: bool) -> tuple[list[str], list[int] | list[str]]: ... - def as_sql(self, with_limits: bool = ..., with_col_aliases: bool = ...) -> Any: ... + def get_qualify_sql(self) -> tuple[list[str], list[Any]]: ... + def as_sql(self, with_limits: bool = True, with_col_aliases: bool = False) -> _AsSqlType: ... def get_default_columns( self, - start_alias: str | None = ..., - opts: Any | None = ..., - from_parent: type[Model] | None = ..., + select_mask: dict[str, Any], + start_alias: str | None = None, + opts: Any | None = None, + from_parent: type[Model] | None = None, ) -> list[Expression]: ... def get_distinct(self) -> tuple[list[Any], list[Any]]: ... def find_ordering_name( self, name: str, opts: Any, - alias: str | None = ..., - default_order: str = ..., - already_seen: (set[tuple[tuple[tuple[str, str]] | None, tuple[tuple[str, str]]]] | None) = ..., + alias: str | None = None, + default_order: str = "ASC", + already_seen: set[tuple[tuple[tuple[str, str]] | None, tuple[tuple[str, str]]]] | None = None, ) -> list[tuple[Expression, bool]]: ... - def get_from_clause(self) -> tuple[list[str], list[int | str]]: ... + def get_from_clause(self) -> tuple[list[str], _ParamsT]: ... def get_related_selections( self, select: list[tuple[Expression, str | None]], - opts: Any | None = ..., - root_alias: str | None = ..., - cur_depth: int = ..., - requested: dict[str, dict[str, dict[str, dict[Any, Any]]]] | bool | None = ..., - restricted: bool | None = ..., + select_mask: dict[str, Any], + opts: Any | None = None, + root_alias: str | None = None, + cur_depth: int = 1, + requested: dict[str, dict[str, dict[str, dict[Any, Any]]]] | None = None, + restricted: bool | None = None, ) -> list[dict[str, Any]]: ... - def get_select_for_update_of_arguments(self) -> Any: ... - def deferred_to_columns(self) -> dict[type[Model], set[str]]: ... + def get_select_for_update_of_arguments(self) -> list[Any]: ... def get_converters( self, expressions: list[Expression] ) -> dict[int, tuple[list[Callable[..., Any]], Expression]]: ... def apply_converters( - self, - rows: chain[Any], - converters: dict[int, tuple[list[Callable[..., Any]], Expression]], - ) -> Iterator[ - list[bytes | datetime | int | str | None] - | list[date | Decimal | float | str | None] - | list[datetime | float | str | UUID | None] - ]: ... + self, rows: Iterable[Iterable[Any]], converters: dict[int, tuple[list[Callable[..., Any]], Expression]] + ) -> Iterator[list[None | date | datetime | float | Decimal | UUID | bytes | str]]: ... + def has_composite_fields(self, expressions: Iterable[Expression]) -> bool: ... + def composite_fields_to_tuples( + self, rows: Iterable[Any], expressions: Iterable[Expression] + ) -> Iterator[list[tuple[Any, ...]]]: ... def results_iter( self, - results: Iterator[Any] | list[list[tuple[int | str]]] | None = ..., - tuple_expected: bool = ..., - chunked_fetch: bool = ..., - chunk_size: int = ..., - ) -> Iterator[Any]: ... + results: Iterable[list[Sequence[Any]]] | None = None, + tuple_expected: bool = False, + chunked_fetch: bool = False, + chunk_size: int = 100, + ) -> Iterator[Sequence[Any]]: ... def has_results(self) -> bool: ... - def execute_sql(self, result_type: str = ..., chunked_fetch: bool = ..., chunk_size: int = ...) -> Any | None: ... - def as_subquery_condition( - self, alias: str, columns: list[str], compiler: SQLCompiler - ) -> tuple[str, tuple[Any, ...]]: ... + @overload + def execute_sql( # pyright: ignore[reportOverlappingOverload] + self, result_type: Literal["cursor"] = "cursor", chunked_fetch: bool = False, chunk_size: int = 100 + ) -> CursorWrapper: ... + @overload + def execute_sql( + self, + result_type: Literal["no results"] | None = "no results", + chunked_fetch: bool = False, + chunk_size: int = 100, + ) -> None: ... + @overload + def execute_sql( + self, result_type: Literal["single"] = "single", chunked_fetch: bool = False, chunk_size: int = 100 + ) -> Iterable[Sequence[Any]] | None: ... + @overload + def execute_sql( + self, result_type: Literal["multi"] = "multi", chunked_fetch: bool = False, chunk_size: int = 100 + ) -> Iterable[list[Sequence[Any]]] | None: ... def explain_query(self) -> Iterator[str]: ... class SQLInsertCompiler(SQLCompiler): - returning_fields: Any = ... - returning_params: Any = ... - def field_as_sql(self, field: Any, val: Any) -> Any: ... + query: InsertQuery + returning_fields: Sequence[Any] | None + returning_params: Sequence[Any] + def field_as_sql( + self, + field: Field[Any, Any] | None, + get_placeholder: Callable[[Any, SQLInsertCompiler, BaseDatabaseWrapper], str], + val: Any, + ) -> _AsSqlType: ... def prepare_value(self, field: Any, value: Any) -> Any: ... def pre_save_val(self, field: Any, obj: Any) -> Any: ... - def assemble_as_sql(self, fields: Any, value_rows: Any) -> Any: ... - def as_sql(self) -> Any: ... # type: ignore [override] + def assemble_as_sql(self, fields: Any, value_rows: Any) -> tuple[list[list[str]], list[list[Any]]]: ... + @override + def as_sql(self) -> list[_AsSqlType]: ... # type: ignore[override] + @override + def execute_sql( # type: ignore[override] + self, returning_fields: Sequence[str] | None = None + ) -> list[tuple[Any]]: ... # 1-tuple class SQLDeleteCompiler(SQLCompiler): - def single_alias(self) -> Any: ... - def as_sql(self) -> Any: ... # type: ignore [override] + query: DeleteQuery + @cached_property + def single_alias(self) -> bool: ... + @cached_property + def contains_self_reference_subquery(self) -> bool: ... + @override + def as_sql(self) -> _AsSqlType: ... # type: ignore[override] class SQLUpdateCompiler(SQLCompiler): - def as_sql(self) -> Any: ... # type: ignore [override] + query: UpdateQuery + returning_fields: Sequence[Any] | None + returning_params: Sequence[Any] + @override + def as_sql(self) -> _AsSqlType: ... # type: ignore[override] + @override + def execute_sql(self, result_type: Literal["cursor", "no results"]) -> int: ... # type: ignore[override] + def execute_returning_sql(self, returning_fields: Sequence[Any] | None) -> list[Sequence[Any]]: ... + @override + def pre_sql_setup(self) -> None: ... # type: ignore[override] class SQLAggregateCompiler(SQLCompiler): - col_count: Any = ... - def as_sql(self) -> Any: ... # type: ignore [override] + query: AggregateQuery + col_count: int + @override + def as_sql(self) -> _AsSqlType: ... # type: ignore[override] -def cursor_iter(cursor: Any, sentinel: Any, col_count: int | None, itersize: int) -> Iterator[Any]: ... +def cursor_iter( + cursor: CursorWrapper, sentinel: Any, col_count: int | None, itersize: int +) -> Iterator[list[Sequence[Any]]]: ... diff --git a/django-stubs/db/models/sql/constants.pyi b/django-stubs/db/models/sql/constants.pyi index 00b9557b4..125314763 100644 --- a/django-stubs/db/models/sql/constants.pyi +++ b/django-stubs/db/models/sql/constants.pyi @@ -1,14 +1,14 @@ -from re import Pattern +from typing import Final, Literal -GET_ITERATOR_CHUNK_SIZE: int = ... +GET_ITERATOR_CHUNK_SIZE: Final[int] -MULTI: str = ... -SINGLE: str = ... -CURSOR: str = ... -NO_RESULTS: str = ... +MULTI: Literal["multi"] +SINGLE: Literal["single"] +NO_RESULTS: Literal["no results"] +CURSOR: Literal["cursor"] +ROW_COUNT: Literal["row count"] -ORDER_PATTERN: Pattern[str] = ... -ORDER_DIR: dict[str, tuple[str, str]] = ... +ORDER_DIR: dict[str, tuple[str, str]] -INNER: str = ... -LOUTER: str = ... +INNER: Literal["INNER JOIN"] +LOUTER: Literal["LEFT OUTER JOIN"] diff --git a/django-stubs/db/models/sql/datastructures.pyi b/django-stubs/db/models/sql/datastructures.pyi index 0606dd866..c63a60a10 100644 --- a/django-stubs/db/models/sql/datastructures.pyi +++ b/django-stubs/db/models/sql/datastructures.pyi @@ -1,26 +1,26 @@ -from collections import OrderedDict from typing import Any +from django.db.backends.base.base import BaseDatabaseWrapper from django.db.models.fields.mixins import FieldCacheMixin from django.db.models.query_utils import FilteredRelation, PathInfo -from django.db.models.sql.compiler import SQLCompiler +from django.db.models.sql.compiler import SQLCompiler, _AsSqlType class MultiJoin(Exception): - level: int = ... - names_with_path: list[tuple[str, list[PathInfo]]] = ... + level: int + names_with_path: list[tuple[str, list[PathInfo]]] def __init__(self, names_pos: int, path_with_names: list[tuple[str, list[PathInfo]]]) -> None: ... class Empty: ... class Join: - table_name: str = ... - parent_alias: str = ... - table_alias: str | None = ... - join_type: str = ... - join_cols: tuple[Any, ...] = ... - join_field: FieldCacheMixin = ... - nullable: bool = ... - filtered_relation: FilteredRelation | None = ... + table_name: str + parent_alias: str + table_alias: str | None + join_type: str + join_cols: tuple[Any, ...] + join_field: FieldCacheMixin + nullable: bool + filtered_relation: FilteredRelation | None def __init__( self, table_name: str, @@ -29,21 +29,23 @@ class Join: join_type: str, join_field: FieldCacheMixin, nullable: bool, - filtered_relation: FilteredRelation | None = ..., + filtered_relation: FilteredRelation | None = None, ) -> None: ... - def as_sql(self, compiler: SQLCompiler, connection: Any) -> tuple[str, list[int | str]]: ... - def relabeled_clone(self, change_map: dict[str, str] | OrderedDict[Any, Any]) -> Join: ... - def equals(self, other: BaseTable | Join, with_filtered_relation: bool) -> bool: ... + def as_sql(self, compiler: SQLCompiler, connection: BaseDatabaseWrapper) -> _AsSqlType: ... + def relabeled_clone(self, change_map: dict[str | None, str]) -> Join: ... + @property + def identity(self) -> tuple[type[Join], str, str, FieldCacheMixin, FilteredRelation | None]: ... def demote(self) -> Join: ... def promote(self) -> Join: ... class BaseTable: - join_type: Any = ... - parent_alias: Any = ... - filtered_relation: Any = ... - table_name: str = ... - table_alias: str | None = ... + join_type: Any + parent_alias: Any + filtered_relation: Any + table_name: str + table_alias: str | None def __init__(self, table_name: str, alias: str | None) -> None: ... - def as_sql(self, compiler: SQLCompiler, connection: Any) -> tuple[str, list[Any]]: ... - def relabeled_clone(self, change_map: OrderedDict[Any, Any]) -> BaseTable: ... - def equals(self, other: Join, with_filtered_relation: bool) -> bool: ... + def as_sql(self, compiler: SQLCompiler, connection: BaseDatabaseWrapper) -> _AsSqlType: ... + def relabeled_clone(self, change_map: dict[str | None, str]) -> BaseTable: ... + @property + def identity(self) -> tuple[type[BaseTable], str, str | None]: ... diff --git a/django-stubs/db/models/sql/query.pyi b/django-stubs/db/models/sql/query.pyi index 9de5243e8..e5c4471eb 100644 --- a/django-stubs/db/models/sql/query.pyi +++ b/django-stubs/db/models/sql/query.pyi @@ -1,174 +1,198 @@ -from collections import Counter, OrderedDict +import collections from collections.abc import Callable, Iterable, Iterator, Sequence -from typing import Any, NamedTuple +from typing import Any, Literal, NamedTuple -from django.db.models import Expression, Field, FilteredRelation, Model, Q, QuerySet -from django.db.models.expressions import Combinable +from django.db.backends.utils import CursorWrapper +from django.db.models import Field, FilteredRelation, Model, Q +from django.db.models.expressions import BaseExpression, Combinable, Expression from django.db.models.lookups import Lookup, Transform -from django.db.models.query_utils import PathInfo, RegisterLookupMixin -from django.db.models.sql.compiler import SQLCompiler -from django.db.models.sql.datastructures import BaseTable +from django.db.models.options import Options +from django.db.models.query import _OrderByFieldName +from django.db.models.query_utils import PathInfo +from django.db.models.sql.datastructures import BaseTable, Join from django.db.models.sql.where import WhereNode +from django.utils.functional import cached_property +from typing_extensions import override class JoinInfo(NamedTuple): - final_field: Any - targets: Any + final_field: Field[Any, Any] + targets: tuple[Any, ...] opts: Any - joins: Any - path: Any - transform_function: Any + joins: list[str] + path: list[Any] + transform_function: Callable[[Field[Any, Any], str], Expression] class RawQuery: high_mark: int | None low_mark: int | None - params: Any = ... - sql: str = ... - using: str = ... - extra_select: dict[Any, Any] = ... - annotation_select: dict[Any, Any] = ... - cursor: object = ... - def __init__(self, sql: str, using: str, params: Any = ...) -> None: ... + params: Any + sql: str + using: str + extra_select: dict[Any, Any] + annotation_select: dict[Any, Any] + cursor: CursorWrapper | None + def __init__(self, sql: str, using: str, params: Any = ()) -> None: ... def chain(self, using: str) -> RawQuery: ... def clone(self, using: str) -> RawQuery: ... def get_columns(self) -> list[str]: ... - def __iter__(self) -> Any: ... + def __iter__(self) -> Iterator[Any]: ... + @property + def params_type(self) -> type[dict[Any, Any] | tuple[Any, ...]] | None: ... -class Query: - base_table: str - related_ids: list[int] | None - related_updates: dict[type[Model], list[tuple[Field[Any, Any], None, int | str]]] - values: list[Any] - alias_prefix: str = ... - subq_aliases: frozenset[Any] = ... - compiler: str = ... - model: type[Model] | None = ... - alias_refcount: dict[str, int] = ... - alias_map: dict[str, BaseTable] = ... - external_aliases: set[str] = ... - table_map: dict[str, list[str]] = ... - default_cols: bool = ... - default_ordering: bool = ... - standard_ordering: bool = ... - used_aliases: set[str] = ... - filter_is_sticky: bool = ... - subquery: bool = ... - group_by: Sequence[Combinable] | Sequence[str] | bool | None = ... - order_by: tuple[Any, ...] = ... - distinct: bool = ... - distinct_fields: tuple[Any, ...] = ... - select_for_update: bool = ... - select_for_update_nowait: bool = ... - select_for_update_skip_locked: bool = ... - select_for_update_of: tuple[Any, ...] = ... - select_related: dict[str, Any] | bool = ... - max_depth: int = ... - values_select: tuple[Any, ...] = ... - annotation_select_mask: set[str] | None = ... - combinator: str | None = ... - combinator_all: bool = ... - combined_queries: tuple[Any, ...] = ... - extra_select_mask: set[str] | None = ... - extra_tables: tuple[Any, ...] = ... - extra_order_by: list[str] | tuple[Any, ...] = ... - deferred_loading: tuple[set[str] | frozenset[Any], bool] = ... - explain_query: bool = ... - explain_format: str | None = ... - explain_options: dict[str, int] = ... - high_mark: int | None = ... - low_mark: int = ... +class Query(BaseExpression): + alias_prefix: str + subq_aliases: frozenset[Any] + compiler: str + base_table_class: type[BaseTable] + model: type[Model] | None + alias_refcount: dict[str, int] + alias_map: dict[str, BaseTable | Join] + external_aliases: dict[str, bool] + table_map: dict[str, list[str]] + default_cols: bool + default_ordering: bool + standard_ordering: bool + used_aliases: set[str] where: WhereNode - def __init__(self, model: type[Model] | None, where: type[WhereNode] = ...) -> None: ... - @property - def extra(self) -> OrderedDict[Any, Any]: ... + filter_is_sticky: bool + subquery: bool + group_by: None | Sequence[Combinable] | Sequence[str] | Literal[True] + order_by: Sequence[_OrderByFieldName] + distinct: bool + distinct_fields: tuple[str, ...] + select: Sequence[BaseExpression] + select_for_update: bool + select_for_update_nowait: bool + select_for_update_skip_locked: bool + select_for_update_of: tuple[Any, ...] + select_for_no_key_update: bool + select_related: dict[str, Any] | bool + max_depth: int + join_class: type[Join] + values_select: tuple[Any, ...] + selected: dict[str, int | str | Expression] | None + annotation_select_mask: list[str] | None + combinator: str | None + combinator_all: bool + combined_queries: tuple[Any, ...] + extra_select_mask: set[str] | None + extra_tables: tuple[Any, ...] + extra_order_by: Sequence[_OrderByFieldName] + deferred_loading: tuple[set[str] | frozenset[str], bool] + high_mark: int | None + low_mark: int + extra: dict[str, Any] + annotations: dict[str, Expression] + empty_result_set_value: Any | None + explain_info: Any | None + def __init__(self, model: type[Model] | None, alias_cols: bool = True) -> None: ... @property - def annotations(self) -> OrderedDict[Any, Any]: ... + @override + def output_field(self) -> Field[Any, Any]: ... @property def has_select_fields(self) -> bool: ... + @cached_property + def base_table(self) -> str: ... + def add_annotation(self, annotation: Any, alias: str, select: bool = True) -> None: ... def sql_with_params(self) -> tuple[str, tuple[Any, ...]]: ... - def __deepcopy__(self, memo: dict[str, Any]) -> Query: ... - def get_compiler(self, using: str | None = ..., connection: Any = ...) -> SQLCompiler: ... + def __deepcopy__(self, memo: dict[int, Any]) -> Query: ... + def get_compiler( + self, using: str | None = None, connection: Any | None = None, elide_empty: bool = True + ) -> Any: ... + def join_parent_model(self, opts: Any, model: Any | None, alias: str, seen: dict[Any, str]) -> str: ... + def names_to_path( + self, names: Sequence[str], opts: Any, allow_many: bool = True, fail_on_missing: bool = False + ) -> tuple[list[Any], Any, tuple[Any, ...], Sequence[str]]: ... + def get_meta(self) -> Options[Any]: ... def clone(self) -> Query: ... - def chain(self, klass: type[Query] | None = ...) -> Query: ... - def relabeled_clone(self, change_map: dict[Any, Any] | OrderedDict[Any, Any]) -> Query: ... + def chain(self, klass: type[Query] | None = None) -> Query: ... def get_count(self, using: str) -> int: ... + @override + def get_group_by_cols(self, wrapper: Any | None = None) -> list[Any]: ... def has_filters(self) -> WhereNode: ... + def get_external_cols(self) -> list[Any]: ... + def exists(self, limit: bool = True) -> Any: ... def has_results(self, using: str) -> bool: ... - def explain(self, using: str, format: str | None = ..., **options: Any) -> str: ... + def explain(self, using: str, format: str | None = None, **options: Any) -> str: ... def combine(self, rhs: Query, connector: str) -> None: ... - def deferred_to_data(self, target: dict[Any, Any], callback: Callable[..., Any]) -> None: ... def ref_alias(self, alias: str) -> None: ... - def unref_alias(self, alias: str, amount: int = ...) -> None: ... - def promote_joins(self, aliases: set[str]) -> None: ... - def demote_joins(self, aliases: set[str]) -> None: ... + def unref_alias(self, alias: str, amount: int = 1) -> None: ... + def promote_joins(self, aliases: Iterable[str]) -> None: ... + def demote_joins(self, aliases: Iterable[str]) -> None: ... def reset_refcounts(self, to_counts: dict[str, int]) -> None: ... - def change_aliases(self, change_map: dict[Any, Any] | OrderedDict[Any, Any]) -> None: ... - def bump_prefix(self, outer_query: Query) -> None: ... + def check_alias(self, alias: str) -> None: ... + def check_related_objects(self, field: Any, value: Any, opts: Any) -> None: ... + def check_query_object_type(self, value: Any, opts: Any, field: Any) -> None: ... + def change_aliases(self, change_map: dict[str | None, str]) -> None: ... + def bump_prefix(self, other_query: Query, exclude: Any | None = None) -> None: ... def get_initial_alias(self) -> str: ... def count_active_tables(self) -> int: ... - def resolve_expression(self, query: Query, *args: Any, **kwargs: Any) -> Query: ... - def as_sql(self, compiler: SQLCompiler, connection: Any) -> Any: ... - def resolve_lookup_value(self, value: Any, can_reuse: set[str] | None, allow_joins: bool) -> Any: ... - def solve_lookup_type(self, lookup: str) -> tuple[Sequence[str], Sequence[str], bool]: ... + @override + def resolve_expression(self, query: Query, *args: Any, **kwargs: Any) -> Query: ... # type: ignore[override] + def resolve_lookup_value( + self, value: Any, can_reuse: set[str] | None, allow_joins: bool, summarize: bool = False + ) -> Any: ... + def solve_lookup_type( + self, lookup: str, summarize: bool = False + ) -> tuple[Sequence[str], Sequence[str], Expression | Literal[False]]: ... + def table_alias( + self, table_name: str, create: bool = False, filtered_relation: Any | None = None + ) -> tuple[str, bool]: ... + def get_aggregation(self, using: Any, aggregate_exprs: dict[str, Any]) -> dict[str, Any]: ... def build_filter( self, - filter_expr: dict[str, str] | tuple[str, tuple[int, int]], - branch_negated: bool = ..., - current_negated: bool = ..., - can_reuse: set[str] | None = ..., - allow_joins: bool = ..., - split_subq: bool = ..., - reuse_with_filtered_relation: bool = ..., - ) -> tuple[WhereNode, list[Any]]: ... - def add_filter(self, filter_clause: tuple[str, list[int] | list[str]]) -> None: ... - def add_q(self, q_object: Q) -> None: ... - def build_where(self, q_object: Q) -> Any: ... - def build_filtered_relation_q( - self, - q_object: Q, - reuse: set[str], - branch_negated: bool = ..., - current_negated: bool = ..., - ) -> WhereNode: ... + filter_expr: Q | Expression | dict[str, str] | tuple[str, Any], + branch_negated: bool = False, + current_negated: bool = False, + can_reuse: set[str] | None = None, + allow_joins: bool = True, + split_subq: bool = True, + check_filterable: bool = True, + summarize: bool = False, + update_join_types: bool = True, + ) -> tuple[WhereNode, Iterable[str]]: ... + def add_select_col(self, col: Any, name: str) -> None: ... + def add_filter(self, filter_lhs: tuple[str, Any], filter_rhs: tuple[str, Any]) -> None: ... + def add_q(self, q_object: Q, reuse_all: bool = False) -> None: ... + def build_where(self, filter_expr: Q | Expression | dict[str, str] | tuple[str, Any]) -> WhereNode: ... def add_filtered_relation(self, filtered_relation: FilteredRelation, alias: str) -> None: ... def setup_joins( self, - names: list[str], + names: Sequence[str], opts: Any, alias: str, - can_reuse: set[str] | None = ..., - allow_many: bool = ..., - reuse_with_filtered_relation: bool = ..., + can_reuse: set[str] | None = None, + allow_many: bool = True, ) -> JoinInfo: ... def trim_joins( - self, targets: tuple[Field[Any, Any]], joins: list[str], path: list[PathInfo] - ) -> tuple[tuple[Field[Any, Any]], str, list[str]]: ... + self, targets: tuple[Field[Any, Any], ...], joins: list[str], path: list[PathInfo] + ) -> tuple[tuple[Field[Any, Any], ...], str, list[str]]: ... def resolve_ref( - self, - name: str, - allow_joins: bool = ..., - reuse: set[str] | None = ..., - summarize: bool = ..., + self, name: str, allow_joins: bool = True, reuse: set[str] | None = None, summarize: bool = False ) -> Expression: ... def split_exclude( self, - filter_expr: tuple[str, QuerySet[Any] | int], + filter_expr: tuple[str, Any], can_reuse: set[str], names_with_path: list[tuple[str, list[PathInfo]]], - ) -> tuple[WhereNode, tuple[Any, ...]]: ... + ) -> tuple[WhereNode, Iterable[str]]: ... def set_empty(self) -> None: ... def is_empty(self) -> bool: ... - def set_limits(self, low: int | None = ..., high: int | None = ...) -> None: ... + def set_limits(self, low: int | None = None, high: int | None = None) -> None: ... def clear_limits(self) -> None: ... + @property + def is_sliced(self) -> bool: ... def has_limit_one(self) -> bool: ... def can_filter(self) -> bool: ... def clear_select_clause(self) -> None: ... def clear_select_fields(self) -> None: ... def set_select(self, cols: list[Expression]) -> None: ... - def add_distinct_fields(self, *field_names: Any) -> None: ... - def add_fields(self, field_names: Iterator[Any] | list[str], allow_m2m: bool = ...) -> None: ... - def add_ordering(self, *ordering: Any) -> None: ... - def clear_ordering(self, force_empty: bool) -> None: ... - def set_group_by(self) -> None: ... + def add_distinct_fields(self, *field_names: str) -> None: ... + def add_fields(self, field_names: Iterable[str], allow_m2m: bool = True) -> None: ... + def add_ordering(self, *ordering: _OrderByFieldName) -> None: ... + def clear_where(self) -> None: ... + def clear_ordering(self, force: bool = False, clear_default: bool = True) -> None: ... + def set_group_by(self, allow_aliases: bool = True) -> None: ... def add_select_related(self, fields: Iterable[str]) -> None: ... def add_extra( self, @@ -177,38 +201,39 @@ class Query: where: Sequence[str] | None, params: Sequence[str] | None, tables: Sequence[str] | None, - order_by: Sequence[str] | None, + order_by: Sequence[_OrderByFieldName] | None, ) -> None: ... def clear_deferred_loading(self) -> None: ... def add_deferred_loading(self, field_names: Iterable[str]) -> None: ... def add_immediate_loading(self, field_names: Iterable[str]) -> None: ... - def get_loaded_field_names(self) -> dict[type[Model], set[str]]: ... - def get_loaded_field_names_cb( - self, - target: dict[type[Model], set[str]], - model: type[Model], - fields: set[Field[Any, Any]], - ) -> None: ... - def set_annotation_mask(self, names: list[str] | set[str] | tuple[Any, ...] | None) -> None: ... - def append_annotation_mask(self, names: list[str]) -> None: ... - def set_extra_mask(self, names: list[str] | tuple[Any, ...]) -> None: ... - def set_values(self, fields: list[str] | tuple[Any, ...]) -> None: ... + def get_select_mask(self) -> dict[str, Any]: ... + def set_annotation_mask(self, names: Iterable[str] | None) -> None: ... + def append_annotation_mask(self, names: Iterable[str]) -> None: ... + def set_extra_mask(self, names: Iterable[str] | None) -> None: ... + def set_values(self, fields: Iterable[str] | None) -> None: ... + @property + def annotation_select(self) -> dict[str, Any]: ... + @property + def extra_select(self) -> dict[str, Any]: ... def trim_start(self, names_with_path: list[tuple[str, list[PathInfo]]]) -> tuple[str, bool]: ... def is_nullable(self, field: Field[Any, Any]) -> bool: ... - def build_lookup( + def check_filterable(self, expression: Any) -> None: ... + def build_lookup(self, lookups: Sequence[str], lhs: Expression | Query, rhs: Any) -> Lookup[Any]: ... + def try_transform(self, lhs: Expression | Query, name: str, lookups: Sequence[str] | None = ...) -> Transform: ... + def join( self, - lookups: Sequence[str], - lhs: RegisterLookupMixin | Query, - rhs: Query | None, - ) -> Lookup[Any]: ... - def try_transform(self, lhs: RegisterLookupMixin | Query, name: str) -> Transform: ... + join: BaseTable | Join, + reuse: str | None = None, + ) -> str: ... class JoinPromoter: - connector: str = ... - negated: bool = ... - effective_connector: str = ... - num_children: int = ... - votes: Counter[Any] = ... + connector: str + negated: bool + effective_connector: str + num_children: int + votes: collections.Counter[Any] def __init__(self, connector: str, num_children: int, negated: bool) -> None: ... - def add_votes(self, votes: Iterator[Any] | list[Any] | set[str] | tuple[Any, ...]) -> None: ... + def add_votes(self, votes: Iterable[str]) -> None: ... def update_join_types(self, query: Query) -> set[str]: ... + +__all__ = ["Query", "RawQuery"] diff --git a/django-stubs/db/models/sql/subqueries.pyi b/django-stubs/db/models/sql/subqueries.pyi index 50c9136b6..4fa6b2093 100644 --- a/django-stubs/db/models/sql/subqueries.pyi +++ b/django-stubs/db/models/sql/subqueries.pyi @@ -4,23 +4,15 @@ from typing import Any from django.db.models.base import Model from django.db.models.expressions import Case from django.db.models.fields import Field -from django.db.models.query import QuerySet from django.db.models.sql.query import Query from django.db.models.sql.where import WhereNode class DeleteQuery(Query): - select: tuple[Any, ...] - where_class: type[WhereNode] - where: WhereNode = ... def do_query(self, table: str, where: WhereNode, using: str) -> int: ... def delete_batch(self, pk_list: list[int] | list[str], using: str) -> int: ... - def delete_qs(self, query: QuerySet[Any], using: str) -> int: ... class UpdateQuery(Query): - select: tuple[Any, ...] - where_class: type[WhereNode] def __init__(self, *args: Any, **kwargs: Any) -> None: ... - where: WhereNode = ... def update_batch(self, pk_list: list[int], values: dict[str, int | None], using: str) -> None: ... def add_update_values(self, values: dict[str, Any]) -> None: ... def add_update_fields(self, values_seq: list[tuple[Field[Any, Any], type[Model] | None, Case]]) -> None: ... @@ -28,18 +20,21 @@ class UpdateQuery(Query): def get_related_updates(self) -> list[UpdateQuery]: ... class InsertQuery(Query): - select: tuple[Any, ...] - where: WhereNode - where_class: type[WhereNode] - fields: Iterable[Field[Any, Any]] = ... - objs: list[Model] = ... - raw: bool = ... - def __init__(self, *args: Any, **kwargs: Any) -> None: ... - def insert_values(self, fields: Iterable[Field[Any, Any]], objs: list[Model], raw: bool = ...) -> None: ... + fields: Iterable[Field[Any, Any]] + objs: list[Model] + raw: bool + def __init__( + self, + *args: Any, + on_conflict: Any | None = ..., + update_fields: Any | None = ..., + unique_fields: Any | None = ..., + **kwargs: Any, + ) -> None: ... + def insert_values(self, fields: Iterable[Field[Any, Any]], objs: list[Model], raw: bool = False) -> None: ... class AggregateQuery(Query): - select: tuple[Any, ...] - sub_params: tuple[Any, ...] - where: WhereNode - where_class: type[WhereNode] - def add_subquery(self, query: Query, using: str) -> None: ... + inner_query: Query + def __init__(self, model: type[Model], inner_query: Query) -> None: ... + +__all__ = ["AggregateQuery", "DeleteQuery", "InsertQuery", "UpdateQuery"] diff --git a/django-stubs/db/models/sql/where.pyi b/django-stubs/db/models/sql/where.pyi index 129435654..4dc7788b8 100644 --- a/django-stubs/db/models/sql/where.pyi +++ b/django-stubs/db/models/sql/where.pyi @@ -1,46 +1,60 @@ -from collections import OrderedDict -from typing import Any +from collections.abc import Iterator, Sequence +from typing import Any, Final -import django.utils.tree as tree +from django.db.backends.base.base import BaseDatabaseWrapper from django.db.models.expressions import Expression -from django.db.models.sql.compiler import SQLCompiler -from django.db.models.sql.query import Query +from django.db.models.fields import BooleanField +from django.db.models.lookups import Lookup +from django.db.models.sql.compiler import SQLCompiler, _AsSqlType, _ParamsT +from django.utils import tree +from django.utils.functional import cached_property -AND: str -OR: str +AND: Final = "AND" +OR: Final = "OR" +XOR: Final = "XOR" class WhereNode(tree.Node): - connector: str - contains_aggregate: bool - contains_over_clause: bool - negated: bool - default: Any = ... - resolved: bool = ... - conditional: bool = ... - def split_having(self, negated: bool = ...) -> tuple[WhereNode | None, WhereNode | None]: ... - def as_sql(self, compiler: SQLCompiler, connection: Any) -> Any: ... + resolved: bool + conditional: bool + def split_having_qualify( + self, negated: bool = ..., must_group_by: bool = ... + ) -> tuple[WhereNode | None, WhereNode | None, WhereNode | None]: ... + def as_sql(self, compiler: SQLCompiler, connection: BaseDatabaseWrapper) -> _AsSqlType: ... def get_group_by_cols(self) -> list[Expression]: ... - def relabel_aliases(self, change_map: dict[str | None, str] | OrderedDict[Any, Any]) -> None: ... + def get_source_expressions(self) -> list[Any]: ... + def set_source_expressions(self, children: list[Any]) -> None: ... + def relabel_aliases(self, change_map: dict[str | None, str]) -> None: ... def clone(self) -> WhereNode: ... - def relabeled_clone(self, change_map: dict[str | None, str] | OrderedDict[Any, Any]) -> WhereNode: ... + def relabeled_clone(self, change_map: dict[str | None, str]) -> WhereNode: ... + def replace_expressions(self, replacements: dict[Any, Any]) -> WhereNode: ... + def get_refs(self) -> set[str]: ... + @cached_property + def contains_aggregate(self) -> bool: ... + @cached_property + def contains_over_clause(self) -> bool: ... + @property + def is_summary(self) -> bool: ... def resolve_expression(self, *args: Any, **kwargs: Any) -> WhereNode: ... + @cached_property + def output_field(self) -> BooleanField[bool]: ... + def select_format(self, compiler: SQLCompiler, sql: str, params: _ParamsT) -> _AsSqlType: ... + def get_db_converters(self, connection: BaseDatabaseWrapper) -> list[Any]: ... + def get_lookup(self, lookup: str) -> type[Lookup[Any]] | None: ... + def leaves(self) -> Iterator[Any]: ... class NothingNode: - contains_aggregate: bool = ... - def as_sql(self, compiler: SQLCompiler = ..., connection: Any = ...) -> Any: ... + contains_aggregate: bool + contains_over_clause: bool + def as_sql( + self, compiler: SQLCompiler | None = None, connection: BaseDatabaseWrapper | None = None + ) -> _AsSqlType: ... class ExtraWhere: - contains_aggregate: bool = ... - sqls: list[str] = ... - params: list[int] | list[str] | None = ... - def __init__(self, sqls: list[str], params: list[int] | list[str] | None) -> None: ... - def as_sql(self, compiler: SQLCompiler = ..., connection: Any = ...) -> tuple[str, list[int] | list[str]]: ... - -class SubqueryConstraint: - contains_aggregate: bool = ... - alias: str = ... - columns: list[str] = ... - targets: list[str] = ... - query_object: Query = ... - def __init__(self, alias: str, columns: list[str], targets: list[str], query_object: Query) -> None: ... - def as_sql(self, compiler: SQLCompiler, connection: Any) -> tuple[str, tuple[Any, ...]]: ... + contains_aggregate: bool + contains_over_clause: bool + sqls: Sequence[str] + params: Sequence[int] | Sequence[str] | None + def __init__(self, sqls: Sequence[str], params: Sequence[int] | Sequence[str] | None) -> None: ... + def as_sql( + self, compiler: SQLCompiler | None = None, connection: BaseDatabaseWrapper | None = None + ) -> _AsSqlType: ... diff --git a/django-stubs/test/utils.pyi b/django-stubs/test/utils.pyi index 1fb1fea43..19f569e16 100644 --- a/django-stubs/test/utils.pyi +++ b/django-stubs/test/utils.pyi @@ -8,7 +8,7 @@ from typing import Any, TypeAlias, TypeVar, overload from django.apps.registry import Apps from django.conf import LazySettings, Settings from django.core.checks.registry import CheckRegistry -from django.db import DefaultConnectionProxy +from django.db.backends.base.base import BaseDatabaseWrapper from django.test.runner import DiscoverRunner from django.test.testcases import SimpleTestCase from typing_extensions import Self @@ -45,7 +45,7 @@ def setup_databases( parallel: int = ..., aliases: Iterable[str] | None = ..., **kwargs: Any, -) -> list[tuple[DefaultConnectionProxy, str, bool]]: ... +) -> list[tuple[BaseDatabaseWrapper, str, bool]]: ... def get_runner(settings: LazySettings, test_runner_class: str | None = ...) -> type[DiscoverRunner]: ... class TestContextDecorator: diff --git a/s/fix-sync.yml b/s/fix-sync.yml index 3472cb056..302f04339 100644 --- a/s/fix-sync.yml +++ b/s/fix-sync.yml @@ -1,4 +1,5 @@ # ast-grep rules to fix bare Callable -> Callable[..., Any] +# and bare tuple -> tuple[Any, ...] id: fix-callable-simple language: python rule: @@ -21,6 +22,30 @@ rule: pattern: "|" fix: Callable[..., Any] --- +id: fix-tuple-type +language: python +rule: + pattern: tuple + inside: + kind: type +fix: tuple[Any, ...] +--- +id: fix-tuple-union-before +language: python +rule: + pattern: tuple + precedes: + pattern: "|" +fix: tuple[Any, ...] +--- +id: fix-tuple-union-after +language: python +rule: + pattern: tuple + follows: + pattern: "|" +fix: tuple[Any, ...] +--- id: fix-typevar-import language: python rule: diff --git a/s/sync-files.txt b/s/sync-files.txt index c2c4c92c1..539a80886 100644 --- a/s/sync-files.txt +++ b/s/sync-files.txt @@ -23,6 +23,22 @@ django-stubs/contrib/sitemaps/apps.pyi django-stubs/core/validators.pyi #django-stubs/utils/deconstruct.pyi django-stubs/utils/decorators.pyi -#django-stubs/db/models/__init__.pyi +django-stubs/db/models/__init__.pyi #django-stubs/db/models/query.pyi django-stubs/contrib/admin/decorators.pyi +#django-stubs/db/models/aggregates.pyi +#django-stubs/db/models/sql/compiler.pyi +#django-stubs/db/models/sql/query.pyi +#django-stubs/db/models/sql/subqueries.pyi +django-stubs/db/models/sql/__init__.pyi +#django-stubs/db/models/sql/where.pyi +django-stubs/db/models/sql/constants.pyi +django-stubs/db/models/sql/datastructures.pyi +django-stubs/db/models/functions/__init__.pyi +#django-stubs/db/models/functions/json.pyi +#django-stubs/db/models/functions/datetime.pyi +django-stubs/db/models/functions/math.pyi +#django-stubs/db/models/functions/comparison.pyi +#django-stubs/db/models/functions/text.pyi +django-stubs/db/__init__.pyi +django-stubs/db/migrations/executor.pyi