mirror of
https://github.com/python/cpython.git
synced 2025-08-28 04:35:02 +00:00
gh-100039: enhance __signature__ to work with str and callables (GH-100168)
Callables should be either class- or static-methods. Enum now uses the classmethod version to greatly improve the help given for enums and flags.
This commit is contained in:
parent
5234e1cbea
commit
a5a7cea202
5 changed files with 73 additions and 4 deletions
|
@ -685,7 +685,7 @@ class EnumType(type):
|
||||||
'member order does not match _order_:\n %r\n %r'
|
'member order does not match _order_:\n %r\n %r'
|
||||||
% (enum_class._member_names_, _order_)
|
% (enum_class._member_names_, _order_)
|
||||||
)
|
)
|
||||||
|
#
|
||||||
return enum_class
|
return enum_class
|
||||||
|
|
||||||
def __bool__(cls):
|
def __bool__(cls):
|
||||||
|
@ -1083,6 +1083,13 @@ class Enum(metaclass=EnumType):
|
||||||
attributes -- see the documentation for details.
|
attributes -- see the documentation for details.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def __signature__(cls):
|
||||||
|
if cls._member_names_:
|
||||||
|
return '(*values)'
|
||||||
|
else:
|
||||||
|
return '(new_class_name, /, names, *, module=None, qualname=None, type=None, start=1, boundary=None)'
|
||||||
|
|
||||||
def __new__(cls, value):
|
def __new__(cls, value):
|
||||||
# all enum instances are actually created during class construction
|
# all enum instances are actually created during class construction
|
||||||
# without calling this method; this method is called by the metaclass'
|
# without calling this method; this method is called by the metaclass'
|
||||||
|
|
|
@ -2443,10 +2443,18 @@ def _signature_from_callable(obj, *,
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
if sig is not None:
|
if sig is not None:
|
||||||
|
# since __text_signature__ is not writable on classes, __signature__
|
||||||
|
# may contain text (or be a callable that returns text);
|
||||||
|
# if so, convert it
|
||||||
|
o_sig = sig
|
||||||
|
if not isinstance(sig, (Signature, str)) and callable(sig):
|
||||||
|
sig = sig()
|
||||||
|
if isinstance(sig, str):
|
||||||
|
sig = _signature_fromstr(sigcls, obj, sig)
|
||||||
if not isinstance(sig, Signature):
|
if not isinstance(sig, Signature):
|
||||||
raise TypeError(
|
raise TypeError(
|
||||||
'unexpected object {!r} in __signature__ '
|
'unexpected object {!r} in __signature__ '
|
||||||
'attribute'.format(sig))
|
'attribute'.format(o_sig))
|
||||||
return sig
|
return sig
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -4259,7 +4259,7 @@ expected_help_output_with_docs = """\
|
||||||
Help on class Color in module %s:
|
Help on class Color in module %s:
|
||||||
|
|
||||||
class Color(enum.Enum)
|
class Color(enum.Enum)
|
||||||
| Color(value, names=None, *values, module=None, qualname=None, type=None, start=1, boundary=None)
|
| Color(*values)
|
||||||
|
|
|
|
||||||
| Method resolution order:
|
| Method resolution order:
|
||||||
| Color
|
| Color
|
||||||
|
@ -4315,7 +4315,7 @@ expected_help_output_without_docs = """\
|
||||||
Help on class Color in module %s:
|
Help on class Color in module %s:
|
||||||
|
|
||||||
class Color(enum.Enum)
|
class Color(enum.Enum)
|
||||||
| Color(value, names=None, *values, module=None, qualname=None, type=None, start=1)
|
| Color(*values)
|
||||||
|
|
|
|
||||||
| Method resolution order:
|
| Method resolution order:
|
||||||
| Color
|
| Color
|
||||||
|
@ -4462,6 +4462,27 @@ class TestStdLib(unittest.TestCase):
|
||||||
if failed:
|
if failed:
|
||||||
self.fail("result does not equal expected, see print above")
|
self.fail("result does not equal expected, see print above")
|
||||||
|
|
||||||
|
def test_inspect_signatures(self):
|
||||||
|
from inspect import signature, Signature, Parameter
|
||||||
|
self.assertEqual(
|
||||||
|
signature(Enum),
|
||||||
|
Signature([
|
||||||
|
Parameter('new_class_name', Parameter.POSITIONAL_ONLY),
|
||||||
|
Parameter('names', Parameter.POSITIONAL_OR_KEYWORD),
|
||||||
|
Parameter('module', Parameter.KEYWORD_ONLY, default=None),
|
||||||
|
Parameter('qualname', Parameter.KEYWORD_ONLY, default=None),
|
||||||
|
Parameter('type', Parameter.KEYWORD_ONLY, default=None),
|
||||||
|
Parameter('start', Parameter.KEYWORD_ONLY, default=1),
|
||||||
|
Parameter('boundary', Parameter.KEYWORD_ONLY, default=None),
|
||||||
|
]),
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
signature(enum.FlagBoundary),
|
||||||
|
Signature([
|
||||||
|
Parameter('values', Parameter.VAR_POSITIONAL),
|
||||||
|
]),
|
||||||
|
)
|
||||||
|
|
||||||
def test_test_simple_enum(self):
|
def test_test_simple_enum(self):
|
||||||
@_simple_enum(Enum)
|
@_simple_enum(Enum)
|
||||||
class SimpleColor:
|
class SimpleColor:
|
||||||
|
|
|
@ -3614,6 +3614,38 @@ class TestSignatureObject(unittest.TestCase):
|
||||||
self.assertEqual(signature_func(foo), inspect.Signature())
|
self.assertEqual(signature_func(foo), inspect.Signature())
|
||||||
self.assertEqual(inspect.get_annotations(foo), {})
|
self.assertEqual(inspect.get_annotations(foo), {})
|
||||||
|
|
||||||
|
def test_signature_as_str(self):
|
||||||
|
self.maxDiff = None
|
||||||
|
class S:
|
||||||
|
__signature__ = '(a, b=2)'
|
||||||
|
|
||||||
|
self.assertEqual(self.signature(S),
|
||||||
|
((('a', ..., ..., 'positional_or_keyword'),
|
||||||
|
('b', 2, ..., 'positional_or_keyword')),
|
||||||
|
...))
|
||||||
|
|
||||||
|
def test_signature_as_callable(self):
|
||||||
|
# __signature__ should be either a staticmethod or a bound classmethod
|
||||||
|
class S:
|
||||||
|
@classmethod
|
||||||
|
def __signature__(cls):
|
||||||
|
return '(a, b=2)'
|
||||||
|
|
||||||
|
self.assertEqual(self.signature(S),
|
||||||
|
((('a', ..., ..., 'positional_or_keyword'),
|
||||||
|
('b', 2, ..., 'positional_or_keyword')),
|
||||||
|
...))
|
||||||
|
|
||||||
|
class S:
|
||||||
|
@staticmethod
|
||||||
|
def __signature__():
|
||||||
|
return '(a, b=2)'
|
||||||
|
|
||||||
|
self.assertEqual(self.signature(S),
|
||||||
|
((('a', ..., ..., 'positional_or_keyword'),
|
||||||
|
('b', 2, ..., 'positional_or_keyword')),
|
||||||
|
...))
|
||||||
|
|
||||||
|
|
||||||
class TestParameterObject(unittest.TestCase):
|
class TestParameterObject(unittest.TestCase):
|
||||||
def test_signature_parameter_kinds(self):
|
def test_signature_parameter_kinds(self):
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Improve signatures for enums and flags.
|
Loading…
Add table
Add a link
Reference in a new issue