diff --git a/django-stubs/db/migrations/operations/special.pyi b/django-stubs/db/migrations/operations/special.pyi index 1495b1de3..af8f86909 100644 --- a/django-stubs/db/migrations/operations/special.pyi +++ b/django-stubs/db/migrations/operations/special.pyi @@ -1,5 +1,5 @@ import sys -from typing import Any, Mapping, Optional, Sequence, Tuple, Union +from typing import Any, Dict, Mapping, Optional, Sequence, Tuple, Union from django.db.backends.base.schema import BaseDatabaseSchemaEditor from django.db.migrations.state import StateApps @@ -21,15 +21,17 @@ class SeparateDatabaseAndState(Operation): class RunSQL(Operation): noop: Literal[""] = ... - sql: Union[str, _ListOrTuple[str], _ListOrTuple[Tuple[str, Optional[_ListOrTuple[str]]]]] = ... - reverse_sql: Optional[Union[str, _ListOrTuple[str], _ListOrTuple[Tuple[str, Optional[_ListOrTuple[str]]]]]] = ... + sql: Union[str, _ListOrTuple[Union[str, Tuple[str, Union[Dict[str, Any], Optional[_ListOrTuple[str]]]]]]] = ... + reverse_sql: Optional[ + Union[str, _ListOrTuple[Union[str, Tuple[str, Union[Dict[str, Any], Optional[_ListOrTuple[str]]]]]]] + ] = ... state_operations: Sequence[Operation] = ... hints: Mapping[str, Any] = ... def __init__( self, - sql: Union[str, _ListOrTuple[str], _ListOrTuple[Tuple[str, Optional[_ListOrTuple[str]]]]], + sql: Union[str, _ListOrTuple[Union[str, Tuple[str, Union[Dict[str, Any], Optional[_ListOrTuple[str]]]]]]], reverse_sql: Optional[ - Union[str, _ListOrTuple[str], _ListOrTuple[Tuple[str, Optional[_ListOrTuple[str]]]]] + Union[str, _ListOrTuple[Union[str, Tuple[str, Union[Dict[str, Any], Optional[_ListOrTuple[str]]]]]]] ] = ..., state_operations: Sequence[Operation] = ..., hints: Optional[Mapping[str, Any]] = ..., diff --git a/tests/typecheck/db/migrations/test_operations.yml b/tests/typecheck/db/migrations/test_operations.yml new file mode 100644 index 000000000..7c830fb5c --- /dev/null +++ b/tests/typecheck/db/migrations/test_operations.yml @@ -0,0 +1,20 @@ +- case: runsql_sqls_variants + main: | + from django.db.migrations import RunSQL + + RunSQL(sql="SOME SQL") + + RunSQL(sql=("SOME SQLS", "SOME SQLS"), reverse_sql=("SOME SQLS", "SOME SQLS")) + + RunSQL(sql=["SOME SQLS", "SOME SQLS"], reverse_sql=["SOME SQLS", "SOME SQLS"]) + + RunSQL(sql=["SOME SQLS", ("SOME SQLS %s", ("SQL PARAM AS A TUPLE",))], reverse_sql=["SOME SQLS", ("SOME SQLS %s", ("SQL PARAM AS A TUPLE",))]) + + RunSQL(sql=["SOME SQLS", ("SOME SQLS NO PARAM", None)], reverse_sql=["SOME SQLS", ("SOME SQLS NO PARAM", None)]) + + RunSQL(sql=["SOME SQLS", ("SOME SQLS %(VAL)s", {"VAL": "FOO"})], reverse_sql=["SOME SQLS", ("SOME SQLS %(VAL)s", {"VAL": "FOO"})]) + + RunSQL(sql=["SOME SQLS", ("SOME SQLS %s, %s", ["PARAM", "ANOTHER PARAM"])], reverse_sql=["SOME SQLS", ("SOME SQLS %s, %s", ["PARAM", "ANOTHER PARAM"])]) + + RunSQL(sql=("SOME SQL", {})) # E: Argument "sql" to "RunSQL" has incompatible type "Tuple[str, Dict[, ]]"; expected "Union[str, Union[List[Union[str, Tuple[str, Union[Dict[str, Any], List[str], Tuple[str, ...], Tuple[], None]]]], Tuple[Union[str, Tuple[str, Union[Dict[str, Any], List[str], Tuple[str, ...], Tuple[], None]]], ...], Tuple[]]]" + RunSQL(sql=["SOME SQLS", ("SOME SQLS %s, %s", [object(), "ANOTHER PARAM"])]) # E: List item 0 has incompatible type "object"; expected "str"