mirror of https://github.com/python/cpython
gh-76785: Drop PyInterpreterID_Type (gh-117101)
I added it quite a while ago as a strategy for managing interpreter lifetimes relative to the PEP 554 (now 734) implementation. Relatively recently I refactored that implementation to no longer rely on InterpreterID objects. Thus now I'm removing it.
This commit is contained in:
parent
abdd1f938f
commit
617158e078
|
@ -1,14 +0,0 @@
|
||||||
#ifndef Py_CPYTHON_INTERPRETERIDOBJECT_H
|
|
||||||
# error "this header file must not be included directly"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Interpreter ID Object */
|
|
||||||
|
|
||||||
PyAPI_DATA(PyTypeObject) PyInterpreterID_Type;
|
|
||||||
|
|
||||||
PyAPI_FUNC(PyObject *) PyInterpreterID_New(int64_t);
|
|
||||||
PyAPI_FUNC(PyObject *) PyInterpreterState_GetIDObject(PyInterpreterState *);
|
|
||||||
|
|
||||||
#ifdef Py_BUILD_CORE
|
|
||||||
extern int64_t _PyInterpreterID_GetID(PyObject *);
|
|
||||||
#endif
|
|
|
@ -295,12 +295,11 @@ _PyInterpreterState_SetFinalizing(PyInterpreterState *interp, PyThreadState *tst
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
extern int64_t _PyInterpreterState_ObjectToID(PyObject *);
|
|
||||||
|
|
||||||
// Export for the _xxinterpchannels module.
|
// Exports for the _testinternalcapi module.
|
||||||
|
PyAPI_FUNC(int64_t) _PyInterpreterState_ObjectToID(PyObject *);
|
||||||
PyAPI_FUNC(PyInterpreterState *) _PyInterpreterState_LookUpID(int64_t);
|
PyAPI_FUNC(PyInterpreterState *) _PyInterpreterState_LookUpID(int64_t);
|
||||||
PyAPI_FUNC(PyInterpreterState *) _PyInterpreterState_LookUpIDObject(PyObject *);
|
PyAPI_FUNC(PyInterpreterState *) _PyInterpreterState_LookUpIDObject(PyObject *);
|
||||||
|
|
||||||
PyAPI_FUNC(int) _PyInterpreterState_IDInitref(PyInterpreterState *);
|
PyAPI_FUNC(int) _PyInterpreterState_IDInitref(PyInterpreterState *);
|
||||||
PyAPI_FUNC(int) _PyInterpreterState_IDIncref(PyInterpreterState *);
|
PyAPI_FUNC(int) _PyInterpreterState_IDIncref(PyInterpreterState *);
|
||||||
PyAPI_FUNC(void) _PyInterpreterState_IDDecref(PyInterpreterState *);
|
PyAPI_FUNC(void) _PyInterpreterState_IDDecref(PyInterpreterState *);
|
||||||
|
|
|
@ -1,17 +0,0 @@
|
||||||
#ifndef Py_INTERPRETERIDOBJECT_H
|
|
||||||
#define Py_INTERPRETERIDOBJECT_H
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef Py_LIMITED_API
|
|
||||||
# define Py_CPYTHON_INTERPRETERIDOBJECT_H
|
|
||||||
# include "cpython/interpreteridobject.h"
|
|
||||||
# undef Py_CPYTHON_INTERPRETERIDOBJECT_H
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#endif /* !Py_INTERPRETERIDOBJECT_H */
|
|
|
@ -2207,132 +2207,264 @@ class SubinterpreterTest(unittest.TestCase):
|
||||||
@requires_subinterpreters
|
@requires_subinterpreters
|
||||||
class InterpreterIDTests(unittest.TestCase):
|
class InterpreterIDTests(unittest.TestCase):
|
||||||
|
|
||||||
InterpreterID = _testcapi.get_interpreterid_type()
|
def add_interp_cleanup(self, interpid):
|
||||||
|
def ensure_destroyed():
|
||||||
def new_interpreter(self):
|
|
||||||
def ensure_destroyed(interpid):
|
|
||||||
try:
|
try:
|
||||||
_interpreters.destroy(interpid)
|
_interpreters.destroy(interpid)
|
||||||
except _interpreters.InterpreterNotFoundError:
|
except _interpreters.InterpreterNotFoundError:
|
||||||
pass
|
pass
|
||||||
|
self.addCleanup(ensure_destroyed)
|
||||||
|
|
||||||
|
def new_interpreter(self):
|
||||||
id = _interpreters.create()
|
id = _interpreters.create()
|
||||||
self.addCleanup(lambda: ensure_destroyed(id))
|
self.add_interp_cleanup(id)
|
||||||
return id
|
return id
|
||||||
|
|
||||||
def test_with_int(self):
|
def test_conversion_int(self):
|
||||||
id = self.InterpreterID(10, force=True)
|
convert = _testinternalcapi.normalize_interp_id
|
||||||
|
interpid = convert(10)
|
||||||
|
self.assertEqual(interpid, 10)
|
||||||
|
|
||||||
self.assertEqual(int(id), 10)
|
def test_conversion_coerced(self):
|
||||||
|
convert = _testinternalcapi.normalize_interp_id
|
||||||
def test_coerce_id(self):
|
class MyInt(str):
|
||||||
class Int(str):
|
|
||||||
def __index__(self):
|
def __index__(self):
|
||||||
return 10
|
return 10
|
||||||
|
interpid = convert(MyInt())
|
||||||
|
self.assertEqual(interpid, 10)
|
||||||
|
|
||||||
id = self.InterpreterID(Int(), force=True)
|
def test_conversion_from_interpreter(self):
|
||||||
self.assertEqual(int(id), 10)
|
convert = _testinternalcapi.normalize_interp_id
|
||||||
|
interpid = self.new_interpreter()
|
||||||
|
converted = convert(interpid)
|
||||||
|
self.assertEqual(converted, interpid)
|
||||||
|
|
||||||
|
def test_conversion_bad(self):
|
||||||
|
convert = _testinternalcapi.normalize_interp_id
|
||||||
|
|
||||||
def test_bad_id(self):
|
|
||||||
for badid in [
|
for badid in [
|
||||||
object(),
|
object(),
|
||||||
10.0,
|
10.0,
|
||||||
'10',
|
'10',
|
||||||
b'10',
|
b'10',
|
||||||
]:
|
]:
|
||||||
with self.subTest(badid):
|
with self.subTest(f'bad: {badid!r}'):
|
||||||
with self.assertRaises(TypeError):
|
with self.assertRaises(TypeError):
|
||||||
self.InterpreterID(badid)
|
convert(badid)
|
||||||
|
|
||||||
badid = -1
|
badid = -1
|
||||||
with self.subTest(badid):
|
with self.subTest(f'bad: {badid!r}'):
|
||||||
with self.assertRaises(ValueError):
|
with self.assertRaises(ValueError):
|
||||||
self.InterpreterID(badid)
|
convert(badid)
|
||||||
|
|
||||||
badid = 2**64
|
badid = 2**64
|
||||||
with self.subTest(badid):
|
with self.subTest(f'bad: {badid!r}'):
|
||||||
with self.assertRaises(OverflowError):
|
with self.assertRaises(OverflowError):
|
||||||
self.InterpreterID(badid)
|
convert(badid)
|
||||||
|
|
||||||
def test_exists(self):
|
def test_lookup_exists(self):
|
||||||
id = self.new_interpreter()
|
interpid = self.new_interpreter()
|
||||||
with self.assertRaises(_interpreters.InterpreterNotFoundError):
|
self.assertTrue(
|
||||||
self.InterpreterID(int(id) + 1) # unforced
|
_testinternalcapi.interpreter_exists(interpid))
|
||||||
|
|
||||||
def test_does_not_exist(self):
|
def test_lookup_does_not_exist(self):
|
||||||
id = self.new_interpreter()
|
interpid = _testinternalcapi.unused_interpreter_id()
|
||||||
with self.assertRaises(_interpreters.InterpreterNotFoundError):
|
self.assertFalse(
|
||||||
self.InterpreterID(int(id) + 1) # unforced
|
_testinternalcapi.interpreter_exists(interpid))
|
||||||
|
|
||||||
def test_destroyed(self):
|
def test_lookup_destroyed(self):
|
||||||
id = _interpreters.create()
|
interpid = _interpreters.create()
|
||||||
_interpreters.destroy(id)
|
_interpreters.destroy(interpid)
|
||||||
with self.assertRaises(_interpreters.InterpreterNotFoundError):
|
self.assertFalse(
|
||||||
self.InterpreterID(id) # unforced
|
_testinternalcapi.interpreter_exists(interpid))
|
||||||
|
|
||||||
def test_str(self):
|
def test_linked_lifecycle_does_not_exist(self):
|
||||||
id = self.InterpreterID(10, force=True)
|
exists = _testinternalcapi.interpreter_exists
|
||||||
self.assertEqual(str(id), '10')
|
is_linked = _testinternalcapi.interpreter_refcount_linked
|
||||||
|
link = _testinternalcapi.link_interpreter_refcount
|
||||||
|
unlink = _testinternalcapi.unlink_interpreter_refcount
|
||||||
|
get_refcount = _testinternalcapi.get_interpreter_refcount
|
||||||
|
incref = _testinternalcapi.interpreter_incref
|
||||||
|
decref = _testinternalcapi.interpreter_decref
|
||||||
|
|
||||||
def test_repr(self):
|
with self.subTest('never existed'):
|
||||||
id = self.InterpreterID(10, force=True)
|
interpid = _testinternalcapi.unused_interpreter_id()
|
||||||
self.assertEqual(repr(id), 'InterpreterID(10)')
|
self.assertFalse(
|
||||||
|
exists(interpid))
|
||||||
|
with self.assertRaises(_interpreters.InterpreterNotFoundError):
|
||||||
|
is_linked(interpid)
|
||||||
|
with self.assertRaises(_interpreters.InterpreterNotFoundError):
|
||||||
|
link(interpid)
|
||||||
|
with self.assertRaises(_interpreters.InterpreterNotFoundError):
|
||||||
|
unlink(interpid)
|
||||||
|
with self.assertRaises(_interpreters.InterpreterNotFoundError):
|
||||||
|
get_refcount(interpid)
|
||||||
|
with self.assertRaises(_interpreters.InterpreterNotFoundError):
|
||||||
|
incref(interpid)
|
||||||
|
with self.assertRaises(_interpreters.InterpreterNotFoundError):
|
||||||
|
decref(interpid)
|
||||||
|
|
||||||
def test_equality(self):
|
with self.subTest('destroyed'):
|
||||||
id1 = self.new_interpreter()
|
interpid = _interpreters.create()
|
||||||
id2 = self.InterpreterID(id1)
|
_interpreters.destroy(interpid)
|
||||||
id3 = self.InterpreterID(
|
self.assertFalse(
|
||||||
self.new_interpreter())
|
exists(interpid))
|
||||||
|
with self.assertRaises(_interpreters.InterpreterNotFoundError):
|
||||||
|
is_linked(interpid)
|
||||||
|
with self.assertRaises(_interpreters.InterpreterNotFoundError):
|
||||||
|
link(interpid)
|
||||||
|
with self.assertRaises(_interpreters.InterpreterNotFoundError):
|
||||||
|
unlink(interpid)
|
||||||
|
with self.assertRaises(_interpreters.InterpreterNotFoundError):
|
||||||
|
get_refcount(interpid)
|
||||||
|
with self.assertRaises(_interpreters.InterpreterNotFoundError):
|
||||||
|
incref(interpid)
|
||||||
|
with self.assertRaises(_interpreters.InterpreterNotFoundError):
|
||||||
|
decref(interpid)
|
||||||
|
|
||||||
self.assertTrue(id2 == id2) # identity
|
def test_linked_lifecycle_initial(self):
|
||||||
self.assertTrue(id2 == id1) # int-equivalent
|
is_linked = _testinternalcapi.interpreter_refcount_linked
|
||||||
self.assertTrue(id1 == id2) # reversed
|
get_refcount = _testinternalcapi.get_interpreter_refcount
|
||||||
self.assertTrue(id2 == int(id2))
|
|
||||||
self.assertTrue(id2 == float(int(id2)))
|
|
||||||
self.assertTrue(float(int(id2)) == id2)
|
|
||||||
self.assertFalse(id2 == float(int(id2)) + 0.1)
|
|
||||||
self.assertFalse(id2 == str(int(id2)))
|
|
||||||
self.assertFalse(id2 == 2**1000)
|
|
||||||
self.assertFalse(id2 == float('inf'))
|
|
||||||
self.assertFalse(id2 == 'spam')
|
|
||||||
self.assertFalse(id2 == id3)
|
|
||||||
|
|
||||||
self.assertFalse(id2 != id2)
|
# A new interpreter will start out not linked, with a refcount of 0.
|
||||||
self.assertFalse(id2 != id1)
|
interpid = _testinternalcapi.new_interpreter()
|
||||||
self.assertFalse(id1 != id2)
|
self.add_interp_cleanup(interpid)
|
||||||
self.assertTrue(id2 != id3)
|
linked = is_linked(interpid)
|
||||||
|
refcount = get_refcount(interpid)
|
||||||
|
|
||||||
def test_linked_lifecycle(self):
|
self.assertFalse(linked)
|
||||||
id1 = _interpreters.create()
|
self.assertEqual(refcount, 0)
|
||||||
_testinternalcapi.unlink_interpreter_refcount(id1)
|
|
||||||
|
def test_linked_lifecycle_never_linked(self):
|
||||||
|
exists = _testinternalcapi.interpreter_exists
|
||||||
|
is_linked = _testinternalcapi.interpreter_refcount_linked
|
||||||
|
get_refcount = _testinternalcapi.get_interpreter_refcount
|
||||||
|
incref = _testinternalcapi.interpreter_incref
|
||||||
|
decref = _testinternalcapi.interpreter_decref
|
||||||
|
|
||||||
|
interpid = _testinternalcapi.new_interpreter()
|
||||||
|
self.add_interp_cleanup(interpid)
|
||||||
|
|
||||||
|
# Incref will not automatically link it.
|
||||||
|
incref(interpid)
|
||||||
|
self.assertFalse(
|
||||||
|
is_linked(interpid))
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
_testinternalcapi.get_interpreter_refcount(id1),
|
1, get_refcount(interpid))
|
||||||
0)
|
|
||||||
|
|
||||||
id2 = self.InterpreterID(id1)
|
# It isn't linked so it isn't destroyed.
|
||||||
|
decref(interpid)
|
||||||
|
self.assertTrue(
|
||||||
|
exists(interpid))
|
||||||
|
self.assertFalse(
|
||||||
|
is_linked(interpid))
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
_testinternalcapi.get_interpreter_refcount(id1),
|
0, get_refcount(interpid))
|
||||||
1)
|
|
||||||
|
|
||||||
# The interpreter isn't linked to ID objects, so it isn't destroyed.
|
def test_linked_lifecycle_link_unlink(self):
|
||||||
del id2
|
exists = _testinternalcapi.interpreter_exists
|
||||||
|
is_linked = _testinternalcapi.interpreter_refcount_linked
|
||||||
|
link = _testinternalcapi.link_interpreter_refcount
|
||||||
|
unlink = _testinternalcapi.unlink_interpreter_refcount
|
||||||
|
|
||||||
|
interpid = _testinternalcapi.new_interpreter()
|
||||||
|
self.add_interp_cleanup(interpid)
|
||||||
|
|
||||||
|
# Linking at refcount 0 does not destroy the interpreter.
|
||||||
|
link(interpid)
|
||||||
|
self.assertTrue(
|
||||||
|
exists(interpid))
|
||||||
|
self.assertTrue(
|
||||||
|
is_linked(interpid))
|
||||||
|
|
||||||
|
# Unlinking at refcount 0 does not destroy the interpreter.
|
||||||
|
unlink(interpid)
|
||||||
|
self.assertTrue(
|
||||||
|
exists(interpid))
|
||||||
|
self.assertFalse(
|
||||||
|
is_linked(interpid))
|
||||||
|
|
||||||
|
def test_linked_lifecycle_link_incref_decref(self):
|
||||||
|
exists = _testinternalcapi.interpreter_exists
|
||||||
|
is_linked = _testinternalcapi.interpreter_refcount_linked
|
||||||
|
link = _testinternalcapi.link_interpreter_refcount
|
||||||
|
get_refcount = _testinternalcapi.get_interpreter_refcount
|
||||||
|
incref = _testinternalcapi.interpreter_incref
|
||||||
|
decref = _testinternalcapi.interpreter_decref
|
||||||
|
|
||||||
|
interpid = _testinternalcapi.new_interpreter()
|
||||||
|
self.add_interp_cleanup(interpid)
|
||||||
|
|
||||||
|
# Linking it will not change the refcount.
|
||||||
|
link(interpid)
|
||||||
|
self.assertTrue(
|
||||||
|
is_linked(interpid))
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
_testinternalcapi.get_interpreter_refcount(id1),
|
0, get_refcount(interpid))
|
||||||
0)
|
|
||||||
|
|
||||||
_testinternalcapi.link_interpreter_refcount(id1)
|
# Decref with a refcount of 0 is not allowed.
|
||||||
|
incref(interpid)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
_testinternalcapi.get_interpreter_refcount(id1),
|
1, get_refcount(interpid))
|
||||||
0)
|
|
||||||
|
|
||||||
id3 = self.InterpreterID(id1)
|
# When linked, decref back to 0 destroys the interpreter.
|
||||||
|
decref(interpid)
|
||||||
|
self.assertFalse(
|
||||||
|
exists(interpid))
|
||||||
|
|
||||||
|
def test_linked_lifecycle_incref_link(self):
|
||||||
|
is_linked = _testinternalcapi.interpreter_refcount_linked
|
||||||
|
link = _testinternalcapi.link_interpreter_refcount
|
||||||
|
get_refcount = _testinternalcapi.get_interpreter_refcount
|
||||||
|
incref = _testinternalcapi.interpreter_incref
|
||||||
|
|
||||||
|
interpid = _testinternalcapi.new_interpreter()
|
||||||
|
self.add_interp_cleanup(interpid)
|
||||||
|
|
||||||
|
incref(interpid)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
_testinternalcapi.get_interpreter_refcount(id1),
|
1, get_refcount(interpid))
|
||||||
1)
|
|
||||||
|
|
||||||
# The interpreter is linked now so is destroyed.
|
# Linking it will not reset the refcount.
|
||||||
del id3
|
link(interpid)
|
||||||
with self.assertRaises(_interpreters.InterpreterNotFoundError):
|
self.assertTrue(
|
||||||
_testinternalcapi.get_interpreter_refcount(id1)
|
is_linked(interpid))
|
||||||
|
self.assertEqual(
|
||||||
|
1, get_refcount(interpid))
|
||||||
|
|
||||||
|
def test_linked_lifecycle_link_incref_unlink_decref(self):
|
||||||
|
exists = _testinternalcapi.interpreter_exists
|
||||||
|
is_linked = _testinternalcapi.interpreter_refcount_linked
|
||||||
|
link = _testinternalcapi.link_interpreter_refcount
|
||||||
|
unlink = _testinternalcapi.unlink_interpreter_refcount
|
||||||
|
get_refcount = _testinternalcapi.get_interpreter_refcount
|
||||||
|
incref = _testinternalcapi.interpreter_incref
|
||||||
|
decref = _testinternalcapi.interpreter_decref
|
||||||
|
|
||||||
|
interpid = _testinternalcapi.new_interpreter()
|
||||||
|
self.add_interp_cleanup(interpid)
|
||||||
|
|
||||||
|
link(interpid)
|
||||||
|
self.assertTrue(
|
||||||
|
is_linked(interpid))
|
||||||
|
|
||||||
|
incref(interpid)
|
||||||
|
self.assertEqual(
|
||||||
|
1, get_refcount(interpid))
|
||||||
|
|
||||||
|
# Unlinking it will not change the refcount.
|
||||||
|
unlink(interpid)
|
||||||
|
self.assertFalse(
|
||||||
|
is_linked(interpid))
|
||||||
|
self.assertEqual(
|
||||||
|
1, get_refcount(interpid))
|
||||||
|
|
||||||
|
# Unlinked: decref back to 0 does not destroys the interpreter.
|
||||||
|
decref(interpid)
|
||||||
|
self.assertTrue(
|
||||||
|
exists(interpid))
|
||||||
|
self.assertEqual(
|
||||||
|
0, get_refcount(interpid))
|
||||||
|
|
||||||
|
|
||||||
class BuiltinStaticTypesTests(unittest.TestCase):
|
class BuiltinStaticTypesTests(unittest.TestCase):
|
||||||
|
|
|
@ -507,7 +507,6 @@ OBJECT_OBJS= \
|
||||||
Objects/floatobject.o \
|
Objects/floatobject.o \
|
||||||
Objects/frameobject.o \
|
Objects/frameobject.o \
|
||||||
Objects/funcobject.o \
|
Objects/funcobject.o \
|
||||||
Objects/interpreteridobject.o \
|
|
||||||
Objects/iterobject.o \
|
Objects/iterobject.o \
|
||||||
Objects/listobject.o \
|
Objects/listobject.o \
|
||||||
Objects/longobject.o \
|
Objects/longobject.o \
|
||||||
|
@ -1003,7 +1002,6 @@ PYTHON_HEADERS= \
|
||||||
$(srcdir)/Include/frameobject.h \
|
$(srcdir)/Include/frameobject.h \
|
||||||
$(srcdir)/Include/genericaliasobject.h \
|
$(srcdir)/Include/genericaliasobject.h \
|
||||||
$(srcdir)/Include/import.h \
|
$(srcdir)/Include/import.h \
|
||||||
$(srcdir)/Include/interpreteridobject.h \
|
|
||||||
$(srcdir)/Include/intrcheck.h \
|
$(srcdir)/Include/intrcheck.h \
|
||||||
$(srcdir)/Include/iterobject.h \
|
$(srcdir)/Include/iterobject.h \
|
||||||
$(srcdir)/Include/listobject.h \
|
$(srcdir)/Include/listobject.h \
|
||||||
|
@ -1077,7 +1075,6 @@ PYTHON_HEADERS= \
|
||||||
$(srcdir)/Include/cpython/genobject.h \
|
$(srcdir)/Include/cpython/genobject.h \
|
||||||
$(srcdir)/Include/cpython/import.h \
|
$(srcdir)/Include/cpython/import.h \
|
||||||
$(srcdir)/Include/cpython/initconfig.h \
|
$(srcdir)/Include/cpython/initconfig.h \
|
||||||
$(srcdir)/Include/cpython/interpreteridobject.h \
|
|
||||||
$(srcdir)/Include/cpython/listobject.h \
|
$(srcdir)/Include/cpython/listobject.h \
|
||||||
$(srcdir)/Include/cpython/longintrepr.h \
|
$(srcdir)/Include/cpython/longintrepr.h \
|
||||||
$(srcdir)/Include/cpython/longobject.h \
|
$(srcdir)/Include/cpython/longobject.h \
|
||||||
|
|
|
@ -19,3 +19,20 @@ clear_xid_class(PyTypeObject *cls)
|
||||||
return _PyCrossInterpreterData_UnregisterClass(cls);
|
return _PyCrossInterpreterData_UnregisterClass(cls);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef RETURNS_INTERPID_OBJECT
|
||||||
|
static PyObject *
|
||||||
|
get_interpid_obj(PyInterpreterState *interp)
|
||||||
|
{
|
||||||
|
if (_PyInterpreterState_IDInitref(interp) != 0) {
|
||||||
|
return NULL;
|
||||||
|
};
|
||||||
|
int64_t id = PyInterpreterState_GetID(interp);
|
||||||
|
if (id < 0) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
assert(id < LLONG_MAX);
|
||||||
|
return PyLong_FromLongLong(id);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
|
@ -13,7 +13,6 @@
|
||||||
#include "_testcapi/parts.h"
|
#include "_testcapi/parts.h"
|
||||||
|
|
||||||
#include "frameobject.h" // PyFrame_New()
|
#include "frameobject.h" // PyFrame_New()
|
||||||
#include "interpreteridobject.h" // PyInterpreterID_Type
|
|
||||||
#include "marshal.h" // PyMarshal_WriteLongToFile()
|
#include "marshal.h" // PyMarshal_WriteLongToFile()
|
||||||
|
|
||||||
#include <float.h> // FLT_MAX
|
#include <float.h> // FLT_MAX
|
||||||
|
@ -1449,12 +1448,6 @@ run_in_subinterp(PyObject *self, PyObject *args)
|
||||||
return PyLong_FromLong(r);
|
return PyLong_FromLong(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
|
||||||
get_interpreterid_type(PyObject *self, PyObject *Py_UNUSED(ignored))
|
|
||||||
{
|
|
||||||
return Py_NewRef(&PyInterpreterID_Type);
|
|
||||||
}
|
|
||||||
|
|
||||||
static PyMethodDef ml;
|
static PyMethodDef ml;
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
|
@ -3299,7 +3292,6 @@ static PyMethodDef TestMethods[] = {
|
||||||
{"crash_no_current_thread", crash_no_current_thread, METH_NOARGS},
|
{"crash_no_current_thread", crash_no_current_thread, METH_NOARGS},
|
||||||
{"test_current_tstate_matches", test_current_tstate_matches, METH_NOARGS},
|
{"test_current_tstate_matches", test_current_tstate_matches, METH_NOARGS},
|
||||||
{"run_in_subinterp", run_in_subinterp, METH_VARARGS},
|
{"run_in_subinterp", run_in_subinterp, METH_VARARGS},
|
||||||
{"get_interpreterid_type", get_interpreterid_type, METH_NOARGS},
|
|
||||||
{"create_cfunction", create_cfunction, METH_NOARGS},
|
{"create_cfunction", create_cfunction, METH_NOARGS},
|
||||||
{"call_in_temporary_c_thread", call_in_temporary_c_thread, METH_VARARGS,
|
{"call_in_temporary_c_thread", call_in_temporary_c_thread, METH_VARARGS,
|
||||||
PyDoc_STR("set_error_class(error_class) -> None")},
|
PyDoc_STR("set_error_class(error_class) -> None")},
|
||||||
|
|
|
@ -1475,6 +1475,83 @@ run_in_subinterp_with_config(PyObject *self, PyObject *args, PyObject *kwargs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
normalize_interp_id(PyObject *self, PyObject *idobj)
|
||||||
|
{
|
||||||
|
int64_t interpid = _PyInterpreterState_ObjectToID(idobj);
|
||||||
|
if (interpid < 0) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return PyLong_FromLongLong(interpid);
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
unused_interpreter_id(PyObject *self, PyObject *Py_UNUSED(ignored))
|
||||||
|
{
|
||||||
|
int64_t interpid = INT64_MAX;
|
||||||
|
assert(interpid > _PyRuntime.interpreters.next_id);
|
||||||
|
return PyLong_FromLongLong(interpid);
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
new_interpreter(PyObject *self, PyObject *Py_UNUSED(ignored))
|
||||||
|
{
|
||||||
|
// Unlike _interpreters.create(), we do not automatically link
|
||||||
|
// the interpreter to its refcount.
|
||||||
|
PyThreadState *save_tstate = PyThreadState_Get();
|
||||||
|
const PyInterpreterConfig config = \
|
||||||
|
(PyInterpreterConfig)_PyInterpreterConfig_INIT;
|
||||||
|
PyThreadState *tstate = NULL;
|
||||||
|
PyStatus status = Py_NewInterpreterFromConfig(&tstate, &config);
|
||||||
|
PyThreadState_Swap(save_tstate);
|
||||||
|
if (PyStatus_Exception(status)) {
|
||||||
|
_PyErr_SetFromPyStatus(status);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
PyInterpreterState *interp = PyThreadState_GetInterpreter(tstate);
|
||||||
|
|
||||||
|
if (_PyInterpreterState_IDInitref(interp) < 0) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t interpid = PyInterpreterState_GetID(interp);
|
||||||
|
if (interpid < 0) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
PyObject *idobj = PyLong_FromLongLong(interpid);
|
||||||
|
if (idobj == NULL) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
PyThreadState_Swap(tstate);
|
||||||
|
PyThreadState_Clear(tstate);
|
||||||
|
PyThreadState_Swap(save_tstate);
|
||||||
|
PyThreadState_Delete(tstate);
|
||||||
|
|
||||||
|
return idobj;
|
||||||
|
|
||||||
|
error:
|
||||||
|
save_tstate = PyThreadState_Swap(tstate);
|
||||||
|
Py_EndInterpreter(tstate);
|
||||||
|
PyThreadState_Swap(save_tstate);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
interpreter_exists(PyObject *self, PyObject *idobj)
|
||||||
|
{
|
||||||
|
PyInterpreterState *interp = _PyInterpreterState_LookUpIDObject(idobj);
|
||||||
|
if (interp == NULL) {
|
||||||
|
if (PyErr_ExceptionMatches(PyExc_InterpreterNotFoundError)) {
|
||||||
|
PyErr_Clear();
|
||||||
|
Py_RETURN_FALSE;
|
||||||
|
}
|
||||||
|
assert(PyErr_Occurred());
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
Py_RETURN_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
get_interpreter_refcount(PyObject *self, PyObject *idobj)
|
get_interpreter_refcount(PyObject *self, PyObject *idobj)
|
||||||
{
|
{
|
||||||
|
@ -1509,6 +1586,41 @@ unlink_interpreter_refcount(PyObject *self, PyObject *idobj)
|
||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
interpreter_refcount_linked(PyObject *self, PyObject *idobj)
|
||||||
|
{
|
||||||
|
PyInterpreterState *interp = _PyInterpreterState_LookUpIDObject(idobj);
|
||||||
|
if (interp == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (_PyInterpreterState_RequiresIDRef(interp)) {
|
||||||
|
Py_RETURN_TRUE;
|
||||||
|
}
|
||||||
|
Py_RETURN_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
interpreter_incref(PyObject *self, PyObject *idobj)
|
||||||
|
{
|
||||||
|
PyInterpreterState *interp = _PyInterpreterState_LookUpIDObject(idobj);
|
||||||
|
if (interp == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
_PyInterpreterState_IDIncref(interp);
|
||||||
|
Py_RETURN_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
interpreter_decref(PyObject *self, PyObject *idobj)
|
||||||
|
{
|
||||||
|
PyInterpreterState *interp = _PyInterpreterState_LookUpIDObject(idobj);
|
||||||
|
if (interp == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
_PyInterpreterState_IDDecref(interp);
|
||||||
|
Py_RETURN_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_xid_capsule_destructor(PyObject *capsule)
|
_xid_capsule_destructor(PyObject *capsule)
|
||||||
|
@ -1749,9 +1861,16 @@ static PyMethodDef module_functions[] = {
|
||||||
{"run_in_subinterp_with_config",
|
{"run_in_subinterp_with_config",
|
||||||
_PyCFunction_CAST(run_in_subinterp_with_config),
|
_PyCFunction_CAST(run_in_subinterp_with_config),
|
||||||
METH_VARARGS | METH_KEYWORDS},
|
METH_VARARGS | METH_KEYWORDS},
|
||||||
|
{"normalize_interp_id", normalize_interp_id, METH_O},
|
||||||
|
{"unused_interpreter_id", unused_interpreter_id, METH_NOARGS},
|
||||||
|
{"new_interpreter", new_interpreter, METH_NOARGS},
|
||||||
|
{"interpreter_exists", interpreter_exists, METH_O},
|
||||||
{"get_interpreter_refcount", get_interpreter_refcount, METH_O},
|
{"get_interpreter_refcount", get_interpreter_refcount, METH_O},
|
||||||
{"link_interpreter_refcount", link_interpreter_refcount, METH_O},
|
{"link_interpreter_refcount", link_interpreter_refcount, METH_O},
|
||||||
{"unlink_interpreter_refcount", unlink_interpreter_refcount, METH_O},
|
{"unlink_interpreter_refcount", unlink_interpreter_refcount, METH_O},
|
||||||
|
{"interpreter_refcount_linked", interpreter_refcount_linked, METH_O},
|
||||||
|
{"interpreter_incref", interpreter_incref, METH_O},
|
||||||
|
{"interpreter_decref", interpreter_decref, METH_O},
|
||||||
{"compile_perf_trampoline_entry", compile_perf_trampoline_entry, METH_VARARGS},
|
{"compile_perf_trampoline_entry", compile_perf_trampoline_entry, METH_VARARGS},
|
||||||
{"perf_trampoline_set_persist_after_fork", perf_trampoline_set_persist_after_fork, METH_VARARGS},
|
{"perf_trampoline_set_persist_after_fork", perf_trampoline_set_persist_after_fork, METH_VARARGS},
|
||||||
{"get_crossinterp_data", get_crossinterp_data, METH_VARARGS},
|
{"get_crossinterp_data", get_crossinterp_data, METH_VARARGS},
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "Python.h"
|
#include "Python.h"
|
||||||
#include "interpreteridobject.h"
|
|
||||||
#include "pycore_crossinterp.h" // struct _xid
|
#include "pycore_crossinterp.h" // struct _xid
|
||||||
#include "pycore_interp.h" // _PyInterpreterState_LookUpID()
|
#include "pycore_interp.h" // _PyInterpreterState_LookUpID()
|
||||||
|
|
||||||
|
@ -18,7 +17,9 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define REGISTERS_HEAP_TYPES
|
#define REGISTERS_HEAP_TYPES
|
||||||
|
#define RETURNS_INTERPID_OBJECT
|
||||||
#include "_interpreters_common.h"
|
#include "_interpreters_common.h"
|
||||||
|
#undef RETURNS_INTERPID_OBJECT
|
||||||
#undef REGISTERS_HEAP_TYPES
|
#undef REGISTERS_HEAP_TYPES
|
||||||
|
|
||||||
|
|
||||||
|
@ -2908,7 +2909,7 @@ channelsmod_list_interpreters(PyObject *self, PyObject *args, PyObject *kwds)
|
||||||
goto except;
|
goto except;
|
||||||
}
|
}
|
||||||
if (res) {
|
if (res) {
|
||||||
interpid_obj = PyInterpreterState_GetIDObject(interp);
|
interpid_obj = get_interpid_obj(interp);
|
||||||
if (interpid_obj == NULL) {
|
if (interpid_obj == NULL) {
|
||||||
goto except;
|
goto except;
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,10 +16,11 @@
|
||||||
#include "pycore_pyerrors.h" // _Py_excinfo
|
#include "pycore_pyerrors.h" // _Py_excinfo
|
||||||
#include "pycore_pystate.h" // _PyInterpreterState_SetRunningMain()
|
#include "pycore_pystate.h" // _PyInterpreterState_SetRunningMain()
|
||||||
|
|
||||||
#include "interpreteridobject.h"
|
|
||||||
#include "marshal.h" // PyMarshal_ReadObjectFromString()
|
#include "marshal.h" // PyMarshal_ReadObjectFromString()
|
||||||
|
|
||||||
|
#define RETURNS_INTERPID_OBJECT
|
||||||
#include "_interpreters_common.h"
|
#include "_interpreters_common.h"
|
||||||
|
#undef RETURNS_INTERPID_OBJECT
|
||||||
|
|
||||||
|
|
||||||
#define MODULE_NAME _xxsubinterpreters
|
#define MODULE_NAME _xxsubinterpreters
|
||||||
|
@ -38,20 +39,6 @@ _get_current_interp(void)
|
||||||
#define look_up_interp _PyInterpreterState_LookUpIDObject
|
#define look_up_interp _PyInterpreterState_LookUpIDObject
|
||||||
|
|
||||||
|
|
||||||
static PyObject *
|
|
||||||
get_interpid_obj(PyInterpreterState *interp)
|
|
||||||
{
|
|
||||||
if (_PyInterpreterState_IDInitref(interp) != 0) {
|
|
||||||
return NULL;
|
|
||||||
};
|
|
||||||
int64_t id = PyInterpreterState_GetID(interp);
|
|
||||||
if (id < 0) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
assert(id < LLONG_MAX);
|
|
||||||
return PyLong_FromLongLong(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
_get_current_module(void)
|
_get_current_module(void)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,274 +0,0 @@
|
||||||
/* InterpreterID object */
|
|
||||||
|
|
||||||
#include "Python.h"
|
|
||||||
#include "pycore_interp.h" // _PyInterpreterState_LookUpID()
|
|
||||||
#include "interpreteridobject.h"
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct interpid {
|
|
||||||
PyObject_HEAD
|
|
||||||
int64_t id;
|
|
||||||
} interpid;
|
|
||||||
|
|
||||||
int64_t
|
|
||||||
_PyInterpreterID_GetID(PyObject *self)
|
|
||||||
{
|
|
||||||
if (!PyObject_TypeCheck(self, &PyInterpreterID_Type)) {
|
|
||||||
PyErr_Format(PyExc_TypeError,
|
|
||||||
"expected an InterpreterID, got %R",
|
|
||||||
self);
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
}
|
|
||||||
int64_t id = ((interpid *)self)->id;
|
|
||||||
assert(id >= 0);
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
static interpid *
|
|
||||||
newinterpid(PyTypeObject *cls, int64_t id, int force)
|
|
||||||
{
|
|
||||||
PyInterpreterState *interp = _PyInterpreterState_LookUpID(id);
|
|
||||||
if (interp == NULL) {
|
|
||||||
if (force) {
|
|
||||||
PyErr_Clear();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (interp != NULL) {
|
|
||||||
if (_PyInterpreterState_IDIncref(interp) < 0) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
interpid *self = PyObject_New(interpid, cls);
|
|
||||||
if (self == NULL) {
|
|
||||||
if (interp != NULL) {
|
|
||||||
_PyInterpreterState_IDDecref(interp);
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
self->id = id;
|
|
||||||
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
static PyObject *
|
|
||||||
interpid_new(PyTypeObject *cls, PyObject *args, PyObject *kwds)
|
|
||||||
{
|
|
||||||
static char *kwlist[] = {"id", "force", NULL};
|
|
||||||
PyObject *idobj;
|
|
||||||
int force = 0;
|
|
||||||
if (!PyArg_ParseTupleAndKeywords(args, kwds,
|
|
||||||
"O|$p:InterpreterID.__init__", kwlist,
|
|
||||||
&idobj, &force)) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
int64_t id = _PyInterpreterState_ObjectToID(idobj);
|
|
||||||
if (id < 0) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (PyObject *)newinterpid(cls, id, force);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
interpid_dealloc(PyObject *v)
|
|
||||||
{
|
|
||||||
int64_t id = ((interpid *)v)->id;
|
|
||||||
PyInterpreterState *interp = _PyInterpreterState_LookUpID(id);
|
|
||||||
if (interp != NULL) {
|
|
||||||
_PyInterpreterState_IDDecref(interp);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// already deleted
|
|
||||||
PyErr_Clear();
|
|
||||||
}
|
|
||||||
Py_TYPE(v)->tp_free(v);
|
|
||||||
}
|
|
||||||
|
|
||||||
static PyObject *
|
|
||||||
interpid_repr(PyObject *self)
|
|
||||||
{
|
|
||||||
PyTypeObject *type = Py_TYPE(self);
|
|
||||||
const char *name = _PyType_Name(type);
|
|
||||||
interpid *id = (interpid *)self;
|
|
||||||
return PyUnicode_FromFormat("%s(%" PRId64 ")", name, id->id);
|
|
||||||
}
|
|
||||||
|
|
||||||
static PyObject *
|
|
||||||
interpid_str(PyObject *self)
|
|
||||||
{
|
|
||||||
interpid *id = (interpid *)self;
|
|
||||||
return PyUnicode_FromFormat("%" PRId64 "", id->id);
|
|
||||||
}
|
|
||||||
|
|
||||||
static PyObject *
|
|
||||||
interpid_int(PyObject *self)
|
|
||||||
{
|
|
||||||
interpid *id = (interpid *)self;
|
|
||||||
return PyLong_FromLongLong(id->id);
|
|
||||||
}
|
|
||||||
|
|
||||||
static PyNumberMethods interpid_as_number = {
|
|
||||||
0, /* nb_add */
|
|
||||||
0, /* nb_subtract */
|
|
||||||
0, /* nb_multiply */
|
|
||||||
0, /* nb_remainder */
|
|
||||||
0, /* nb_divmod */
|
|
||||||
0, /* nb_power */
|
|
||||||
0, /* nb_negative */
|
|
||||||
0, /* nb_positive */
|
|
||||||
0, /* nb_absolute */
|
|
||||||
0, /* nb_bool */
|
|
||||||
0, /* nb_invert */
|
|
||||||
0, /* nb_lshift */
|
|
||||||
0, /* nb_rshift */
|
|
||||||
0, /* nb_and */
|
|
||||||
0, /* nb_xor */
|
|
||||||
0, /* nb_or */
|
|
||||||
(unaryfunc)interpid_int, /* nb_int */
|
|
||||||
0, /* nb_reserved */
|
|
||||||
0, /* nb_float */
|
|
||||||
|
|
||||||
0, /* nb_inplace_add */
|
|
||||||
0, /* nb_inplace_subtract */
|
|
||||||
0, /* nb_inplace_multiply */
|
|
||||||
0, /* nb_inplace_remainder */
|
|
||||||
0, /* nb_inplace_power */
|
|
||||||
0, /* nb_inplace_lshift */
|
|
||||||
0, /* nb_inplace_rshift */
|
|
||||||
0, /* nb_inplace_and */
|
|
||||||
0, /* nb_inplace_xor */
|
|
||||||
0, /* nb_inplace_or */
|
|
||||||
|
|
||||||
0, /* nb_floor_divide */
|
|
||||||
0, /* nb_true_divide */
|
|
||||||
0, /* nb_inplace_floor_divide */
|
|
||||||
0, /* nb_inplace_true_divide */
|
|
||||||
|
|
||||||
(unaryfunc)interpid_int, /* nb_index */
|
|
||||||
};
|
|
||||||
|
|
||||||
static Py_hash_t
|
|
||||||
interpid_hash(PyObject *self)
|
|
||||||
{
|
|
||||||
interpid *id = (interpid *)self;
|
|
||||||
PyObject *obj = PyLong_FromLongLong(id->id);
|
|
||||||
if (obj == NULL) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
Py_hash_t hash = PyObject_Hash(obj);
|
|
||||||
Py_DECREF(obj);
|
|
||||||
return hash;
|
|
||||||
}
|
|
||||||
|
|
||||||
static PyObject *
|
|
||||||
interpid_richcompare(PyObject *self, PyObject *other, int op)
|
|
||||||
{
|
|
||||||
if (op != Py_EQ && op != Py_NE) {
|
|
||||||
Py_RETURN_NOTIMPLEMENTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!PyObject_TypeCheck(self, &PyInterpreterID_Type)) {
|
|
||||||
Py_RETURN_NOTIMPLEMENTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
interpid *id = (interpid *)self;
|
|
||||||
int equal;
|
|
||||||
if (PyObject_TypeCheck(other, &PyInterpreterID_Type)) {
|
|
||||||
interpid *otherid = (interpid *)other;
|
|
||||||
equal = (id->id == otherid->id);
|
|
||||||
}
|
|
||||||
else if (PyLong_CheckExact(other)) {
|
|
||||||
/* Fast path */
|
|
||||||
int overflow;
|
|
||||||
long long otherid = PyLong_AsLongLongAndOverflow(other, &overflow);
|
|
||||||
if (otherid == -1 && PyErr_Occurred()) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
equal = !overflow && (otherid >= 0) && (id->id == otherid);
|
|
||||||
}
|
|
||||||
else if (PyNumber_Check(other)) {
|
|
||||||
PyObject *pyid = PyLong_FromLongLong(id->id);
|
|
||||||
if (pyid == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
PyObject *res = PyObject_RichCompare(pyid, other, op);
|
|
||||||
Py_DECREF(pyid);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Py_RETURN_NOTIMPLEMENTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((op == Py_EQ && equal) || (op == Py_NE && !equal)) {
|
|
||||||
Py_RETURN_TRUE;
|
|
||||||
}
|
|
||||||
Py_RETURN_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
PyDoc_STRVAR(interpid_doc,
|
|
||||||
"A interpreter ID identifies a interpreter and may be used as an int.");
|
|
||||||
|
|
||||||
PyTypeObject PyInterpreterID_Type = {
|
|
||||||
PyVarObject_HEAD_INIT(&PyType_Type, 0)
|
|
||||||
"InterpreterID", /* tp_name */
|
|
||||||
sizeof(interpid), /* tp_basicsize */
|
|
||||||
0, /* tp_itemsize */
|
|
||||||
(destructor)interpid_dealloc, /* tp_dealloc */
|
|
||||||
0, /* tp_vectorcall_offset */
|
|
||||||
0, /* tp_getattr */
|
|
||||||
0, /* tp_setattr */
|
|
||||||
0, /* tp_as_async */
|
|
||||||
(reprfunc)interpid_repr, /* tp_repr */
|
|
||||||
&interpid_as_number, /* tp_as_number */
|
|
||||||
0, /* tp_as_sequence */
|
|
||||||
0, /* tp_as_mapping */
|
|
||||||
interpid_hash, /* tp_hash */
|
|
||||||
0, /* tp_call */
|
|
||||||
(reprfunc)interpid_str, /* tp_str */
|
|
||||||
0, /* tp_getattro */
|
|
||||||
0, /* tp_setattro */
|
|
||||||
0, /* tp_as_buffer */
|
|
||||||
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
|
|
||||||
interpid_doc, /* tp_doc */
|
|
||||||
0, /* tp_traverse */
|
|
||||||
0, /* tp_clear */
|
|
||||||
interpid_richcompare, /* tp_richcompare */
|
|
||||||
0, /* tp_weaklistoffset */
|
|
||||||
0, /* tp_iter */
|
|
||||||
0, /* tp_iternext */
|
|
||||||
0, /* tp_methods */
|
|
||||||
0, /* tp_members */
|
|
||||||
0, /* tp_getset */
|
|
||||||
0, /* tp_base */
|
|
||||||
0, /* tp_dict */
|
|
||||||
0, /* tp_descr_get */
|
|
||||||
0, /* tp_descr_set */
|
|
||||||
0, /* tp_dictoffset */
|
|
||||||
0, /* tp_init */
|
|
||||||
0, /* tp_alloc */
|
|
||||||
interpid_new, /* tp_new */
|
|
||||||
};
|
|
||||||
|
|
||||||
PyObject *PyInterpreterID_New(int64_t id)
|
|
||||||
{
|
|
||||||
return (PyObject *)newinterpid(&PyInterpreterID_Type, id, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
PyObject *
|
|
||||||
PyInterpreterState_GetIDObject(PyInterpreterState *interp)
|
|
||||||
{
|
|
||||||
if (_PyInterpreterState_IDInitref(interp) != 0) {
|
|
||||||
return NULL;
|
|
||||||
};
|
|
||||||
int64_t id = PyInterpreterState_GetID(interp);
|
|
||||||
if (id < 0) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
return (PyObject *)newinterpid(&PyInterpreterID_Type, id, 0);
|
|
||||||
}
|
|
|
@ -24,8 +24,6 @@
|
||||||
#include "pycore_typevarobject.h" // _PyTypeAlias_Type, _Py_initialize_generic
|
#include "pycore_typevarobject.h" // _PyTypeAlias_Type, _Py_initialize_generic
|
||||||
#include "pycore_unionobject.h" // _PyUnion_Type
|
#include "pycore_unionobject.h" // _PyUnion_Type
|
||||||
|
|
||||||
#include "interpreteridobject.h" // _PyInterpreterID_Type
|
|
||||||
|
|
||||||
#ifdef Py_LIMITED_API
|
#ifdef Py_LIMITED_API
|
||||||
// Prevent recursive call _Py_IncRef() <=> Py_INCREF()
|
// Prevent recursive call _Py_IncRef() <=> Py_INCREF()
|
||||||
# error "Py_LIMITED_API macro must not be defined"
|
# error "Py_LIMITED_API macro must not be defined"
|
||||||
|
@ -2240,7 +2238,6 @@ static PyTypeObject* static_types[] = {
|
||||||
&PyGen_Type,
|
&PyGen_Type,
|
||||||
&PyGetSetDescr_Type,
|
&PyGetSetDescr_Type,
|
||||||
&PyInstanceMethod_Type,
|
&PyInstanceMethod_Type,
|
||||||
&PyInterpreterID_Type,
|
|
||||||
&PyListIter_Type,
|
&PyListIter_Type,
|
||||||
&PyListRevIter_Type,
|
&PyListRevIter_Type,
|
||||||
&PyList_Type,
|
&PyList_Type,
|
||||||
|
|
|
@ -142,7 +142,6 @@
|
||||||
<ClCompile Include="..\Objects\funcobject.c" />
|
<ClCompile Include="..\Objects\funcobject.c" />
|
||||||
<ClCompile Include="..\Objects\genericaliasobject.c" />
|
<ClCompile Include="..\Objects\genericaliasobject.c" />
|
||||||
<ClCompile Include="..\Objects\genobject.c" />
|
<ClCompile Include="..\Objects\genobject.c" />
|
||||||
<ClCompile Include="..\Objects\interpreteridobject.c" />
|
|
||||||
<ClCompile Include="..\Objects\iterobject.c" />
|
<ClCompile Include="..\Objects\iterobject.c" />
|
||||||
<ClCompile Include="..\Objects\listobject.c" />
|
<ClCompile Include="..\Objects\listobject.c" />
|
||||||
<ClCompile Include="..\Objects\longobject.c" />
|
<ClCompile Include="..\Objects\longobject.c" />
|
||||||
|
|
|
@ -241,9 +241,6 @@
|
||||||
<ClCompile Include="..\Python\lock.c">
|
<ClCompile Include="..\Python\lock.c">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\Objects\interpreteridobject.c">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\PC\invalid_parameter_handler.c">
|
<ClCompile Include="..\PC\invalid_parameter_handler.c">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
|
|
@ -154,7 +154,6 @@
|
||||||
<ClInclude Include="..\Include\cpython\genobject.h" />
|
<ClInclude Include="..\Include\cpython\genobject.h" />
|
||||||
<ClInclude Include="..\Include\cpython\import.h" />
|
<ClInclude Include="..\Include\cpython\import.h" />
|
||||||
<ClInclude Include="..\Include\cpython\initconfig.h" />
|
<ClInclude Include="..\Include\cpython\initconfig.h" />
|
||||||
<ClInclude Include="..\Include\cpython\interpreteridobject.h" />
|
|
||||||
<ClInclude Include="..\Include\cpython\listobject.h" />
|
<ClInclude Include="..\Include\cpython\listobject.h" />
|
||||||
<ClInclude Include="..\Include\cpython\longintrepr.h" />
|
<ClInclude Include="..\Include\cpython\longintrepr.h" />
|
||||||
<ClInclude Include="..\Include\cpython\longobject.h" />
|
<ClInclude Include="..\Include\cpython\longobject.h" />
|
||||||
|
@ -303,7 +302,6 @@
|
||||||
<ClInclude Include="..\Include\internal\pycore_unicodeobject_generated.h" />
|
<ClInclude Include="..\Include\internal\pycore_unicodeobject_generated.h" />
|
||||||
<ClInclude Include="..\Include\internal\pycore_warnings.h" />
|
<ClInclude Include="..\Include\internal\pycore_warnings.h" />
|
||||||
<ClInclude Include="..\Include\internal\pycore_weakref.h" />
|
<ClInclude Include="..\Include\internal\pycore_weakref.h" />
|
||||||
<ClInclude Include="..\Include\interpreteridobject.h" />
|
|
||||||
<ClInclude Include="..\Include\intrcheck.h" />
|
<ClInclude Include="..\Include\intrcheck.h" />
|
||||||
<ClInclude Include="..\Include\iterobject.h" />
|
<ClInclude Include="..\Include\iterobject.h" />
|
||||||
<ClInclude Include="..\Include\listobject.h" />
|
<ClInclude Include="..\Include\listobject.h" />
|
||||||
|
@ -504,7 +502,6 @@
|
||||||
<ClCompile Include="..\Objects\funcobject.c" />
|
<ClCompile Include="..\Objects\funcobject.c" />
|
||||||
<ClCompile Include="..\Objects\genericaliasobject.c" />
|
<ClCompile Include="..\Objects\genericaliasobject.c" />
|
||||||
<ClCompile Include="..\Objects\genobject.c" />
|
<ClCompile Include="..\Objects\genobject.c" />
|
||||||
<ClCompile Include="..\Objects\interpreteridobject.c" />
|
|
||||||
<ClCompile Include="..\Objects\iterobject.c" />
|
<ClCompile Include="..\Objects\iterobject.c" />
|
||||||
<ClCompile Include="..\Objects\listobject.c" />
|
<ClCompile Include="..\Objects\listobject.c" />
|
||||||
<ClCompile Include="..\Objects\longobject.c" />
|
<ClCompile Include="..\Objects\longobject.c" />
|
||||||
|
|
|
@ -330,9 +330,6 @@
|
||||||
<ClInclude Include="..\Include\pyhash.h">
|
<ClInclude Include="..\Include\pyhash.h">
|
||||||
<Filter>Include</Filter>
|
<Filter>Include</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="..\Include\interpreteridobject.h">
|
|
||||||
<Filter>Include</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="..\Modules\hashtable.h">
|
<ClInclude Include="..\Modules\hashtable.h">
|
||||||
<Filter>Modules</Filter>
|
<Filter>Modules</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
@ -492,9 +489,6 @@
|
||||||
<ClInclude Include="..\Include\cpython\genobject.h">
|
<ClInclude Include="..\Include\cpython\genobject.h">
|
||||||
<Filter>Include</Filter>
|
<Filter>Include</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="..\Include\cpython\interpreteridobject.h">
|
|
||||||
<Filter>Include\cpython</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="..\Include\cpython\pythonrun.h">
|
<ClInclude Include="..\Include\cpython\pythonrun.h">
|
||||||
<Filter>Include\cpython</Filter>
|
<Filter>Include\cpython</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
@ -1475,9 +1469,6 @@
|
||||||
<ClCompile Include="..\Objects\namespaceobject.c">
|
<ClCompile Include="..\Objects\namespaceobject.c">
|
||||||
<Filter>Objects</Filter>
|
<Filter>Objects</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\Objects\interpreteridobject.c">
|
|
||||||
<Filter>Objects</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\Modules\_opcode.c">
|
<ClCompile Include="..\Modules\_opcode.c">
|
||||||
<Filter>Modules</Filter>
|
<Filter>Modules</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
/* Thread and interpreter state structures and their interfaces */
|
/* Thread and interpreter state structures and their interfaces */
|
||||||
|
|
||||||
#include "Python.h"
|
#include "Python.h"
|
||||||
#include "interpreteridobject.h" // PyInterpreterID_Type
|
|
||||||
#include "pycore_abstract.h" // _PyIndex_Check()
|
#include "pycore_abstract.h" // _PyIndex_Check()
|
||||||
#include "pycore_ceval.h"
|
#include "pycore_ceval.h"
|
||||||
#include "pycore_code.h" // stats
|
#include "pycore_code.h" // stats
|
||||||
|
@ -1131,10 +1130,6 @@ PyInterpreterState_GetDict(PyInterpreterState *interp)
|
||||||
int64_t
|
int64_t
|
||||||
_PyInterpreterState_ObjectToID(PyObject *idobj)
|
_PyInterpreterState_ObjectToID(PyObject *idobj)
|
||||||
{
|
{
|
||||||
if (PyObject_TypeCheck(idobj, &PyInterpreterID_Type)) {
|
|
||||||
return _PyInterpreterID_GetID(idobj);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!_PyIndex_Check(idobj)) {
|
if (!_PyIndex_Check(idobj)) {
|
||||||
PyErr_Format(PyExc_TypeError,
|
PyErr_Format(PyExc_TypeError,
|
||||||
"interpreter ID must be an int, got %.100s",
|
"interpreter ID must be an int, got %.100s",
|
||||||
|
|
|
@ -54,7 +54,6 @@ Objects/genobject.c - _PyAsyncGenASend_Type -
|
||||||
Objects/genobject.c - _PyAsyncGenAThrow_Type -
|
Objects/genobject.c - _PyAsyncGenAThrow_Type -
|
||||||
Objects/genobject.c - _PyAsyncGenWrappedValue_Type -
|
Objects/genobject.c - _PyAsyncGenWrappedValue_Type -
|
||||||
Objects/genobject.c - _PyCoroWrapper_Type -
|
Objects/genobject.c - _PyCoroWrapper_Type -
|
||||||
Objects/interpreteridobject.c - PyInterpreterID_Type -
|
|
||||||
Objects/iterobject.c - PyCallIter_Type -
|
Objects/iterobject.c - PyCallIter_Type -
|
||||||
Objects/iterobject.c - PySeqIter_Type -
|
Objects/iterobject.c - PySeqIter_Type -
|
||||||
Objects/iterobject.c - _PyAnextAwaitable_Type -
|
Objects/iterobject.c - _PyAnextAwaitable_Type -
|
||||||
|
|
Can't render this file because it has a wrong number of fields in line 4.
|
Loading…
Reference in New Issue