@@ -2089,132 +2089,219 @@ def test_module_state_shared_in_global(self):
2089
2089
@requires_subinterpreters
2090
2090
class InterpreterIDTests (unittest .TestCase ):
2091
2091
2092
- InterpreterID = _testcapi .get_interpreterid_type ()
2092
+ # InterpreterID = _testcapi.get_interpreterid_type()
2093
2093
2094
- def new_interpreter (self ):
2095
- def ensure_destroyed (interpid ):
2094
+ def check_id (self , interpid , * , force = False ):
2095
+ if force :
2096
+ return
2097
+
2098
+ def add_interp_cleanup (self , interpid ):
2099
+ def ensure_destroyed ():
2096
2100
try :
2097
2101
_interpreters .destroy (interpid )
2098
2102
except _interpreters .InterpreterNotFoundError :
2099
2103
pass
2104
+ self .addCleanup (ensure_destroyed )
2105
+
2106
+ def new_interpreter (self ):
2100
2107
id = _interpreters .create ()
2101
- self .addCleanup ( lambda : ensure_destroyed ( id ) )
2108
+ self .add_interp_cleanup ( id )
2102
2109
return id
2103
2110
2104
- def test_with_int (self ):
2105
- id = self . InterpreterID ( 10 , force = True )
2111
+ def test_conversion (self ):
2112
+ convert = _testinternalcapi . normalize_interp_id
2106
2113
2107
- self .assertEqual (int (id ), 10 )
2114
+ with self .subTest ('int' ):
2115
+ interpid = convert (10 )
2116
+ self .assertEqual (interpid , 10 )
2108
2117
2109
- def test_coerce_id ( self ):
2110
- class Int (str ):
2111
- def __index__ (self ):
2112
- return 10
2118
+ with self . subTest ( 'coerced' ):
2119
+ class MyInt (str ):
2120
+ def __index__ (self ):
2121
+ return 10
2113
2122
2114
- id = self . InterpreterID ( Int (), force = True )
2115
- self .assertEqual (int ( id ) , 10 )
2123
+ interpid = convert ( MyInt () )
2124
+ self .assertEqual (interpid , 10 )
2116
2125
2117
- def test_bad_id (self ):
2118
2126
for badid in [
2119
2127
object (),
2120
2128
10.0 ,
2121
2129
'10' ,
2122
2130
b'10' ,
2123
2131
]:
2124
- with self .subTest (badid ):
2132
+ with self .subTest (f'bad: { badid } ' ):
2125
2133
with self .assertRaises (TypeError ):
2126
- self . InterpreterID (badid )
2134
+ convert (badid )
2127
2135
2128
2136
badid = - 1
2129
- with self .subTest (badid ):
2137
+ with self .subTest (f'bad: { badid } ' ):
2130
2138
with self .assertRaises (ValueError ):
2131
- self . InterpreterID (badid )
2139
+ convert (badid )
2132
2140
2133
2141
badid = 2 ** 64
2134
- with self .subTest (badid ):
2142
+ with self .subTest (f'bad: { badid } ' ):
2135
2143
with self .assertRaises (OverflowError ):
2136
- self . InterpreterID (badid )
2144
+ convert (badid )
2137
2145
2138
- def test_exists (self ):
2139
- id = self .new_interpreter ()
2140
- with self .assertRaises (_interpreters .InterpreterNotFoundError ):
2141
- self .InterpreterID (int (id ) + 1 ) # unforced
2146
+ def test_lookup (self ):
2147
+ with self .subTest ('exists' ):
2148
+ interpid = self .new_interpreter ()
2149
+ self .assertTrue (
2150
+ _testinternalcapi .interpreter_exists (interpid ))
2142
2151
2143
- def test_does_not_exist ( self ):
2144
- id = self . new_interpreter ()
2145
- with self .assertRaises ( _interpreters . InterpreterNotFoundError ):
2146
- self . InterpreterID ( int ( id ) + 1 ) # unforced
2152
+ with self . subTest ( 'does not exist' ):
2153
+ interpid = _testinternalcapi . unused_interpreter_id ()
2154
+ self .assertFalse (
2155
+ _testinternalcapi . interpreter_exists ( interpid ))
2147
2156
2148
- def test_destroyed (self ):
2149
- id = _interpreters .create ()
2150
- _interpreters .destroy (id )
2151
- with self .assertRaises (_interpreters .InterpreterNotFoundError ):
2152
- self .InterpreterID (id ) # unforced
2153
-
2154
- def test_str (self ):
2155
- id = self .InterpreterID (10 , force = True )
2156
- self .assertEqual (str (id ), '10' )
2157
-
2158
- def test_repr (self ):
2159
- id = self .InterpreterID (10 , force = True )
2160
- self .assertEqual (repr (id ), 'InterpreterID(10)' )
2161
-
2162
- def test_equality (self ):
2163
- id1 = self .new_interpreter ()
2164
- id2 = self .InterpreterID (id1 )
2165
- id3 = self .InterpreterID (
2166
- self .new_interpreter ())
2167
-
2168
- self .assertTrue (id2 == id2 ) # identity
2169
- self .assertTrue (id2 == id1 ) # int-equivalent
2170
- self .assertTrue (id1 == id2 ) # reversed
2171
- self .assertTrue (id2 == int (id2 ))
2172
- self .assertTrue (id2 == float (int (id2 )))
2173
- self .assertTrue (float (int (id2 )) == id2 )
2174
- self .assertFalse (id2 == float (int (id2 )) + 0.1 )
2175
- self .assertFalse (id2 == str (int (id2 )))
2176
- self .assertFalse (id2 == 2 ** 1000 )
2177
- self .assertFalse (id2 == float ('inf' ))
2178
- self .assertFalse (id2 == 'spam' )
2179
- self .assertFalse (id2 == id3 )
2180
-
2181
- self .assertFalse (id2 != id2 )
2182
- self .assertFalse (id2 != id1 )
2183
- self .assertFalse (id1 != id2 )
2184
- self .assertTrue (id2 != id3 )
2157
+ with self .subTest ('destroyed' ):
2158
+ interpid = _interpreters .create ()
2159
+ _interpreters .destroy (interpid )
2160
+ self .assertFalse (
2161
+ _testinternalcapi .interpreter_exists (interpid ))
2185
2162
2186
2163
def test_linked_lifecycle (self ):
2187
- id1 = _interpreters .create ()
2188
- _testinternalcapi .unlink_interpreter_refcount (id1 )
2189
- self .assertEqual (
2190
- _testinternalcapi .get_interpreter_refcount (id1 ),
2191
- 0 )
2192
-
2193
- id2 = self .InterpreterID (id1 )
2164
+ def create ():
2165
+ interpid = _testinternalcapi .new_interpreter ()
2166
+ self .add_interp_cleanup (interpid )
2167
+ return interpid
2168
+
2169
+ exists = _testinternalcapi .interpreter_exists
2170
+ is_linked = _testinternalcapi .interpreter_refcount_linked
2171
+ link = _testinternalcapi .link_interpreter_refcount
2172
+ unlink = _testinternalcapi .unlink_interpreter_refcount
2173
+ get_refcount = _testinternalcapi .get_interpreter_refcount
2174
+ incref = _testinternalcapi .interpreter_incref
2175
+ decref = _testinternalcapi .interpreter_decref
2176
+
2177
+ with self .subTest ('does not exist' ):
2178
+ interpid = _testinternalcapi .unused_interpreter_id ()
2179
+ self .assertFalse (
2180
+ exists (interpid ))
2181
+ with self .assertRaises (_interpreters .InterpreterNotFoundError ):
2182
+ is_linked (interpid )
2183
+ with self .assertRaises (_interpreters .InterpreterNotFoundError ):
2184
+ link (interpid )
2185
+ with self .assertRaises (_interpreters .InterpreterNotFoundError ):
2186
+ unlink (interpid )
2187
+ with self .assertRaises (_interpreters .InterpreterNotFoundError ):
2188
+ get_refcount (interpid )
2189
+ with self .assertRaises (_interpreters .InterpreterNotFoundError ):
2190
+ incref (interpid )
2191
+ with self .assertRaises (_interpreters .InterpreterNotFoundError ):
2192
+ decref (interpid )
2193
+
2194
+ with self .subTest ('destroyed' ):
2195
+ interpid = _interpreters .create ()
2196
+ _interpreters .destroy (interpid )
2197
+ self .assertFalse (
2198
+ exists (interpid ))
2199
+ with self .assertRaises (_interpreters .InterpreterNotFoundError ):
2200
+ is_linked (interpid )
2201
+ with self .assertRaises (_interpreters .InterpreterNotFoundError ):
2202
+ link (interpid )
2203
+ with self .assertRaises (_interpreters .InterpreterNotFoundError ):
2204
+ unlink (interpid )
2205
+ with self .assertRaises (_interpreters .InterpreterNotFoundError ):
2206
+ get_refcount (interpid )
2207
+ with self .assertRaises (_interpreters .InterpreterNotFoundError ):
2208
+ incref (interpid )
2209
+ with self .assertRaises (_interpreters .InterpreterNotFoundError ):
2210
+ decref (interpid )
2211
+
2212
+ # A new interpreter will start out not linked, with a refcount of 0.
2213
+ interpid = create ()
2214
+ self .assertFalse (
2215
+ is_linked (interpid ))
2194
2216
self .assertEqual (
2195
- _testinternalcapi .get_interpreter_refcount (id1 ),
2196
- 1 )
2197
-
2198
- # The interpreter isn't linked to ID objects, so it isn't destroyed.
2199
- del id2
2200
- self .assertEqual (
2201
- _testinternalcapi .get_interpreter_refcount (id1 ),
2202
- 0 )
2203
-
2204
- _testinternalcapi .link_interpreter_refcount (id1 )
2205
- self .assertEqual (
2206
- _testinternalcapi .get_interpreter_refcount (id1 ),
2207
- 0 )
2208
-
2209
- id3 = self .InterpreterID (id1 )
2210
- self .assertEqual (
2211
- _testinternalcapi .get_interpreter_refcount (id1 ),
2212
- 1 )
2213
-
2214
- # The interpreter is linked now so is destroyed.
2215
- del id3
2216
- with self .assertRaises (_interpreters .InterpreterNotFoundError ):
2217
- _testinternalcapi .get_interpreter_refcount (id1 )
2217
+ 0 , get_refcount (interpid ))
2218
+
2219
+ with self .subTest ('never linked' ):
2220
+ interpid = create ()
2221
+
2222
+ # Incref will not automatically link it.
2223
+ incref (interpid )
2224
+ self .assertFalse (
2225
+ is_linked (interpid ))
2226
+ self .assertEqual (
2227
+ 1 , get_refcount (interpid ))
2228
+
2229
+ # It isn't linked so it isn't destroyed.
2230
+ decref (interpid )
2231
+ self .assertTrue (
2232
+ exists (interpid ))
2233
+ self .assertFalse (
2234
+ is_linked (interpid ))
2235
+ self .assertEqual (
2236
+ 0 , get_refcount (interpid ))
2237
+
2238
+ with self .subTest ('linking/unlinking at refcount 0 does not destroy' ):
2239
+ interpid = create ()
2240
+
2241
+ link (interpid )
2242
+ self .assertTrue (
2243
+ exists (interpid ))
2244
+
2245
+ unlink (interpid )
2246
+ self .assertTrue (
2247
+ exists (interpid ))
2248
+
2249
+ with self .subTest ('link -> incref -> decref => destroyed' ):
2250
+ interpid = create ()
2251
+
2252
+ # Linking it will not change the refcount.
2253
+ link (interpid )
2254
+ self .assertTrue (
2255
+ is_linked (interpid ))
2256
+ self .assertEqual (
2257
+ 0 , get_refcount (interpid ))
2258
+
2259
+ # Decref with a refcount of 0 is not allowed.
2260
+ incref (interpid )
2261
+ self .assertEqual (
2262
+ 1 , get_refcount (interpid ))
2263
+
2264
+ # When linked, decref back to 0 destroys the interpreter.
2265
+ decref (interpid )
2266
+ self .assertFalse (
2267
+ exists (interpid ))
2268
+
2269
+ with self .subTest ('linked after incref' ):
2270
+ interpid = create ()
2271
+
2272
+ incref (interpid )
2273
+ self .assertEqual (
2274
+ 1 , get_refcount (interpid ))
2275
+
2276
+ # Linking it will not reset the refcount.
2277
+ link (interpid )
2278
+ self .assertEqual (
2279
+ 1 , get_refcount (interpid ))
2280
+
2281
+ with self .subTest ('decref to 0 after unlink does not destroy' ):
2282
+ interpid = create ()
2283
+
2284
+ link (interpid )
2285
+ self .assertTrue (
2286
+ is_linked (interpid ))
2287
+
2288
+ incref (interpid )
2289
+ self .assertEqual (
2290
+ 1 , get_refcount (interpid ))
2291
+
2292
+ # Unlinking it will not change the refcount.
2293
+ unlink (interpid )
2294
+ self .assertFalse (
2295
+ is_linked (interpid ))
2296
+ self .assertEqual (
2297
+ 1 , get_refcount (interpid ))
2298
+
2299
+ # When linked, decref back to 0 destroys the interpreter.
2300
+ decref (interpid )
2301
+ self .assertTrue (
2302
+ exists (interpid ))
2303
+ self .assertEqual (
2304
+ 0 , get_refcount (interpid ))
2218
2305
2219
2306
2220
2307
class BuiltinStaticTypesTests (unittest .TestCase ):
0 commit comments