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:
Eric Snow 2024-03-21 11:15:02 -06:00 committed by GitHub
parent abdd1f938f
commit 617158e078
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
18 changed files with 357 additions and 443 deletions

View file

@ -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

View file

@ -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_LookUpIDObject(PyObject *);
PyAPI_FUNC(int) _PyInterpreterState_IDInitref(PyInterpreterState *);
PyAPI_FUNC(int) _PyInterpreterState_IDIncref(PyInterpreterState *);
PyAPI_FUNC(void) _PyInterpreterState_IDDecref(PyInterpreterState *);

View file

@ -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 */

View file

@ -2207,132 +2207,264 @@ def test_module_state_shared_in_global(self):
@requires_subinterpreters
class InterpreterIDTests(unittest.TestCase):
InterpreterID = _testcapi.get_interpreterid_type()
def new_interpreter(self):
def ensure_destroyed(interpid):
def add_interp_cleanup(self, interpid):
def ensure_destroyed():
try:
_interpreters.destroy(interpid)
except _interpreters.InterpreterNotFoundError:
pass
self.addCleanup(ensure_destroyed)
def new_interpreter(self):
id = _interpreters.create()
self.addCleanup(lambda: ensure_destroyed(id))
self.add_interp_cleanup(id)
return id
def test_with_int(self):
id = self.InterpreterID(10, force=True)
def test_conversion_int(self):
convert = _testinternalcapi.normalize_interp_id
interpid = convert(10)
self.assertEqual(interpid, 10)
self.assertEqual(int(id), 10)
def test_coerce_id(self):
class Int(str):
def test_conversion_coerced(self):
convert = _testinternalcapi.normalize_interp_id
class MyInt(str):
def __index__(self):
return 10
interpid = convert(MyInt())
self.assertEqual(interpid, 10)
id = self.InterpreterID(Int(), force=True)
self.assertEqual(int(id), 10)
def test_conversion_from_interpreter(self):
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 [
object(),
10.0,
'10',
b'10',
]:
with self.subTest(badid):
with self.subTest(f'bad: {badid!r}'):
with self.assertRaises(TypeError):
self.InterpreterID(badid)
convert(badid)
badid = -1
with self.subTest(badid):
with self.subTest(f'bad: {badid!r}'):
with self.assertRaises(ValueError):
self.InterpreterID(badid)
convert(badid)
badid = 2**64
with self.subTest(badid):
with self.subTest(f'bad: {badid!r}'):
with self.assertRaises(OverflowError):
self.InterpreterID(badid)
convert(badid)
def test_exists(self):
id = self.new_interpreter()
with self.assertRaises(_interpreters.InterpreterNotFoundError):
self.InterpreterID(int(id) + 1) # unforced
def test_lookup_exists(self):
interpid = self.new_interpreter()
self.assertTrue(
_testinternalcapi.interpreter_exists(interpid))
def test_does_not_exist(self):
id = self.new_interpreter()
with self.assertRaises(_interpreters.InterpreterNotFoundError):
self.InterpreterID(int(id) + 1) # unforced
def test_lookup_does_not_exist(self):
interpid = _testinternalcapi.unused_interpreter_id()
self.assertFalse(
_testinternalcapi.interpreter_exists(interpid))
def test_destroyed(self):
id = _interpreters.create()
_interpreters.destroy(id)
with self.assertRaises(_interpreters.InterpreterNotFoundError):
self.InterpreterID(id) # unforced
def test_lookup_destroyed(self):
interpid = _interpreters.create()
_interpreters.destroy(interpid)
self.assertFalse(
_testinternalcapi.interpreter_exists(interpid))
def test_str(self):
id = self.InterpreterID(10, force=True)
self.assertEqual(str(id), '10')
def test_linked_lifecycle_does_not_exist(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
def test_repr(self):
id = self.InterpreterID(10, force=True)
self.assertEqual(repr(id), 'InterpreterID(10)')
with self.subTest('never existed'):
interpid = _testinternalcapi.unused_interpreter_id()
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):
id1 = self.new_interpreter()
id2 = self.InterpreterID(id1)
id3 = self.InterpreterID(
self.new_interpreter())
with self.subTest('destroyed'):
interpid = _interpreters.create()
_interpreters.destroy(interpid)
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)
self.assertTrue(id2 == id2) # identity
self.assertTrue(id2 == id1) # int-equivalent
self.assertTrue(id1 == id2) # reversed
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)
def test_linked_lifecycle_initial(self):
is_linked = _testinternalcapi.interpreter_refcount_linked
get_refcount = _testinternalcapi.get_interpreter_refcount
self.assertFalse(id2 != id2)
self.assertFalse(id2 != id1)
self.assertFalse(id1 != id2)
self.assertTrue(id2 != id3)
# A new interpreter will start out not linked, with a refcount of 0.
interpid = _testinternalcapi.new_interpreter()
self.add_interp_cleanup(interpid)
linked = is_linked(interpid)
refcount = get_refcount(interpid)
def test_linked_lifecycle(self):
id1 = _interpreters.create()
_testinternalcapi.unlink_interpreter_refcount(id1)
self.assertFalse(linked)
self.assertEqual(refcount, 0)
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(
_testinternalcapi.get_interpreter_refcount(id1),
0)
1, get_refcount(interpid))
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(
_testinternalcapi.get_interpreter_refcount(id1),
1)
0, get_refcount(interpid))
# The interpreter isn't linked to ID objects, so it isn't destroyed.
del id2
def test_linked_lifecycle_link_unlink(self):
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(
_testinternalcapi.get_interpreter_refcount(id1),
0)
0, get_refcount(interpid))
_testinternalcapi.link_interpreter_refcount(id1)
# Decref with a refcount of 0 is not allowed.
incref(interpid)
self.assertEqual(
_testinternalcapi.get_interpreter_refcount(id1),
0)
1, get_refcount(interpid))
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(
_testinternalcapi.get_interpreter_refcount(id1),
1)
1, get_refcount(interpid))
# The interpreter is linked now so is destroyed.
del id3
with self.assertRaises(_interpreters.InterpreterNotFoundError):
_testinternalcapi.get_interpreter_refcount(id1)
# Linking it will not reset the refcount.
link(interpid)
self.assertTrue(
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):

