2323 import libclinic
2424 from libclinic import ClinicError , unspecified , NULL , fail
2525 from libclinic .converters import (
26- int_converter , object_converter , str_converter , self_converter ,
27- Py_ssize_t_converter )
26+ int_converter , object_converter , str_converter , self_converter )
2827 from libclinic .function import (
2928 Module , Class , Function , FunctionKind , Parameter ,
3029 permute_optional_groups , permute_right_option_groups ,
3534 from libclinic .return_converters import return_converters , int_return_converter
3635 from libclinic .block_parser import Block , BlockParser
3736 from libclinic .codegen import BlockPrinter , Destination
38- from libclinic .dsl_parser import DSLParser
37+ from libclinic .dsl_parser import DSLParser , unsupported_special_methods
3938 from libclinic .slots import SlotSpec , SLOTS
4039 from libclinic .cli import parse_file , Clinic
4140
@@ -858,11 +857,10 @@ class Foo "FooObject *" "&Foo_Type"
858857
859858 def test_slot_with_parameters_and_return_type (self ):
860859 # Slots which take arguments or return something else than an
861- # object are not supported yet; check the machinery with fake ones .
860+ # object are not supported yet; check the machinery with them .
862861 slots = {
863- '__contains__' : SlotSpec ('__contains__' , 'int' , 'int' ,
864- {(object_converter ,): 'sq_contains' }),
865- '__bool__' : SlotSpec ('__bool__' , 'int' , 'int' , {(): 'nb_bool' }),
862+ '__contains__' : SlotSpec (return_converter = 'int' ),
863+ '__bool__' : SlotSpec (return_converter = 'int' ),
866864 }
867865 block = """
868866 /*[clinic input]
@@ -3353,42 +3351,38 @@ class Foo "FooObject *" ""
33533351 Foo.__next__
33543352 """ , signatures_in_block = 3 , function_index = 2 )
33553353 self .assertIs (function .kind , FunctionKind .SLOT )
3356- self .assertEqual (function .slot . name , "__next__" )
3354+ self .assertIs (function .slot , SLOTS [ "__next__" ] )
33573355 self .assertEqual (function .c_basename , "Foo_next" )
33583356 self .assertEqual (function .return_converter .type , "PyObject *" )
33593357 self .assertEqual (list (function .parameters ), ["self" ])
33603358
33613359 def test_slot_parameters (self ):
3362- slot = SlotSpec ('__contains__' , 'int' , 'int' , {
3363- (Py_ssize_t_converter ,): 'sq_fake' ,
3364- (object_converter ,): 'sq_contains' })
3360+ # __getitem__ is not supported yet; its parameter gives the slot
3361+ # (Py_ssize_t for sq_item, object for mp_subscript) and is not parsed.
33653362 block = """
33663363 module foo
33673364 class Foo "FooObject *" ""
3368- Foo.__contains__
3369- value : {converter}
3365+ Foo.__getitem__
3366+ key : {converter}
33703367 /
33713368 """
33723369 errors = [
3373- ("Foo.__contains__" ,
3374- "'__contains__' must declare (Py_ssize_t) for sq_fake or "
3375- "(object) for sq_contains; got ()" ),
3376- ("Foo.__contains__\n value: int\n /" ,
3377- "'__contains__' must declare" ),
3378- ("Foo.__contains__\n value: object" ,
3379- "The parameters of '__contains__' must be positional-only" ),
3380- ("Foo.__contains__\n value: object = None\n /" ,
3381- "The parameters of '__contains__' cannot have a default value" ),
3370+ ("Foo.__getitem__\n key: object" ,
3371+ "The parameters of '__getitem__' must be positional-only" ),
3372+ ("Foo.__getitem__\n key: object = None\n /" ,
3373+ "The parameters of '__getitem__' cannot have a default value" ),
33823374 ]
3383- with mock .patch .dict (SLOTS , {'__contains__' : slot }):
3375+ supported = unsupported_special_methods - {'__getitem__' }
3376+ with (mock .patch .dict (SLOTS , {'__getitem__' : SlotSpec (return_converter = 'object' )}),
3377+ mock .patch .object (libclinic .dsl_parser ,
3378+ 'unsupported_special_methods' , supported )):
33843379 for converter in "Py_ssize_t" , "object" :
33853380 with self .subTest (converter = converter ):
33863381 function = self .parse_function (
33873382 block .format (converter = converter ),
33883383 signatures_in_block = 3 , function_index = 2 )
33893384 self .assertIs (function .kind , FunctionKind .SLOT )
3390- self .assertEqual (function .return_converter .type , "int" )
3391- self .assertEqual (list (function .parameters ), ["self" , "value" ])
3385+ self .assertEqual (list (function .parameters ), ["self" , "key" ])
33923386 for body , err in errors :
33933387 with self .subTest (block = body ):
33943388 body = 'class Foo "FooObject *" "&Foo_Type"\n ' + body
@@ -3406,8 +3400,6 @@ def test_slot_errors(self):
34063400 "@coexist cannot be applied to '__next__'" ),
34073401 ("@vectorcall\n Foo.__next__" ,
34083402 "@vectorcall can only be used with __init__ and __new__" ),
3409- ("Foo.__next__\n a: int" ,
3410- "'__next__' methods cannot define parameters" ),
34113403 ("Foo.__next__ -> int" ,
34123404 "'Foo.__next__' cannot define a return type" ),
34133405 ("Foo.__next__\n \n Return the next item." ,
@@ -3660,10 +3652,10 @@ def test_illegal_c_identifier(self):
36603652 self .expect_failure (block , err , lineno = 2 )
36613653
36623654 def test_cannot_convert_special_method (self ):
3663- err = "'__len__ ' is a special method and cannot be converted"
3655+ err = "'__iter__ ' is a special method and cannot be converted"
36643656 block = """
36653657 class T "" ""
3666- T.__len__
3658+ T.__iter__
36673659 """
36683660 self .expect_failure (block , err , lineno = 1 )
36693661
0 commit comments