@@ -2207,132 +2207,219 @@ def test_module_state_shared_in_global(self):
2207
2207
@requires_subinterpreters
2208
2208
class InterpreterIDTests (unittest .TestCase ):
2209
2209
2210
- InterpreterID = _testcapi .get_interpreterid_type ()
2210
+ # InterpreterID = _testcapi.get_interpreterid_type()
2211
2211
2212
- def new_interpreter (self ):
2213
- def ensure_destroyed (interpid ):
2212
+ def check_id (self , interpid , * , force = False ):
2213
+ if force :
2214
+ return
2215
+
2216
+ def add_interp_cleanup (self , interpid ):
2217
+ def ensure_destroyed ():
2214
2218
try :
2215
2219
_interpreters .destroy (interpid )
2216
2220
except _interpreters .InterpreterNotFoundError :
2217
2221
pass
2222
+ self .addCleanup (ensure_destroyed )
2223
+
2224
+ def new_interpreter (self ):
2218
2225
id = _interpreters .create ()
2219
- self .addCleanup ( lambda : ensure_destroyed ( id ) )
2226
+ self .add_interp_cleanup ( id )
2220
2227
return id
2221
2228
2222
- def test_with_int (self ):
2223
- id = self . InterpreterID ( 10 , force = True )
2229
+ def test_conversion (self ):
2230
+ convert = _testinternalcapi . normalize_interp_id
2224
2231
2225
- self .assertEqual (int (id ), 10 )
2232
+ with self .subTest ('int' ):
2233
+ interpid = convert (10 )
2234
+ self .assertEqual (interpid , 10 )
2226
2235
2227
- def test_coerce_id ( self ):
2228
- class Int (str ):
2229
- def __index__ (self ):
2230
- return 10
2236
+ with self . subTest ( 'coerced' ):
2237
+ class MyInt (str ):
2238
+ def __index__ (self ):
2239
+ return 10
2231
2240
2232
- id = self . InterpreterID ( Int (), force = True )
2233
- self .assertEqual (int ( id ) , 10 )
2241
+ interpid = convert ( MyInt () )
2242
+ self .assertEqual (interpid , 10 )
2234
2243
2235
- def test_bad_id (self ):
2236
2244
for badid in [
2237
2245
object (),
2238
2246
10.0 ,
2239
2247
'10' ,
2240
2248
b'10' ,
2241
2249
]:
2242
- with self .subTest (badid ):
2250
+ with self .subTest (f'bad: { badid !r } ' ):
2243
2251
with self .assertRaises (TypeError ):
2244
- self . InterpreterID (badid )
2252
+ convert (badid )
2245
2253
2246
2254
badid = - 1
2247
- with self .subTest (badid ):
2255
+ with self .subTest (f'bad: { badid !r } ' ):
2248
2256
with self .assertRaises (ValueError ):
2249
- self . InterpreterID (badid )
2257
+ convert (badid )
2250
2258
2251
2259
badid = 2 ** 64
2252
- with self .subTest (badid ):
2260
+ with self .subTest (f'bad: { badid !r } ' ):
2253
2261
with self .assertRaises (OverflowError ):
2254
- self . InterpreterID (badid )
2262
+ convert (badid )
2255
2263
2256
- def test_exists (self ):
2257
- id = self .new_interpreter ()
2258
- with self .assertRaises (_interpreters .InterpreterNotFoundError ):
2259
- self .InterpreterID (int (id ) + 1 ) # unforced
2264
+ def test_lookup (self ):
2265
+ with self .subTest ('exists' ):
2266
+ interpid = self .new_interpreter ()
2267
+ self .assertTrue (
2268
+ _testinternalcapi .interpreter_exists (interpid ))
2260
2269
2261
- def test_does_not_exist ( self ):
2262
- id = self . new_interpreter ()
2263
- with self .assertRaises ( _interpreters . InterpreterNotFoundError ):
2264
- self . InterpreterID ( int ( id ) + 1 ) # unforced
2270
+ with self . subTest ( 'does not exist' ):
2271
+ interpid = _testinternalcapi . unused_interpreter_id ()
2272
+ self .assertFalse (
2273
+ _testinternalcapi . interpreter_exists ( interpid ))
2265
2274
2266
- def test_destroyed (self ):
2267
- id = _interpreters .create ()
2268
- _interpreters .destroy (id )
2269
- with self .assertRaises (_interpreters .InterpreterNotFoundError ):
2270
- self .InterpreterID (id ) # unforced
2271
-
2272
- def test_str (self ):
2273
- id = self .InterpreterID (10 , force = True )
2274
- self .assertEqual (str (id ), '10' )
2275
-
2276
- def test_repr (self ):
2277
- id = self .InterpreterID (10 , force = True )
2278
- self .assertEqual (repr (id ), 'InterpreterID(10)' )
2279
-
2280
- def test_equality (self ):
2281
- id1 = self .new_interpreter ()
2282
- id2 = self .InterpreterID (id1 )
2283
- id3 = self .InterpreterID (
2284
- self .new_interpreter ())
2285
-
2286
- self .assertTrue (id2 == id2 ) # identity
2287
- self .assertTrue (id2 == id1 ) # int-equivalent
2288
- self .assertTrue (id1 == id2 ) # reversed
2289
- self .assertTrue (id2 == int (id2 ))
2290
- self .assertTrue (id2 == float (int (id2 )))
2291
- self .assertTrue (float (int (id2 )) == id2 )
2292
- self .assertFalse (id2 == float (int (id2 )) + 0.1 )
2293
- self .assertFalse (id2 == str (int (id2 )))
2294
- self .assertFalse (id2 == 2 ** 1000 )
2295
- self .assertFalse (id2 == float ('inf' ))
2296
- self .assertFalse (id2 == 'spam' )
2297
- self .assertFalse (id2 == id3 )
2298
-
2299
- self .assertFalse (id2 != id2 )
2300
- self .assertFalse (id2 != id1 )
2301
- self .assertFalse (id1 != id2 )
2302
- self .assertTrue (id2 != id3 )
2275
+ with self .subTest ('destroyed' ):
2276
+ interpid = _interpreters .create ()
2277
+ _interpreters .destroy (interpid )
2278
+ self .assertFalse (
2279
+ _testinternalcapi .interpreter_exists (interpid ))
2303
2280
2304
2281
def test_linked_lifecycle (self ):
2305
- id1 = _interpreters .create ()
2306
- _testinternalcapi .unlink_interpreter_refcount (id1 )
2307
- self .assertEqual (
2308
- _testinternalcapi .get_interpreter_refcount (id1 ),
2309
- 0 )
2310
-
2311
- id2 = self .InterpreterID (id1 )
2282
+ def create ():
2283
+ interpid = _testinternalcapi .new_interpreter ()
2284
+ self .add_interp_cleanup (interpid )
2285
+ return interpid
2286
+
2287
+ exists = _testinternalcapi .interpreter_exists
2288
+ is_linked = _testinternalcapi .interpreter_refcount_linked
2289
+ link = _testinternalcapi .link_interpreter_refcount
2290
+ unlink = _testinternalcapi .unlink_interpreter_refcount
2291
+ get_refcount = _testinternalcapi .get_interpreter_refcount
2292
+ incref = _testinternalcapi .interpreter_incref
2293
+ decref = _testinternalcapi .interpreter_decref
2294
+
2295
+ with self .subTest ('does not exist' ):
2296
+ interpid = _testinternalcapi .unused_interpreter_id ()
2297
+ self .assertFalse (
2298
+ exists (interpid ))
2299
+ with self .assertRaises (_interpreters .InterpreterNotFoundError ):
2300
+ is_linked (interpid )
2301
+ with self .assertRaises (_interpreters .InterpreterNotFoundError ):
2302
+ link (interpid )
2303
+ with self .assertRaises (_interpreters .InterpreterNotFoundError ):
2304
+ unlink (interpid )
2305
+ with self .assertRaises (_interpreters .InterpreterNotFoundError ):
2306
+ get_refcount (interpid )
2307
+ with self .assertRaises (_interpreters .InterpreterNotFoundError ):
2308
+ incref (interpid )
2309
+ with self .assertRaises (_interpreters .InterpreterNotFoundError ):
2310
+ decref (interpid )
2311
+
2312
+ with self .subTest ('destroyed' ):
2313
+ interpid = _interpreters .create ()
2314
+ _interpreters .destroy (interpid )
2315
+ self .assertFalse (
2316
+ exists (interpid ))
2317
+ with self .assertRaises (_interpreters .InterpreterNotFoundError ):
2318
+ is_linked (interpid )
2319
+ with self .assertRaises (_interpreters .InterpreterNotFoundError ):
2320
+ link (interpid )
2321
+ with self .assertRaises (_interpreters .InterpreterNotFoundError ):
2322
+ unlink (interpid )
2323
+ with self .assertRaises (_interpreters .InterpreterNotFoundError ):
2324
+ get_refcount (interpid )
2325
+ with self .assertRaises (_interpreters .InterpreterNotFoundError ):
2326
+ incref (interpid )
2327
+ with self .assertRaises (_interpreters .InterpreterNotFoundError ):
2328
+ decref (interpid )
2329
+
2330
+ # A new interpreter will start out not linked, with a refcount of 0.
2331
+ interpid = create ()
2332
+ self .assertFalse (
2333
+ is_linked (interpid ))
2312
2334
self .assertEqual (
2313
- _testinternalcapi .get_interpreter_refcount (id1 ),
2314
- 1 )
2315
-
2316
- # The interpreter isn't linked to ID objects, so it isn't destroyed.
2317
- del id2
2318
- self .assertEqual (
2319
- _testinternalcapi .get_interpreter_refcount (id1 ),
2320
- 0 )
2321
-
2322
- _testinternalcapi .link_interpreter_refcount (id1 )
2323
- self .assertEqual (
2324
- _testinternalcapi .get_interpreter_refcount (id1 ),
2325
- 0 )
2326
-
2327
- id3 = self .InterpreterID (id1 )
2328
- self .assertEqual (
2329
- _testinternalcapi .get_interpreter_refcount (id1 ),
2330
- 1 )
2331
-
2332
- # The interpreter is linked now so is destroyed.
2333
- del id3
2334
- with self .assertRaises (_interpreters .InterpreterNotFoundError ):
2335
- _testinternalcapi .get_interpreter_refcount (id1 )
2335
+ 0 , get_refcount (interpid ))
2336
+
2337
+ with self .subTest ('never linked' ):
2338
+ interpid = create ()
2339
+
2340
+ # Incref will not automatically link it.
2341
+ incref (interpid )
2342
+ self .assertFalse (
2343
+ is_linked (interpid ))
2344
+ self .assertEqual (
2345
+ 1 , get_refcount (interpid ))
2346
+
2347
+ # It isn't linked so it isn't destroyed.
2348
+ decref (interpid )
2349
+ self .assertTrue (
2350
+ exists (interpid ))
2351
+ self .assertFalse (
2352
+ is_linked (interpid ))
2353
+ self .assertEqual (
2354
+ 0 , get_refcount (interpid ))
2355
+
2356
+ with self .subTest ('linking/unlinking at refcount 0 does not destroy' ):
2357
+ interpid = create ()
2358
+
2359
+ link (interpid )
2360
+ self .assertTrue (
2361
+ exists (interpid ))
2362
+
2363
+ unlink (interpid )
2364
+ self .assertTrue (
2365
+ exists (interpid ))
2366
+
2367
+ with self .subTest ('link -> incref -> decref => destroyed' ):
2368
+ interpid = create ()
2369
+
2370
+ # Linking it will not change the refcount.
2371
+ link (interpid )
2372
+ self .assertTrue (
2373
+ is_linked (interpid ))
2374
+ self .assertEqual (
2375
+ 0 , get_refcount (interpid ))
2376
+
2377
+ # Decref with a refcount of 0 is not allowed.
2378
+ incref (interpid )
2379
+ self .assertEqual (
2380
+ 1 , get_refcount (interpid ))
2381
+
2382
+ # When linked, decref back to 0 destroys the interpreter.
2383
+ decref (interpid )
2384
+ self .assertFalse (
2385
+ exists (interpid ))
2386
+
2387
+ with self .subTest ('linked after incref' ):
2388
+ interpid = create ()
2389
+
2390
+ incref (interpid )
2391
+ self .assertEqual (
2392
+ 1 , get_refcount (interpid ))
2393
+
2394
+ # Linking it will not reset the refcount.
2395
+ link (interpid )
2396
+ self .assertEqual (
2397
+ 1 , get_refcount (interpid ))
2398
+
2399
+ with self .subTest ('decref to 0 after unlink does not destroy' ):
2400
+ interpid = create ()
2401
+
2402
+ link (interpid )
2403
+ self .assertTrue (
2404
+ is_linked (interpid ))
2405
+
2406
+ incref (interpid )
2407
+ self .assertEqual (
2408
+ 1 , get_refcount (interpid ))
2409
+
2410
+ # Unlinking it will not change the refcount.
2411
+ unlink (interpid )
2412
+ self .assertFalse (
2413
+ is_linked (interpid ))
2414
+ self .assertEqual (
2415
+ 1 , get_refcount (interpid ))
2416
+
2417
+ # When linked, decref back to 0 destroys the interpreter.
2418
+ decref (interpid )
2419
+ self .assertTrue (
2420
+ exists (interpid ))
2421
+ self .assertEqual (
2422
+ 0 , get_refcount (interpid ))
2336
2423
2337
2424
2338
2425
class BuiltinStaticTypesTests (unittest .TestCase ):
0 commit comments