View file

@ -507,7 +507,6 @@ OBJECT_OBJS= \
Objects/floatobject.o \
Objects/frameobject.o \
Objects/funcobject.o \
Objects/interpreteridobject.o \
Objects/iterobject.o \
Objects/listobject.o \
Objects/longobject.o \
@ -1003,7 +1002,6 @@ PYTHON_HEADERS= \
$(srcdir)/Include/frameobject.h \
$(srcdir)/Include/genericaliasobject.h \
$(srcdir)/Include/import.h \
$(srcdir)/Include/interpreteridobject.h \
$(srcdir)/Include/intrcheck.h \
$(srcdir)/Include/iterobject.h \
$(srcdir)/Include/listobject.h \
@ -1077,7 +1075,6 @@ PYTHON_HEADERS= \
$(srcdir)/Include/cpython/genobject.h \
$(srcdir)/Include/cpython/import.h \
$(srcdir)/Include/cpython/initconfig.h \
$(srcdir)/Include/cpython/interpreteridobject.h \
$(srcdir)/Include/cpython/listobject.h \
$(srcdir)/Include/cpython/longintrepr.h \
$(srcdir)/Include/cpython/longobject.h \

View file

@ -19,3 +19,20 @@ clear_xid_class(PyTypeObject *cls)
return _PyCrossInterpreterData_UnregisterClass(cls);
}
#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

View file

