"or a descriptor")
if args and args[-1] is Placeholder:
raise TypeError("trailing Placeholders are not allowed")
+ for value in keywords.values():
+ if value is Placeholder:
+ raise TypeError("Placeholder cannot be passed as a keyword argument")
if isinstance(func, base_cls):
pto_phcount = func._phcount
tot_args = func.args
import contextlib
from inspect import Signature
+from test.support import ALWAYS_EQ
from test.support import import_helper
from test.support import threading_helper
from test.support import cpython_only
actual_args, actual_kwds = p('x', 'y')
self.assertEqual(actual_args, ('x', 0, 'y', 1))
self.assertEqual(actual_kwds, {})
+ # Checks via `is` and not `eq`
+ # thus ALWAYS_EQ isn't treated as Placeholder
+ p = self.partial(capture, ALWAYS_EQ)
+ actual_args, actual_kwds = p()
+ self.assertEqual(len(actual_args), 1)
+ self.assertIs(actual_args[0], ALWAYS_EQ)
+ self.assertEqual(actual_kwds, {})
def test_placeholders_optimization(self):
PH = self.module.Placeholder
self.assertEqual(p2.args, (PH, 0))
self.assertEqual(p2(1), ((1, 0), {}))
+ def test_placeholders_kw_restriction(self):
+ PH = self.module.Placeholder
+ with self.assertRaisesRegex(TypeError, "Placeholder"):
+ self.partial(capture, a=PH)
+ # Passes, as checks via `is` and not `eq`
+ p = self.partial(capture, a=ALWAYS_EQ)
+ actual_args, actual_kwds = p()
+ self.assertEqual(actual_args, ())
+ self.assertEqual(len(actual_kwds), 1)
+ self.assertIs(actual_kwds['a'], ALWAYS_EQ)
+
def test_construct_placeholder_singleton(self):
PH = self.module.Placeholder
tp = type(PH)
return NULL;
}
+ /* keyword Placeholder prohibition */
+ if (kw != NULL) {
+ PyObject *key, *val;
+ Py_ssize_t pos = 0;
+ while (PyDict_Next(kw, &pos, &key, &val)) {
+ if (val == phold) {
+ PyErr_SetString(PyExc_TypeError,
+ "Placeholder cannot be passed as a keyword argument");
+ return NULL;
+ }
+ }
+ }
+
/* check wrapped function / object */
pto_args = pto_kw = NULL;
int res = PyObject_TypeCheck(func, state->partial_type);