@@ -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,272 @@ 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' }
5383
+ unsupported_signature |= {name for name in ['register' ]
5384
+ if hasattr (faulthandler , name )}
5385
+ self ._test_module_has_signatures (faulthandler , unsupported_signature = unsupported_signature )
5386
+
5387
+ def test_functools_module_has_signatures (self ):
5388
+ no_signature = {'reduce' }
5389
+ self ._test_module_has_signatures (functools , no_signature )
5390
+
5391
+ def test_gc_module_has_signatures (self ):
5392
+ import gc
5393
+ no_signature = {'set_threshold' }
5394
+ self ._test_module_has_signatures (gc , no_signature )
5395
+
5396
+ def test_io_module_has_signatures (self ):
5397
+ methods_no_signature = {
5398
+ 'BufferedRWPair' : {'read' , 'peek' , 'read1' , 'readinto' , 'readinto1' , 'write' },
5399
+ }
5400
+ self ._test_module_has_signatures (io ,
5401
+ methods_no_signature = methods_no_signature )
5402
+
5403
+ def test_itertools_module_has_signatures (self ):
5404
+ import itertools
5405
+ no_signature = {'islice' , 'repeat' }
5406
+ self ._test_module_has_signatures (itertools , no_signature )
5407
+
5408
+ def test_locale_module_has_signatures (self ):
5409
+ import locale
5410
+ self ._test_module_has_signatures (locale )
5411
+
5412
+ def test_marshal_module_has_signatures (self ):
5413
+ import marshal
5414
+ self ._test_module_has_signatures (marshal )
5415
+
5416
+ def test_operator_module_has_signatures (self ):
5417
+ import operator
5418
+ self ._test_module_has_signatures (operator )
5419
+
5420
+ def test_os_module_has_signatures (self ):
5421
+ unsupported_signature = {'chmod' , 'utime' }
5422
+ unsupported_signature |= {name for name in
5423
+ ['get_terminal_size' , 'posix_spawn' , 'posix_spawnp' ,
5424
+ 'register_at_fork' , 'startfile' ]
5425
+ if hasattr (os , name )}
5426
+ self ._test_module_has_signatures (os , unsupported_signature = unsupported_signature )
5427
+
5428
+ def test_pwd_module_has_signatures (self ):
5429
+ pwd = import_helper .import_module ('pwd' )
5430
+ self ._test_module_has_signatures (pwd )
5431
+
5432
+ def test_re_module_has_signatures (self ):
5433
+ import re
5434
+ methods_no_signature = {'Match' : {'group' }}
5435
+ self ._test_module_has_signatures (re ,
5436
+ methods_no_signature = methods_no_signature ,
5437
+ good_exceptions = {'error' , 'PatternError' })
5438
+
5439
+ def test_signal_module_has_signatures (self ):
5440
+ import signal
5441
+ self ._test_module_has_signatures (signal )
5442
+
5443
+ def test_stat_module_has_signatures (self ):
5444
+ import stat
5445
+ self ._test_module_has_signatures (stat )
5446
+
5447
+ def test_string_module_has_signatures (self ):
5448
+ import string
5449
+ self ._test_module_has_signatures (string )
5450
+
5451
+ def test_symtable_module_has_signatures (self ):
5452
+ import symtable
5453
+ self ._test_module_has_signatures (symtable )
5454
+
5455
+ def test_sysconfig_module_has_signatures (self ):
5456
+ import sysconfig
5457
+ self ._test_module_has_signatures (sysconfig )
5458
+
5459
+ def test_threading_module_has_signatures (self ):
5460
+ import threading
5461
+ self ._test_module_has_signatures (threading )
5462
+
5463
+ def test_thread_module_has_signatures (self ):
5464
+ import _thread
5465
+ no_signature = {'RLock' }
5466
+ self ._test_module_has_signatures (_thread , no_signature )
5467
+
5468
+ def test_time_module_has_signatures (self ):
5469
+ no_signature = {
5470
+ 'asctime' , 'ctime' , 'get_clock_info' , 'gmtime' , 'localtime' ,
5471
+ 'strftime' , 'strptime'
5472
+ }
5473
+ no_signature |= {name for name in
5474
+ ['clock_getres' , 'clock_settime' , 'clock_settime_ns' ,
5475
+ 'pthread_getcpuclockid' ]
5476
+ if hasattr (time , name )}
5477
+ self ._test_module_has_signatures (time , no_signature )
5478
+
5479
+ def test_tokenize_module_has_signatures (self ):
5480
+ import tokenize
5481
+ self ._test_module_has_signatures (tokenize )
5482
+
5483
+ def test_tracemalloc_module_has_signatures (self ):
5484
+ import tracemalloc
5485
+ self ._test_module_has_signatures (tracemalloc )
5486
+
5487
+ def test_typing_module_has_signatures (self ):
5488
+ import typing
5489
+ no_signature = {'ParamSpec' , 'ParamSpecArgs' , 'ParamSpecKwargs' ,
5490
+ 'Text' , 'TypeAliasType' , 'TypeVar' , 'TypeVarTuple' }
5491
+ methods_no_signature = {
5492
+ 'Generic' : {'__class_getitem__' , '__init_subclass__' },
5493
+ }
5494
+ methods_unsupported_signature = {
5495
+ 'Text' : {'count' , 'find' , 'index' , 'rfind' , 'rindex' , 'startswith' , 'endswith' , 'maketrans' },
5496
+ }
5497
+ self ._test_module_has_signatures (typing , no_signature ,
5498
+ methods_no_signature = methods_no_signature ,
5499
+ methods_unsupported_signature = methods_unsupported_signature )
5500
+
5501
+ def test_warnings_module_has_signatures (self ):
5502
+ unsupported_signature = {'warn' , 'warn_explicit' }
5503
+ self ._test_module_has_signatures (warnings , unsupported_signature = unsupported_signature )
5504
+
5505
+ def test_weakref_module_has_signatures (self ):
5506
+ import weakref
5507
+ no_signature = {'ReferenceType' , 'ref' }
5508
+ self ._test_module_has_signatures (weakref , no_signature )
5278
5509
5279
5510
def test_python_function_override_signature (self ):
5280
5511
def func (* args , ** kwargs ):
0 commit comments