# An object with __call__
call = getattr_static(type(obj), '__call__', None)
if call is not None:
+ try:
+ text_sig = obj.__text_signature__
+ except AttributeError:
+ pass
+ else:
+ if text_sig:
+ return _signature_fromstr(sigcls, obj, text_sig)
call = _descriptor_get(call, obj)
return _get_signature_of(call)
"""
__slots__ = ('_attrs', '_call')
- def __init__(self, attr, *attrs):
+ def __init__(self, attr, /, *attrs):
if not attrs:
if not isinstance(attr, str):
raise TypeError('attribute name must be a string')
return tuple(getter(obj) for getter in getters)
self._call = func
- def __call__(self, obj):
+ def __call__(self, obj, /):
return self._call(obj)
def __repr__(self):
"""
__slots__ = ('_items', '_call')
- def __init__(self, item, *items):
+ def __init__(self, item, /, *items):
if not items:
self._items = (item,)
def func(obj):
return tuple(obj[i] for i in items)
self._call = func
- def __call__(self, obj):
+ def __call__(self, obj, /):
return self._call(obj)
def __repr__(self):
self._args = args
self._kwargs = kwargs
- def __call__(self, obj):
+ def __call__(self, obj, /):
return getattr(obj, self._name)(*self._args, **self._kwargs)
def __repr__(self):
((('a', ..., ..., "positional_or_keyword"),),
...))
+ def test_signature_on_callable_objects_with_text_signature_attr(self):
+ class C:
+ __text_signature__ = '(a, /, b, c=True)'
+ def __call__(self, *args, **kwargs):
+ pass
+
+ self.assertEqual(self.signature(C), ((), ...))
+ self.assertEqual(self.signature(C()),
+ ((('a', ..., ..., "positional_only"),
+ ('b', ..., ..., "positional_or_keyword"),
+ ('c', True, ..., "positional_or_keyword"),
+ ),
+ ...))
+
+ c = C()
+ c.__text_signature__ = '(x, y)'
+ self.assertEqual(self.signature(c),
+ ((('x', ..., ..., "positional_or_keyword"),
+ ('y', ..., ..., "positional_or_keyword"),
+ ),
+ ...))
+
def test_signature_on_wrapper(self):
class Wrapper:
def __call__(self, b):
import unittest
+import inspect
import pickle
import sys
from decimal import Decimal
if dunder:
self.assertIs(dunder, orig)
+ def test_attrgetter_signature(self):
+ operator = self.module
+ sig = inspect.signature(operator.attrgetter)
+ self.assertEqual(str(sig), '(attr, /, *attrs)')
+ sig = inspect.signature(operator.attrgetter('x', 'z', 'y'))
+ self.assertEqual(str(sig), '(obj, /)')
+
+ def test_itemgetter_signature(self):
+ operator = self.module
+ sig = inspect.signature(operator.itemgetter)
+ self.assertEqual(str(sig), '(item, /, *items)')
+ sig = inspect.signature(operator.itemgetter(2, 3, 5))
+ self.assertEqual(str(sig), '(obj, /)')
+
+ def test_methodcaller_signature(self):
+ operator = self.module
+ sig = inspect.signature(operator.methodcaller)
+ self.assertEqual(str(sig), '(name, /, *args, **kwargs)')
+ sig = inspect.signature(operator.methodcaller('foo', 2, y=3))
+ self.assertEqual(str(sig), '(obj, /)')
+
+
class PyOperatorTestCase(OperatorTestCase, unittest.TestCase):
module = py_operator
--- /dev/null
+Allow to specify the signature of custom callable instances of extension
+type by the :attr:`__text_signature__` attribute. Specify signatures of
+:class:`operator.attrgetter`, :class:`operator.itemgetter`, and
+:class:`operator.methodcaller` instances.
};
+
+static PyObject *
+text_signature(PyObject *self, void *Py_UNUSED(ignored))
+{
+ return PyUnicode_FromString("(obj, /)");
+}
+
+static PyGetSetDef common_getset[] = {
+ {"__text_signature__", text_signature, (setter)NULL},
+ {NULL}
+};
+
/* itemgetter object **********************************************************/
typedef struct {
{Py_tp_clear, itemgetter_clear},
{Py_tp_methods, itemgetter_methods},
{Py_tp_members, itemgetter_members},
+ {Py_tp_getset, common_getset},
{Py_tp_new, itemgetter_new},
{Py_tp_getattro, PyObject_GenericGetAttr},
{Py_tp_repr, itemgetter_repr},
{Py_tp_clear, attrgetter_clear},
{Py_tp_methods, attrgetter_methods},
{Py_tp_members, attrgetter_members},
+ {Py_tp_getset, common_getset},
{Py_tp_new, attrgetter_new},
{Py_tp_getattro, PyObject_GenericGetAttr},
{Py_tp_repr, attrgetter_repr},
{Py_tp_clear, methodcaller_clear},
{Py_tp_methods, methodcaller_methods},
{Py_tp_members, methodcaller_members},
+ {Py_tp_getset, common_getset},
{Py_tp_new, methodcaller_new},
{Py_tp_getattro, PyObject_GenericGetAttr},
{Py_tp_repr, methodcaller_repr},