with self.assertRaisesRegex(TypeError, msg):
A().t(a=1)
+ def test_positional_only_argument(self):
+ @functools.singledispatch
+ def f(arg, /, extra):
+ return "base"
+ @f.register
+ def f_int(arg: int, /, extra: str):
+ return "int"
+ @f.register
+ def f_str(arg: str, /, extra: int):
+ return "str"
+
+ self.assertEqual(f(None, "extra"), "base")
+ self.assertEqual(f(1, "extra"), "int")
+ self.assertEqual(f("s", "extra"), "str")
+
def test_union(self):
@functools.singledispatch
def f(arg):
self.assertEqual(TD.__annotations__, {'a': EqualToForwardRef('UniqueT', owner=TD, module=TD.__module__)})
self.assertEqual(get_type_hints(TD), {'a': TD.__type_params__[0]})
+ def test_get_type_hints_order(self):
+ """Ensure that the order of function annotations matches the order they're defined"""
+ def f(positional: int, /, normal: str, *args: bytes, kwarg: list, **kwargs: bool) -> tuple:
+ pass
+
+ self.assertEqual(list(gth(f)), ["positional", "normal", "args", "kwarg", "kwargs", "return"])
+
class GetUtilitiesTestCase(TestCase):
def test_get_origin(self):
--- /dev/null
+Reorder function annotations so positional-only arguments are returned
+before other arguments. This fixes how :func:`functools.singledispatch`
+registers functions with positional-only arguments.
Py_ssize_t *annotations_len)
{
RETURN_IF_ERROR(
- codegen_argannotations(c, args->args, annotations_len, loc));
+ codegen_argannotations(c, args->posonlyargs, annotations_len, loc));
RETURN_IF_ERROR(
- codegen_argannotations(c, args->posonlyargs, annotations_len, loc));
+ codegen_argannotations(c, args->args, annotations_len, loc));
if (args->vararg && args->vararg->annotation) {
RETURN_IF_ERROR(