Fixed #35175 -- Made migraton writer preserve keyword-only arguments.

Thanks Gerald Goh for the report.
This commit is contained in:
David Sanders 2024-02-08 19:57:14 +11:00 committed by Mariusz Felisiak
parent 8b7ddd1b62
commit 06264258dc
4 changed files with 53 additions and 5 deletions

View File

@ -16,13 +16,18 @@ def _get_callable_parameters(meth_or_func):
return _get_func_parameters(func, remove_first=is_method)
ARG_KINDS = frozenset(
{
inspect.Parameter.POSITIONAL_ONLY,
inspect.Parameter.KEYWORD_ONLY,
inspect.Parameter.POSITIONAL_OR_KEYWORD,
}
)
def get_func_args(func):
params = _get_callable_parameters(func)
return [
param.name
for param in params
if param.kind == inspect.Parameter.POSITIONAL_OR_KEYWORD
]
return [param.name for param in params if param.kind in ARG_KINDS]
def get_func_full_args(func):

View File

@ -68,6 +68,11 @@ class ArgsKwargsOperation(TestOperation):
)
class ArgsAndKeywordOnlyArgsOperation(ArgsKwargsOperation):
def __init__(self, arg1, arg2, *, kwarg1, kwarg2):
super().__init__(arg1, arg2, kwarg1=kwarg1, kwarg2=kwarg2)
class ExpandArgsOperation(TestOperation):
serialization_expand_args = ["arg"]

View File

@ -152,6 +152,24 @@ class OperationWriterTests(SimpleTestCase):
"),",
)
def test_keyword_only_args_signature(self):
operation = (
custom_migration_operations.operations.ArgsAndKeywordOnlyArgsOperation(
1, 2, kwarg1=3, kwarg2=4
)
)
buff, imports = OperationWriter(operation, indentation=0).serialize()
self.assertEqual(imports, {"import custom_migration_operations.operations"})
self.assertEqual(
buff,
"custom_migration_operations.operations.ArgsAndKeywordOnlyArgsOperation(\n"
" arg1=1,\n"
" arg2=2,\n"
" kwarg1=3,\n"
" kwarg2=4,\n"
"),",
)
def test_nested_args_signature(self):
operation = custom_migration_operations.operations.ArgsOperation(
custom_migration_operations.operations.ArgsOperation(1, 2),

View File

@ -4,6 +4,7 @@ from migrations.test_base import OperationTestBase
from django.db import IntegrityError, NotSupportedError, connection, transaction
from django.db.migrations.state import ProjectState
from django.db.migrations.writer import OperationWriter
from django.db.models import CheckConstraint, Index, Q, UniqueConstraint
from django.db.utils import ProgrammingError
from django.test import modify_settings, override_settings
@ -393,6 +394,25 @@ class CreateCollationTests(PostgreSQLTestCase):
self.assertEqual(len(captured_queries), 1)
self.assertIn("DROP COLLATION", captured_queries[0]["sql"])
def test_writer(self):
operation = CreateCollation(
"sample_collation",
"und-u-ks-level2",
provider="icu",
deterministic=False,
)
buff, imports = OperationWriter(operation, indentation=0).serialize()
self.assertEqual(imports, {"import django.contrib.postgres.operations"})
self.assertEqual(
buff,
"django.contrib.postgres.operations.CreateCollation(\n"
" name='sample_collation',\n"
" locale='und-u-ks-level2',\n"
" provider='icu',\n"
" deterministic=False,\n"
"),",
)
@unittest.skipUnless(connection.vendor == "postgresql", "PostgreSQL specific tests.")
class RemoveCollationTests(PostgreSQLTestCase):