Issue #14328: Add keyword-only parameters to PyArg_ParseTupleAndKeywords.

They're optional-only for now (unlike in pure Python) but that's all
I needed.  The syntax can easily be relaxed if we want to support
required keyword-only arguments for extension types in the future.
This commit is contained in:
Larry Hastings 2012-03-20 20:06:16 +00:00
parent 2a886412ba
commit 83a9f48699
4 changed files with 134 additions and 3 deletions

View file

@ -1,6 +1,6 @@
import unittest
from test import support
from _testcapi import getargs_keywords
from _testcapi import getargs_keywords, getargs_keyword_only
"""
> How about the following counterproposal. This also changes some of
@ -293,6 +293,77 @@ class Keywords_TestCase(unittest.TestCase):
else:
self.fail('TypeError should have been raised')
class KeywordOnly_TestCase(unittest.TestCase):
def test_positional_args(self):
# using all possible positional args
self.assertEqual(
getargs_keyword_only(1, 2),
(1, 2, -1)
)
def test_mixed_args(self):
# positional and keyword args
self.assertEqual(
getargs_keyword_only(1, 2, keyword_only=3),
(1, 2, 3)
)
def test_keyword_args(self):
# all keywords
self.assertEqual(
getargs_keyword_only(required=1, optional=2, keyword_only=3),
(1, 2, 3)
)
def test_optional_args(self):
# missing optional keyword args, skipping tuples
self.assertEqual(
getargs_keyword_only(required=1, optional=2),
(1, 2, -1)
)
self.assertEqual(
getargs_keyword_only(required=1, keyword_only=3),
(1, -1, 3)
)
def test_required_args(self):
self.assertEqual(
getargs_keyword_only(1),
(1, -1, -1)
)
self.assertEqual(
getargs_keyword_only(required=1),
(1, -1, -1)
)
# required arg missing
with self.assertRaisesRegex(TypeError,
"Required argument 'required' \(pos 1\) not found"):
getargs_keyword_only(optional=2)
with self.assertRaisesRegex(TypeError,
"Required argument 'required' \(pos 1\) not found"):
getargs_keyword_only(keyword_only=3)
def test_too_many_args(self):
with self.assertRaisesRegex(TypeError,
"Function takes at most 2 positional arguments \(3 given\)"):
getargs_keyword_only(1, 2, 3)
with self.assertRaisesRegex(TypeError,
"function takes at most 3 arguments \(4 given\)"):
getargs_keyword_only(1, 2, 3, keyword_only=5)
def test_invalid_keyword(self):
# extraneous keyword arg
with self.assertRaisesRegex(TypeError,
"'monster' is an invalid keyword argument for this function"):
getargs_keyword_only(1, 2, monster=666)
def test_surrogate_keyword(self):
with self.assertRaisesRegex(TypeError,
"'\udc80' is an invalid keyword argument for this function"):
getargs_keyword_only(1, 2, **{'\uDC80': 10})
class Bytes_TestCase(unittest.TestCase):
def test_c(self):
from _testcapi import getargs_c
@ -441,6 +512,7 @@ def test_main():
Unsigned_TestCase,
Tuple_TestCase,
Keywords_TestCase,
KeywordOnly_TestCase,
Bytes_TestCase,
Unicode_TestCase,
]