Skip to content

Commit 2899599

Browse files
[3.11] pythongh-106368: Increase Argument Clinic test coverage (python#106369)
Add tests for 'self' and 'defining_class' converter requirements. (cherry picked from commit 7f4c812) Co-authored-by: Erlend E. Aasland <[email protected]>
1 parent e0d951d commit 2899599

File tree

1 file changed

+111
-0
lines changed

1 file changed

+111
-0
lines changed

Lib/test/test_clinic.py

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -812,6 +812,117 @@ def test_other_bizarre_things_in_annotations_fail(self):
812812
)
813813
self.assertEqual(s, expected_failure_message)
814814

815+
def test_kwarg_splats_disallowed_in_function_call_annotations(self):
816+
expected_error_msg = (
817+
"Error on line 0:\n"
818+
"Cannot use a kwarg splat in a function-call annotation\n"
819+
)
820+
dataset = (
821+
'module fo\nfo.barbaz\n o: bool(**{None: "bang!"})',
822+
'module fo\nfo.barbaz -> bool(**{None: "bang!"})',
823+
'module fo\nfo.barbaz -> bool(**{"bang": 42})',
824+
'module fo\nfo.barbaz\n o: bool(**{"bang": None})',
825+
)
826+
for fn in dataset:
827+
with self.subTest(fn=fn):
828+
out = self.parse_function_should_fail(fn)
829+
self.assertEqual(out, expected_error_msg)
830+
831+
def test_self_param_placement(self):
832+
expected_error_msg = (
833+
"Error on line 0:\n"
834+
"A 'self' parameter, if specified, must be the very first thing "
835+
"in the parameter block.\n"
836+
)
837+
block = """
838+
module foo
839+
foo.func
840+
a: int
841+
self: self(type="PyObject *")
842+
"""
843+
out = self.parse_function_should_fail(block)
844+
self.assertEqual(out, expected_error_msg)
845+
846+
def test_self_param_cannot_be_optional(self):
847+
expected_error_msg = (
848+
"Error on line 0:\n"
849+
"A 'self' parameter cannot be marked optional.\n"
850+
)
851+
block = """
852+
module foo
853+
foo.func
854+
self: self(type="PyObject *") = None
855+
"""
856+
out = self.parse_function_should_fail(block)
857+
self.assertEqual(out, expected_error_msg)
858+
859+
def test_defining_class_param_placement(self):
860+
expected_error_msg = (
861+
"Error on line 0:\n"
862+
"A 'defining_class' parameter, if specified, must either be the "
863+
"first thing in the parameter block, or come just after 'self'.\n"
864+
)
865+
block = """
866+
module foo
867+
foo.func
868+
self: self(type="PyObject *")
869+
a: int
870+
cls: defining_class
871+
"""
872+
out = self.parse_function_should_fail(block)
873+
self.assertEqual(out, expected_error_msg)
874+
875+
def test_defining_class_param_cannot_be_optional(self):
876+
expected_error_msg = (
877+
"Error on line 0:\n"
878+
"A 'defining_class' parameter cannot be marked optional.\n"
879+
)
880+
block = """
881+
module foo
882+
foo.func
883+
cls: defining_class(type="PyObject *") = None
884+
"""
885+
out = self.parse_function_should_fail(block)
886+
self.assertEqual(out, expected_error_msg)
887+
888+
def test_unused_param(self):
889+
block = self.parse("""
890+
module foo
891+
foo.func
892+
fn: object
893+
k: float
894+
i: float(unused=True)
895+
/
896+
*
897+
flag: bool(unused=True) = False
898+
""")
899+
sig = block.signatures[1] # Function index == 1
900+
params = sig.parameters
901+
conv = lambda fn: params[fn].converter
902+
dataset = (
903+
{"name": "fn", "unused": False},
904+
{"name": "k", "unused": False},
905+
{"name": "i", "unused": True},
906+
{"name": "flag", "unused": True},
907+
)
908+
for param in dataset:
909+
name, unused = param.values()
910+
with self.subTest(name=name, unused=unused):
911+
p = conv(name)
912+
# Verify that the unused flag is parsed correctly.
913+
self.assertEqual(unused, p.unused)
914+
915+
# Now, check that we'll produce correct code.
916+
decl = p.simple_declaration(in_parser=False)
917+
if unused:
918+
self.assertIn("Py_UNUSED", decl)
919+
else:
920+
self.assertNotIn("Py_UNUSED", decl)
921+
922+
# Make sure the Py_UNUSED macro is not used in the parser body.
923+
parser_decl = p.simple_declaration(in_parser=True)
924+
self.assertNotIn("Py_UNUSED", parser_decl)
925+
815926
def parse(self, text):
816927
c = FakeClinic()
817928
parser = DSLParser(c)

0 commit comments

Comments
 (0)