@@ -5221,10 +5221,17 @@ class TestSignatureDefinitions(unittest.TestCase):
5221
5221
# This test case provides a home for checking that particular APIs
5222
5222
# have signatures available for introspection
5223
5223
5224
+ @staticmethod
5225
+ def is_public (name ):
5226
+ return not name .startswith ('_' ) or name .startswith ('__' ) and name .endswith ('__' )
5227
+
5224
5228
@cpython_only
5225
5229
@unittest .skipIf (MISSING_C_DOCSTRINGS ,
5226
5230
"Signature information for builtins requires docstrings" )
5227
- def test_builtins_have_signatures (self ):
5231
+ def _test_module_has_signatures (self , module ,
5232
+ no_signature = (), unsupported_signature = (),
5233
+ methods_no_signature = {}, methods_unsupported_signature = {},
5234
+ good_exceptions = ()):
5228
5235
# This checks all builtin callables in CPython have signatures
5229
5236
# A few have signatures Signature can't yet handle, so we skip those
5230
5237
# since they will have to wait until PEP 457 adds the required
@@ -5233,48 +5240,263 @@ def test_builtins_have_signatures(self):
5233
5240
# reasons, so we also skip those for the time being, but design
5234
5241
# the test to fail in order to indicate when it needs to be
5235
5242
# updated.
5236
- no_signature = set ()
5237
- # These need PEP 457 groups
5238
- needs_groups = {"range" , "slice" , "dir" , "getattr" ,
5239
- "next" , "iter" , "vars" }
5240
- no_signature |= needs_groups
5241
- # These have unrepresentable parameter default values of NULL
5242
- needs_null = {"anext" }
5243
- no_signature |= needs_null
5244
- # These need *args support in Argument Clinic
5245
- needs_varargs = {"min" , "max" , "__build_class__" }
5246
- no_signature |= needs_varargs
5247
- # These builtin types are expected to provide introspection info
5248
- types_with_signatures = {
5249
- 'bool' , 'classmethod' , 'complex' , 'enumerate' , 'filter' , 'float' ,
5250
- 'frozenset' , 'list' , 'map' , 'memoryview' , 'object' , 'property' ,
5251
- 'reversed' , 'set' , 'staticmethod' , 'tuple' , 'zip'
5252
- }
5243
+ no_signature = no_signature or set ()
5253
5244
# Check the signatures we expect to be there
5254
- ns = vars (builtins )
5245
+ ns = vars (module )
5246
+ try :
5247
+ names = set (module .__all__ )
5248
+ except AttributeError :
5249
+ names = set (name for name in ns if self .is_public (name ))
5255
5250
for name , obj in sorted (ns .items ()):
5251
+ if name not in names :
5252
+ continue
5256
5253
if not callable (obj ):
5257
5254
continue
5258
- # The builtin types haven't been converted to AC yet
5259
- if isinstance (obj , type ) and ( name not in types_with_signatures ):
5260
- # Note that this also skips all the exception types
5255
+ if ( isinstance ( obj , type ) and
5256
+ issubclass (obj , BaseException ) and
5257
+ name not in good_exceptions ):
5261
5258
no_signature .add (name )
5262
- if (name in no_signature ):
5263
- # Not yet converted
5264
- continue
5265
- if name in {'classmethod' , 'staticmethod' }:
5266
- # Bug gh-112006: inspect.unwrap() does not work with types
5267
- # with the __wrapped__ data descriptor.
5268
- continue
5269
- with self .subTest (builtin = name ):
5270
- self .assertIsNotNone (inspect .signature (obj ))
5259
+ if name not in no_signature and name not in unsupported_signature :
5260
+ with self .subTest ('supported' , builtin = name ):
5261
+ self .assertIsNotNone (inspect .signature (obj ))
5262
+ if isinstance (obj , type ):
5263
+ with self .subTest (type = name ):
5264
+ self ._test_builtin_methods_have_signatures (obj ,
5265
+ methods_no_signature .get (name , ()),
5266
+ methods_unsupported_signature .get (name , ()))
5271
5267
# Check callables that haven't been converted don't claim a signature
5272
5268
# This ensures this test will start failing as more signatures are
5273
5269
# added, so the affected items can be moved into the scope of the
5274
5270
# regression test above
5275
- for name in no_signature - needs_null :
5276
- with self .subTest (builtin = name ):
5277
- self .assertIsNone (ns [name ].__text_signature__ )
5271
+ for name in no_signature :
5272
+ with self .subTest ('none' , builtin = name ):
5273
+ obj = ns [name ]
5274
+ self .assertIsNone (obj .__text_signature__ )
5275
+ self .assertRaises (ValueError , inspect .signature , obj )
5276
+ for name in unsupported_signature :
5277
+ with self .subTest ('unsupported' , builtin = name ):
5278
+ obj = ns [name ]
5279
+ self .assertIsNotNone (obj .__text_signature__ )
5280
+ self .assertRaises (ValueError , inspect .signature , obj )
5281
+
5282
+ def _test_builtin_methods_have_signatures (self , cls , no_signature , unsupported_signature ):
5283
+ ns = vars (cls )
5284
+ for name in ns :
5285
+ obj = getattr (cls , name , None )
5286
+ if not callable (obj ) or isinstance (obj , type ):
5287
+ continue
5288
+ if name not in no_signature and name not in unsupported_signature :
5289
+ with self .subTest ('supported' , method = name ):
5290
+ self .assertIsNotNone (inspect .signature (obj ))
5291
+ for name in no_signature :
5292
+ with self .subTest ('none' , method = name ):
5293
+ self .assertIsNone (getattr (cls , name ).__text_signature__ )
5294
+ self .assertRaises (ValueError , inspect .signature , getattr (cls , name ))
5295
+ for name in unsupported_signature :
5296
+ with self .subTest ('unsupported' , method = name ):
5297
+ self .assertIsNotNone (getattr (cls , name ).__text_signature__ )
5298
+ self .assertRaises (ValueError , inspect .signature , getattr (cls , name ))
5299
+
5300
+ def test_builtins_have_signatures (self ):
5301
+ no_signature = {'type' , 'super' , 'bytearray' , 'bytes' , 'dict' , 'int' , 'str' }
5302
+ # These need PEP 457 groups
5303
+ needs_groups = {"range" , "slice" , "dir" , "getattr" ,
5304
+ "next" , "iter" , "vars" }
5305
+ no_signature |= needs_groups
5306
+ # These have unrepresentable parameter default values of NULL
5307
+ unsupported_signature = {"anext" }
5308
+ # These need *args support in Argument Clinic
5309
+ needs_varargs = {"min" , "max" , "__build_class__" }
5310
+ no_signature |= needs_varargs
5311
+
5312
+ methods_no_signature = {
5313
+ 'dict' : {'update' },
5314
+ 'object' : {'__class__' },
5315
+ }
5316
+ methods_unsupported_signature = {
5317
+ 'bytearray' : {'count' , 'endswith' , 'find' , 'hex' , 'index' , 'rfind' , 'rindex' , 'startswith' },
5318
+ 'bytes' : {'count' , 'endswith' , 'find' , 'hex' , 'index' , 'rfind' , 'rindex' , 'startswith' },
5319
+ 'dict' : {'pop' },
5320
+ 'int' : {'__round__' },
5321
+ 'memoryview' : {'cast' , 'hex' },
5322
+ 'str' : {'count' , 'endswith' , 'find' , 'index' , 'maketrans' , 'rfind' , 'rindex' , 'startswith' },
5323
+ }
5324
+ self ._test_module_has_signatures (builtins ,
5325
+ no_signature , unsupported_signature ,
5326
+ methods_no_signature , methods_unsupported_signature )
5327
+
5328
+ def test_types_module_has_signatures (self ):
5329
+ unsupported_signature = {'CellType' }
5330
+ methods_no_signature = {
5331
+ 'AsyncGeneratorType' : {'athrow' },
5332
+ 'CoroutineType' : {'throw' },
5333
+ 'GeneratorType' : {'throw' },
5334
+ }
5335
+ self ._test_module_has_signatures (types ,
5336
+ unsupported_signature = unsupported_signature ,
5337
+ methods_no_signature = methods_no_signature )
5338
+
5339
+ def test_sys_module_has_signatures (self ):
5340
+ no_signature = {'getsizeof' , 'set_asyncgen_hooks' }
5341
+ self ._test_module_has_signatures (sys , no_signature )
5342
+
5343
+ def test_abc_module_has_signatures (self ):
5344
+ import abc
5345
+ self ._test_module_has_signatures (abc )
5346
+
5347
+ def test_atexit_module_has_signatures (self ):
5348
+ import atexit
5349
+ self ._test_module_has_signatures (atexit )
5350
+
5351
+ def test_codecs_module_has_signatures (self ):
5352
+ import codecs
5353
+ methods_no_signature = {'StreamReader' : {'charbuffertype' }}
5354
+ self ._test_module_has_signatures (codecs ,
5355
+ methods_no_signature = methods_no_signature )
5356
+
5357
+ def test_collections_module_has_signatures (self ):
5358
+ no_signature = {'OrderedDict' , 'defaultdict' }
5359
+ unsupported_signature = {'deque' }
5360
+ methods_no_signature = {
5361
+ 'OrderedDict' : {'update' },
5362
+ }
5363
+ methods_unsupported_signature = {
5364
+ 'deque' : {'index' },
5365
+ 'OrderedDict' : {'pop' },
5366
+ 'UserString' : {'maketrans' },
5367
+ }
5368
+ self ._test_module_has_signatures (collections ,
5369
+ no_signature , unsupported_signature ,
5370
+ methods_no_signature , methods_unsupported_signature )
5371
+
5372
+ def test_collections_abc_module_has_signatures (self ):
5373
+ import collections .abc
5374
+ self ._test_module_has_signatures (collections .abc )
5375
+
5376
+ def test_errno_module_has_signatures (self ):
5377
+ import errno
5378
+ self ._test_module_has_signatures (errno )
5379
+
5380
+ def test_faulthandler_module_has_signatures (self ):
5381
+ import faulthandler
5382
+ unsupported_signature = {'dump_traceback' , 'dump_traceback_later' , 'enable' , 'register' }
5383
+ self ._test_module_has_signatures (faulthandler , unsupported_signature = unsupported_signature )
5384
+
5385
+ def test_functools_module_has_signatures (self ):
5386
+ no_signature = {'reduce' }
5387
+ self ._test_module_has_signatures (functools , no_signature )
5388
+
5389
+ def test_gc_module_has_signatures (self ):
5390
+ import gc
5391
+ no_signature = {'set_threshold' }
5392
+ self ._test_module_has_signatures (gc , no_signature )
5393
+
5394
+ def test_io_module_has_signatures (self ):
5395
+ methods_no_signature = {
5396
+ 'BufferedRWPair' : {'read' , 'peek' , 'read1' , 'readinto' , 'readinto1' , 'write' },
5397
+ }
5398
+ self ._test_module_has_signatures (io ,
5399
+ methods_no_signature = methods_no_signature )
5400
+
5401
+ def test_itertools_module_has_signatures (self ):
5402
+ import itertools
5403
+ no_signature = {'islice' , 'repeat' }
5404
+ self ._test_module_has_signatures (itertools , no_signature )
5405
+
5406
+ def test_locale_module_has_signatures (self ):
5407
+ import locale
5408
+ self ._test_module_has_signatures (locale )
5409
+
5410
+ def test_marshal_module_has_signatures (self ):
5411
+ import marshal
5412
+ self ._test_module_has_signatures (marshal )
5413
+
5414
+ def test_operator_module_has_signatures (self ):
5415
+ import operator
5416
+ self ._test_module_has_signatures (operator )
5417
+
5418
+ def test_os_module_has_signatures (self ):
5419
+ unsupported_signature = {'chmod' , 'get_terminal_size' , 'posix_spawn' , 'posix_spawnp' , 'register_at_fork' , 'utime' }
5420
+ self ._test_module_has_signatures (os , unsupported_signature = unsupported_signature )
5421
+
5422
+ def test_pwd_module_has_signatures (self ):
5423
+ import pwd
5424
+ self ._test_module_has_signatures (pwd )
5425
+
5426
+ def test_re_module_has_signatures (self ):
5427
+ import re
5428
+ methods_no_signature = {'Match' : {'group' }}
5429
+ self ._test_module_has_signatures (re ,
5430
+ methods_no_signature = methods_no_signature ,
5431
+ good_exceptions = {'error' , 'PatternError' })
5432
+
5433
+ def test_signal_module_has_signatures (self ):
5434
+ import signal
5435
+ self ._test_module_has_signatures (signal )
5436
+
5437
+ def test_stat_module_has_signatures (self ):
5438
+ import stat
5439
+ self ._test_module_has_signatures (stat )
5440
+
5441
+ def test_string_module_has_signatures (self ):
5442
+ import string
5443
+ self ._test_module_has_signatures (string )
5444
+
5445
+ def test_symtable_module_has_signatures (self ):
5446
+ import symtable
5447
+ self ._test_module_has_signatures (symtable )
5448
+
5449
+ def test_sysconfig_module_has_signatures (self ):
5450
+ import sysconfig
5451
+ self ._test_module_has_signatures (sysconfig )
5452
+
5453
+ def test_threading_module_has_signatures (self ):
5454
+ import threading
5455
+ self ._test_module_has_signatures (threading )
5456
+
5457
+ def test_thread_module_has_signatures (self ):
5458
+ import _thread
5459
+ no_signature = {'RLock' }
5460
+ self ._test_module_has_signatures (_thread , no_signature )
5461
+
5462
+ def test_time_module_has_signatures (self ):
5463
+ no_signature = {
5464
+ 'asctime' , 'clock_getres' , 'clock_settime' , 'clock_settime_ns' ,
5465
+ 'ctime' , 'get_clock_info' , 'gmtime' , 'localtime' ,
5466
+ 'pthread_getcpuclockid' , 'strftime' , 'strptime'
5467
+ }
5468
+ self ._test_module_has_signatures (time , no_signature )
5469
+
5470
+ def test_tokenize_module_has_signatures (self ):
5471
+ import tokenize
5472
+ self ._test_module_has_signatures (tokenize )
5473
+
5474
+ def test_tracemalloc_module_has_signatures (self ):
5475
+ import tracemalloc
5476
+ self ._test_module_has_signatures (tracemalloc )
5477
+
5478
+ def test_typing_module_has_signatures (self ):
5479
+ import typing
5480
+ no_signature = {'ParamSpec' , 'ParamSpecArgs' , 'ParamSpecKwargs' ,
5481
+ 'Text' , 'TypeAliasType' , 'TypeVar' , 'TypeVarTuple' }
5482
+ methods_no_signature = {
5483
+ 'Generic' : {'__class_getitem__' , '__init_subclass__' },
5484
+ }
5485
+ methods_unsupported_signature = {
5486
+ 'Text' : {'count' , 'find' , 'index' , 'rfind' , 'rindex' , 'startswith' , 'endswith' , 'maketrans' },
5487
+ }
5488
+ self ._test_module_has_signatures (typing , no_signature ,
5489
+ methods_no_signature = methods_no_signature ,
5490
+ methods_unsupported_signature = methods_unsupported_signature )
5491
+
5492
+ def test_warnings_module_has_signatures (self ):
5493
+ unsupported_signature = {'warn' , 'warn_explicit' }
5494
+ self ._test_module_has_signatures (warnings , unsupported_signature = unsupported_signature )
5495
+
5496
+ def test_weakref_module_has_signatures (self ):
5497
+ import weakref
5498
+ no_signature = {'ReferenceType' , 'ref' }
5499
+ self ._test_module_has_signatures (weakref , no_signature )
5278
5500
5279
5501
def test_python_function_override_signature (self ):
5280
5502
def func (* args , ** kwargs ):
0 commit comments