@ -13,7 +13,6 @@
#include "_testcapi/parts.h"
#include "frameobject.h" // PyFrame_New()
#include "interpreteridobject.h" // PyInterpreterID_Type
#include "marshal.h" // PyMarshal_WriteLongToFile()
#include <float.h> // FLT_MAX
@ -1449,12 +1448,6 @@ run_in_subinterp(PyObject *self, PyObject *args)
return PyLong_FromLong(r);
}
static PyObject *
get_interpreterid_type(PyObject *self, PyObject *Py_UNUSED(ignored))
{
return Py_NewRef(&PyInterpreterID_Type);
}
static PyMethodDef ml;
static PyObject *
@ -3299,7 +3292,6 @@ static PyMethodDef TestMethods[] = {
{"crash_no_current_thread", crash_no_current_thread, METH_NOARGS},
{"test_current_tstate_matches", test_current_tstate_matches, METH_NOARGS},
{"run_in_subinterp", run_in_subinterp, METH_VARARGS},
{"get_interpreterid_type", get_interpreterid_type, METH_NOARGS},
{"create_cfunction", create_cfunction, METH_NOARGS},
{"call_in_temporary_c_thread", call_in_temporary_c_thread, METH_VARARGS,
PyDoc_STR("set_error_class(error_class) -> None")},

View file

@ -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 *
get_interpreter_refcount(PyObject *self, PyObject *idobj)
{
@ -1509,6 +1586,41 @@ unlink_interpreter_refcount(PyObject *self, PyObject *idobj)
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
_xid_capsule_destructor(PyObject *capsule)
@ -1749,9 +1861,16 @@ static PyMethodDef module_functions[] = {
{"run_in_subinterp_with_config",
_PyCFunction_CAST(run_in_subinterp_with_config),
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},
{"link_interpreter_refcount", link_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},
{"perf_trampoline_set_persist_after_fork", perf_trampoline_set_persist_after_fork, METH_VARARGS},
{"get_crossinterp_data", get_crossinterp_data, METH_VARARGS},

View file

@ -6,7 +6,6 @@
#endif
#include "Python.h"
#include "interpreteridobject.h"
#include "pycore_crossinterp.h" // struct _xid
#include "pycore_interp.h" // _PyInterpreterState_LookUpID()
@ -18,7 +17,9 @@
#endif
#define REGISTERS_HEAP_TYPES
#define RETURNS_INTERPID_OBJECT
#include "_interpreters_common.h"
#undef RETURNS_INTERPID_OBJECT
#undef REGISTERS_HEAP_TYPES
@ -2908,7 +2909,7 @@ channelsmod_list_interpreters(PyObject *self, PyObject *args, PyObject *kwds)
goto except;
}
if (res) {
interpid_obj = PyInterpreterState_GetIDObject(interp);
interpid_obj = get_interpid_obj(interp);
if (interpid_obj == NULL) {
goto except;
}

View file

@ -16,10 +16,11 @@
#include "pycore_pyerrors.h" // _Py_excinfo
#include "pycore_pystate.h" // _PyInterpreterState_SetRunningMain()
#include "interpreteridobject.h"
#include "marshal.h" // PyMarshal_ReadObjectFromString()
#define RETURNS_INTERPID_OBJECT
#include "_interpreters_common.h"
#undef RETURNS_INTERPID_OBJECT
#define MODULE_NAME _xxsubinterpreters
@ -38,20 +39,6 @@ _get_current_interp(void)
#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 *
_get_current_module(void)
{

View file

@ -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);
}

View file

@ -24,8 +24,6 @@
#include "pycore_typevarobject.h" // _PyTypeAlias_Type, _Py_initialize_generic
#include "pycore_unionobject.h" // _PyUnion_Type
#include "interpreteridobject.h" // _PyInterpreterID_Type
#ifdef Py_LIMITED_API
// Prevent recursive call _Py_IncRef() <=> Py_INCREF()
# error "Py_LIMITED_API macro must not be defined"
@ -2240,7 +2238,6 @@ static PyTypeObject* static_types[] = {
&PyGen_Type,
&PyGetSetDescr_Type,
&PyInstanceMethod_Type,
&PyInterpreterID_Type,
&PyListIter_Type,
&PyListRevIter_Type,
&PyList_Type,

View file

@ -142,7 +142,6 @@
<ClCompile Include="..\Objects\funcobject.c" />
<ClCompile Include="..\Objects\genericaliasobject.c" />
<ClCompile Include="..\Objects\genobject.c" />
<ClCompile Include="..\Objects\interpreteridobject.c" />
<ClCompile Include="..\Objects\iterobject.c" />
<ClCompile Include="..\Objects\listobject.c" />
<ClCompile Include="..\Objects\longobject.c" />

View file

@ -241,9 +241,6 @@
<ClCompile Include="..\Python\lock.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\Objects\interpreteridobject.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\PC\invalid_parameter_handler.c">
<Filter>Source Files</Filter>
</ClCompile>

View file

@ -154,7 +154,6 @@
<ClInclude Include="..\Include\cpython\genobject.h" />
<ClInclude Include="..\Include\cpython\import.h" />
<ClInclude Include="..\Include\cpython\initconfig.h" />
<ClInclude Include="..\Include\cpython\interpreteridobject.h" />
<ClInclude Include="..\Include\cpython\listobject.h" />
<ClInclude Include="..\Include\cpython\longintrepr.h" />
<ClInclude Include="..\Include\cpython\longobject.h" />
@ -303,7 +302,6 @@
<ClInclude Include="..\Include\internal\pycore_unicodeobject_generated.h" />
<ClInclude Include="..\Include\internal\pycore_warnings.h" />
<ClInclude Include="..\Include\internal\pycore_weakref.h" />
<ClInclude Include="..\Include\interpreteridobject.h" />
<ClInclude Include="..\Include\intrcheck.h" />
<ClInclude Include="..\Include\iterobject.h" />
<ClInclude Include="..\Include\listobject.h" />
@ -504,7 +502,6 @@
<ClCompile Include="..\Objects\funcobject.c" />
<ClCompile Include="..\Objects\genericaliasobject.c" />
<ClCompile Include="..\Objects\genobject.c" />
<ClCompile Include="..\Objects\interpreteridobject.c" />
<ClCompile Include="..\Objects\iterobject.c" />
<ClCompile Include="..\Objects\listobject.c" />
<ClCompile Include="..\Objects\longobject.c" />

View file

@ -330,9 +330,6 @@
<ClInclude Include="..\Include\pyhash.h">
<Filter>Include</Filter>
</ClInclude>
<ClInclude Include="..\Include\interpreteridobject.h">
<Filter>Include</Filter>
</ClInclude>
<ClInclude Include="..\Modules\hashtable.h">
<Filter>Modules</Filter>
</ClInclude>
@ -492,9 +489,6 @@
<ClInclude Include="..\Include\cpython\genobject.h">
<Filter>Include</Filter>
</ClInclude>
<ClInclude Include="..\Include\cpython\interpreteridobject.h">
<Filter>Include\cpython</Filter>
</ClInclude>
<ClInclude Include="..\Include\cpython\pythonrun.h">
<Filter>Include\cpython</Filter>
</ClInclude>
@ -1475,9 +1469,6 @@
<ClCompile Include="..\Objects\namespaceobject.c">
<Filter>Objects</Filter>
</ClCompile>
<ClCompile Include="..\Objects\interpreteridobject.c">
<Filter>Objects</Filter>
</ClCompile>
<ClCompile Include="..\Modules\_opcode.c">
<Filter>Modules</Filter>
</ClCompile>

View file

@ -2,7 +2,6 @@
/* Thread and interpreter state structures and their interfaces */
#include "Python.h"
#include "interpreteridobject.h" // PyInterpreterID_Type
#include "pycore_abstract.h" // _PyIndex_Check()
#include "pycore_ceval.h"
#include "pycore_code.h" // stats
@ -1131,10 +1130,6 @@ PyInterpreterState_GetDict(PyInterpreterState *interp)
int64_t
_PyInterpreterState_ObjectToID(PyObject *idobj)
{
if (PyObject_TypeCheck(idobj, &PyInterpreterID_Type)) {
return _PyInterpreterID_GetID(idobj);
}
if (!_PyIndex_Check(idobj)) {
PyErr_Format(PyExc_TypeError,
"interpreter ID must be an int, got %.100s",

View file

@ -54,7 +54,6 @@ Objects/genobject.c - _PyAsyncGenASend_Type -
Objects/genobject.c - _PyAsyncGenAThrow_Type -
Objects/genobject.c - _PyAsyncGenWrappedValue_Type -
Objects/genobject.c - _PyCoroWrapper_Type -
Objects/interpreteridobject.c - PyInterpreterID_Type -
Objects/iterobject.c - PyCallIter_Type -
Objects/iterobject.c - PySeqIter_Type -
Objects/iterobject.c - _PyAnextAwaitable_Type -

Can't render this file because it has a wrong number of fields in line 4.