mirror of
https://github.com/panda3d/panda3d.git
synced 2025-09-29 16:20:11 -04:00
interrogate: clean up py_panda.h a bit more
Inching towards reducing code in py_panda and eventually having no Python-specific code in interrogatedb anymore.
This commit is contained in:
parent
bc596797a3
commit
3cc88cd304
@ -2536,7 +2536,7 @@ write_module_class(ostream &out, Object *obj) {
|
||||
}
|
||||
}
|
||||
|
||||
if (NeedsARichCompareFunction(obj->_itype)) {
|
||||
if (NeedsARichCompareFunction(obj->_itype) || slots.count("tp_compare")) {
|
||||
out << "//////////////////\n";
|
||||
out << "// A rich comparison function\n";
|
||||
out << "// " << ClassName << "\n";
|
||||
@ -2547,7 +2547,6 @@ write_module_class(ostream &out, Object *obj) {
|
||||
out << " return nullptr;\n";
|
||||
out << " }\n\n";
|
||||
|
||||
out << " switch (op) {\n";
|
||||
for (fi = obj->_methods.begin(); fi != obj->_methods.end(); ++fi) {
|
||||
std::set<FunctionRemap*> remaps;
|
||||
Function *func = (*fi);
|
||||
@ -2564,21 +2563,28 @@ write_module_class(ostream &out, Object *obj) {
|
||||
}
|
||||
}
|
||||
const string &fname = func->_ifunc.get_name();
|
||||
const char *op_type;
|
||||
if (fname == "operator <") {
|
||||
out << " case Py_LT:\n";
|
||||
op_type = "Py_LT";
|
||||
} else if (fname == "operator <=") {
|
||||
out << " case Py_LE:\n";
|
||||
op_type = "Py_LE";
|
||||
} else if (fname == "operator ==") {
|
||||
out << " case Py_EQ:\n";
|
||||
op_type = "Py_EQ";
|
||||
} else if (fname == "operator !=") {
|
||||
out << " case Py_NE:\n";
|
||||
op_type = "Py_NE";
|
||||
} else if (fname == "operator >") {
|
||||
out << " case Py_GT:\n";
|
||||
op_type = "Py_GT";
|
||||
} else if (fname == "operator >=") {
|
||||
out << " case Py_GE:\n";
|
||||
op_type = "Py_GE";
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
if (!has_local_richcompare) {
|
||||
out << " switch (op) {\n";
|
||||
has_local_richcompare = true;
|
||||
}
|
||||
out << " case " << op_type << ":\n";
|
||||
|
||||
out << " {\n";
|
||||
|
||||
string expected_params;
|
||||
@ -2587,14 +2593,15 @@ write_module_class(ostream &out, Object *obj) {
|
||||
|
||||
out << " break;\n";
|
||||
out << " }\n";
|
||||
has_local_richcompare = true;
|
||||
}
|
||||
|
||||
out << " }\n\n";
|
||||
|
||||
out << " if (_PyErr_OCCURRED()) {\n";
|
||||
out << " PyErr_Clear();\n";
|
||||
out << " }\n\n";
|
||||
if (has_local_richcompare) {
|
||||
// End of switch block
|
||||
out << " }\n\n";
|
||||
out << " if (_PyErr_OCCURRED()) {\n";
|
||||
out << " PyErr_Clear();\n";
|
||||
out << " }\n\n";
|
||||
}
|
||||
|
||||
if (slots.count("tp_compare")) {
|
||||
// A lot of Panda code depends on comparisons being done via the
|
||||
@ -2624,6 +2631,7 @@ write_module_class(ostream &out, Object *obj) {
|
||||
out << " case Py_GE:\n";
|
||||
out << " return PyBool_FromLong(cmpval >= 0);\n";
|
||||
out << " }\n";
|
||||
has_local_richcompare = true;
|
||||
}
|
||||
|
||||
out << " Py_INCREF(Py_NotImplemented);\n";
|
||||
@ -2850,7 +2858,7 @@ write_module_class(ostream &out, Object *obj) {
|
||||
out << "#else\n";
|
||||
if (has_hash_compare) {
|
||||
write_function_slot(out, 4, slots, "tp_compare",
|
||||
"&DTOOL_PyObject_ComparePointers");
|
||||
"&DtoolInstance_ComparePointers");
|
||||
} else {
|
||||
out << " nullptr, // tp_compare\n";
|
||||
}
|
||||
@ -2880,7 +2888,7 @@ write_module_class(ostream &out, Object *obj) {
|
||||
|
||||
// hashfunc tp_hash;
|
||||
if (has_hash_compare) {
|
||||
write_function_slot(out, 4, slots, "tp_hash", "&DTOOL_PyObject_HashPointer");
|
||||
write_function_slot(out, 4, slots, "tp_hash", "&DtoolInstance_HashPointer");
|
||||
} else {
|
||||
out << " nullptr, // tp_hash\n";
|
||||
}
|
||||
@ -2951,7 +2959,7 @@ write_module_class(ostream &out, Object *obj) {
|
||||
} else if (has_hash_compare) {
|
||||
// All hashable types need to be comparable.
|
||||
out << "#if PY_MAJOR_VERSION >= 3\n";
|
||||
out << " &DTOOL_PyObject_RichCompare,\n";
|
||||
out << " &DtoolInstance_RichComparePointers,\n";
|
||||
out << "#else\n";
|
||||
out << " nullptr, // tp_richcompare\n";
|
||||
out << "#endif\n";
|
||||
|
@ -79,13 +79,13 @@ EXPORT_THIS Dtool_PyTypedObject Dtool_DTOOL_SUPER_BASE = {
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
nullptr, // tp_compare
|
||||
#else
|
||||
&DTOOL_PyObject_ComparePointers,
|
||||
&DtoolInstance_ComparePointers,
|
||||
#endif
|
||||
nullptr, // tp_repr
|
||||
nullptr, // tp_as_number
|
||||
nullptr, // tp_as_sequence
|
||||
nullptr, // tp_as_mapping
|
||||
&DTOOL_PyObject_HashPointer,
|
||||
&DtoolInstance_HashPointer,
|
||||
nullptr, // tp_call
|
||||
nullptr, // tp_str
|
||||
PyObject_GenericGetAttr,
|
||||
@ -96,7 +96,7 @@ EXPORT_THIS Dtool_PyTypedObject Dtool_DTOOL_SUPER_BASE = {
|
||||
nullptr, // tp_traverse
|
||||
nullptr, // tp_clear
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
&DTOOL_PyObject_RichCompare,
|
||||
&DtoolInstance_RichComparePointers,
|
||||
#else
|
||||
nullptr, // tp_richcompare
|
||||
#endif
|
||||
|
@ -16,8 +16,6 @@
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
|
||||
PyTupleObject Dtool_EmptyTuple = {PyVarObject_HEAD_INIT(nullptr, 0)};
|
||||
|
||||
#if PY_MAJOR_VERSION < 3
|
||||
/**
|
||||
* Given a long or int, returns a size_t, or raises an OverflowError if it is
|
||||
|
@ -138,11 +138,29 @@ typedef long Py_hash_t;
|
||||
|
||||
/* Python 3.6 */
|
||||
|
||||
// Used to implement _PyObject_CallNoArg
|
||||
extern EXPCL_INTERROGATEDB PyTupleObject Dtool_EmptyTuple;
|
||||
|
||||
#ifndef _PyObject_CallNoArg
|
||||
# define _PyObject_CallNoArg(func) PyObject_Call((func), (PyObject *)&Dtool_EmptyTuple, nullptr)
|
||||
INLINE PyObject *_PyObject_CallNoArg(PyObject *func) {
|
||||
static PyTupleObject empty_tuple = {PyVarObject_HEAD_INIT(nullptr, 0)};
|
||||
#ifdef Py_TRACE_REFS
|
||||
_Py_AddToAllObjects((PyObject *)&empty_tuple, 0);
|
||||
#endif
|
||||
return PyObject_Call(func, (PyObject *)&empty_tuple, nullptr);
|
||||
}
|
||||
# define _PyObject_CallNoArg _PyObject_CallNoArg
|
||||
#endif
|
||||
|
||||
#ifndef _PyObject_FastCall
|
||||
INLINE PyObject *_PyObject_FastCall(PyObject *func, PyObject **args, Py_ssize_t nargs) {
|
||||
PyObject *tuple = PyTuple_New(nargs);
|
||||
for (Py_ssize_t i = 0; i < nargs; ++i) {
|
||||
PyTuple_SET_ITEM(tuple, i, args[i]);
|
||||
Py_INCREF(args[i]);
|
||||
}
|
||||
PyObject *result = PyObject_Call(func, tuple, nullptr);
|
||||
Py_DECREF(tuple);
|
||||
return result;
|
||||
}
|
||||
# define _PyObject_FastCall _PyObject_FastCall
|
||||
#endif
|
||||
|
||||
// Python versions before 3.6 didn't require longlong support to be enabled.
|
||||
@ -161,6 +179,21 @@ extern EXPCL_INTERROGATEDB PyTupleObject Dtool_EmptyTuple;
|
||||
# define PyDict_GET_SIZE(mp) (((PyDictObject *)mp)->ma_used)
|
||||
#endif
|
||||
|
||||
#ifndef Py_RETURN_RICHCOMPARE
|
||||
# define Py_RETURN_RICHCOMPARE(val1, val2, op) \
|
||||
do { \
|
||||
switch (op) { \
|
||||
NODEFAULT \
|
||||
case Py_EQ: if ((val1) == (val2)) Py_RETURN_TRUE; Py_RETURN_FALSE; \
|
||||
case Py_NE: if ((val1) != (val2)) Py_RETURN_TRUE; Py_RETURN_FALSE; \
|
||||
case Py_LT: if ((val1) < (val2)) Py_RETURN_TRUE; Py_RETURN_FALSE; \
|
||||
case Py_GT: if ((val1) > (val2)) Py_RETURN_TRUE; Py_RETURN_FALSE; \
|
||||
case Py_LE: if ((val1) <= (val2)) Py_RETURN_TRUE; Py_RETURN_FALSE; \
|
||||
case Py_GE: if ((val1) >= (val2)) Py_RETURN_TRUE; Py_RETURN_FALSE; \
|
||||
} \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
/* Other Python implementations */
|
||||
|
||||
// _PyErr_OCCURRED is an undocumented macro version of PyErr_Occurred.
|
||||
|
@ -62,6 +62,37 @@ DtoolInstance_GetPointer(PyObject *self, T *&into, Dtool_PyTypedObject &target_c
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to create a hash from a wrapped Python object.
|
||||
*/
|
||||
INLINE Py_hash_t DtoolInstance_HashPointer(PyObject *self) {
|
||||
if (self != nullptr && DtoolInstance_Check(self)) {
|
||||
return (Py_hash_t)(intptr_t)DtoolInstance_VOID_PTR(self);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Python 2-style comparison function that compares objects by pointer.
|
||||
*/
|
||||
INLINE int DtoolInstance_ComparePointers(PyObject *v1, PyObject *v2) {
|
||||
void *v1_this = DtoolInstance_Check(v1) ? DtoolInstance_VOID_PTR(v1) : nullptr;
|
||||
void *v2_this = DtoolInstance_Check(v2) ? DtoolInstance_VOID_PTR(v2) : nullptr;
|
||||
if (v1_this != nullptr && v2_this != nullptr) {
|
||||
return (v1_this > v2_this) - (v1_this < v2_this);
|
||||
} else {
|
||||
return (v1 > v2) - (v1 < v2);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Rich comparison function that compares objects by pointer.
|
||||
*/
|
||||
INLINE PyObject *DtoolInstance_RichComparePointers(PyObject *v1, PyObject *v2, int op) {
|
||||
int cmpval = DtoolInstance_ComparePointers(v1, v2);
|
||||
Py_RETURN_RICHCOMPARE(cmpval, 0, op);
|
||||
}
|
||||
|
||||
/**
|
||||
* These functions wrap a pointer for a class that defines get_type_handle().
|
||||
*/
|
||||
|
@ -143,13 +143,6 @@ DTOOL_Call_GetPointerThisClass(PyObject *self, Dtool_PyTypedObject *classdef,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void *DTOOL_Call_GetPointerThis(PyObject *self) {
|
||||
if (self != nullptr && DtoolInstance_Check(self)) {
|
||||
return DtoolInstance_VOID_PTR(self);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is similar to a PyErr_Occurred() check, except that it also checks
|
||||
* Notify to see if an assertion has occurred. If that is the case, then it
|
||||
@ -588,10 +581,6 @@ PyObject *Dtool_PyModuleInitHelper(LibraryDef *defs[], const char *modulename) {
|
||||
return Dtool_Raise_TypeError("PyType_Ready(Dtool_StaticProperty_Type)");
|
||||
}
|
||||
|
||||
#ifdef Py_TRACE_REFS
|
||||
_Py_AddToAllObjects((PyObject *)&Dtool_EmptyTuple, 0);
|
||||
#endif
|
||||
|
||||
// Initialize the base class of everything.
|
||||
Dtool_PyModuleClassInit_DTOOL_SUPER_BASE(nullptr);
|
||||
}
|
||||
@ -734,127 +723,6 @@ PyObject *Dtool_AddToDictionary(PyObject *self1, PyObject *args) {
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
Py_hash_t DTOOL_PyObject_HashPointer(PyObject *self) {
|
||||
if (self != nullptr && DtoolInstance_Check(self)) {
|
||||
return (Py_hash_t)(intptr_t)DtoolInstance_VOID_PTR(self);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Compare v to w. Return
|
||||
-1 if v < w or exception (PyErr_Occurred() true in latter case).
|
||||
0 if v == w.
|
||||
1 if v > w.
|
||||
XXX The docs (C API manual) say the return value is undefined in case
|
||||
XXX of error.
|
||||
*/
|
||||
|
||||
int DTOOL_PyObject_ComparePointers(PyObject *v1, PyObject *v2) {
|
||||
// try this compare
|
||||
void *v1_this = DTOOL_Call_GetPointerThis(v1);
|
||||
void *v2_this = DTOOL_Call_GetPointerThis(v2);
|
||||
if (v1_this != nullptr && v2_this != nullptr) { // both are our types...
|
||||
if (v1_this < v2_this) {
|
||||
return -1;
|
||||
}
|
||||
if (v1_this > v2_this) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// ok self compare...
|
||||
if (v1 < v2) {
|
||||
return -1;
|
||||
}
|
||||
if (v1 > v2) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int DTOOL_PyObject_Compare(PyObject *v1, PyObject *v2) {
|
||||
// First try compareTo function..
|
||||
PyObject * func = PyObject_GetAttrString(v1, "compare_to");
|
||||
if (func == nullptr) {
|
||||
PyErr_Clear();
|
||||
} else {
|
||||
#if PY_VERSION_HEX >= 0x03060000
|
||||
PyObject *res = _PyObject_FastCall(func, &v2, 1);
|
||||
#else
|
||||
PyObject *res = nullptr;
|
||||
PyObject *args = PyTuple_Pack(1, v2);
|
||||
if (args != nullptr) {
|
||||
res = PyObject_Call(func, args, nullptr);
|
||||
Py_DECREF(args);
|
||||
}
|
||||
#endif
|
||||
Py_DECREF(func);
|
||||
PyErr_Clear(); // just in case the function threw an error
|
||||
// only use if the function returns an INT... hmm
|
||||
if (res != nullptr) {
|
||||
if (PyLong_Check(res)) {
|
||||
long answer = PyLong_AsLong(res);
|
||||
Py_DECREF(res);
|
||||
|
||||
// Python really wants us to return strictly -1, 0, or 1.
|
||||
if (answer < 0) {
|
||||
return -1;
|
||||
} else if (answer > 0) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#if PY_MAJOR_VERSION < 3
|
||||
else if (PyInt_Check(res)) {
|
||||
long answer = PyInt_AsLong(res);
|
||||
Py_DECREF(res);
|
||||
|
||||
// Python really wants us to return strictly -1, 0, or 1.
|
||||
if (answer < 0) {
|
||||
return -1;
|
||||
} else if (answer > 0) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
Py_DECREF(res);
|
||||
}
|
||||
}
|
||||
|
||||
return DTOOL_PyObject_ComparePointers(v1, v2);
|
||||
}
|
||||
|
||||
PyObject *DTOOL_PyObject_RichCompare(PyObject *v1, PyObject *v2, int op) {
|
||||
int cmpval = DTOOL_PyObject_Compare(v1, v2);
|
||||
bool result;
|
||||
switch (op) {
|
||||
NODEFAULT
|
||||
case Py_LT:
|
||||
result = (cmpval < 0);
|
||||
break;
|
||||
case Py_LE:
|
||||
result = (cmpval <= 0);
|
||||
break;
|
||||
case Py_EQ:
|
||||
result = (cmpval == 0);
|
||||
break;
|
||||
case Py_NE:
|
||||
result = (cmpval != 0);
|
||||
break;
|
||||
case Py_GT:
|
||||
result = (cmpval > 0);
|
||||
break;
|
||||
case Py_GE:
|
||||
result = (cmpval >= 0);
|
||||
break;
|
||||
}
|
||||
return PyBool_FromLong(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a support function for a synthesized __copy__() method from a C++
|
||||
* make_copy() method.
|
||||
@ -875,15 +743,7 @@ PyObject *copy_from_make_copy(PyObject *self, PyObject *noargs) {
|
||||
*/
|
||||
PyObject *copy_from_copy_constructor(PyObject *self, PyObject *noargs) {
|
||||
PyObject *callable = (PyObject *)Py_TYPE(self);
|
||||
|
||||
#if PY_VERSION_HEX >= 0x03060000
|
||||
PyObject *result = _PyObject_FastCall(callable, &self, 1);
|
||||
#else
|
||||
PyObject *args = PyTuple_Pack(1, self);
|
||||
PyObject *result = PyObject_Call(callable, args, nullptr);
|
||||
Py_DECREF(args);
|
||||
#endif
|
||||
return result;
|
||||
return _PyObject_FastCall(callable, &self, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -195,8 +195,6 @@ EXPCL_INTERROGATEDB void DTOOL_Call_ExtractThisPointerForType(PyObject *self, Dt
|
||||
|
||||
EXPCL_INTERROGATEDB void *DTOOL_Call_GetPointerThisClass(PyObject *self, Dtool_PyTypedObject *classdef, int param, const std::string &function_name, bool const_ok, bool report_errors);
|
||||
|
||||
EXPCL_INTERROGATEDB void *DTOOL_Call_GetPointerThis(PyObject *self);
|
||||
|
||||
EXPCL_INTERROGATEDB bool Dtool_Call_ExtractThisPointer(PyObject *self, Dtool_PyTypedObject &classdef, void **answer);
|
||||
|
||||
EXPCL_INTERROGATEDB bool Dtool_Call_ExtractThisPointer_NonConst(PyObject *self, Dtool_PyTypedObject &classdef,
|
||||
@ -205,6 +203,10 @@ EXPCL_INTERROGATEDB bool Dtool_Call_ExtractThisPointer_NonConst(PyObject *self,
|
||||
template<class T> INLINE bool DtoolInstance_GetPointer(PyObject *self, T *&into);
|
||||
template<class T> INLINE bool DtoolInstance_GetPointer(PyObject *self, T *&into, Dtool_PyTypedObject &classdef);
|
||||
|
||||
INLINE Py_hash_t DtoolInstance_HashPointer(PyObject *self);
|
||||
INLINE int DtoolInstance_ComparePointers(PyObject *v1, PyObject *v2);
|
||||
INLINE PyObject *DtoolInstance_RichComparePointers(PyObject *v1, PyObject *v2, int op);
|
||||
|
||||
// Functions related to error reporting.
|
||||
EXPCL_INTERROGATEDB bool _Dtool_CheckErrorOccurred();
|
||||
|
||||
@ -331,21 +333,8 @@ EXPCL_INTERROGATEDB PyObject *Dtool_BorrowThisReference(PyObject *self, PyObject
|
||||
// some point..
|
||||
EXPCL_INTERROGATEDB PyObject *Dtool_AddToDictionary(PyObject *self1, PyObject *args);
|
||||
|
||||
|
||||
EXPCL_INTERROGATEDB Py_hash_t DTOOL_PyObject_HashPointer(PyObject *obj);
|
||||
|
||||
/* Compare v to w. Return
|
||||
-1 if v < w or exception (PyErr_Occurred() true in latter case).
|
||||
0 if v == w.
|
||||
1 if v > w.
|
||||
XXX The docs (C API manual) say the return value is undefined in case
|
||||
XXX of error.
|
||||
*/
|
||||
|
||||
EXPCL_INTERROGATEDB int DTOOL_PyObject_ComparePointers(PyObject *v1, PyObject *v2);
|
||||
EXPCL_INTERROGATEDB int DTOOL_PyObject_Compare(PyObject *v1, PyObject *v2);
|
||||
|
||||
EXPCL_INTERROGATEDB PyObject *DTOOL_PyObject_RichCompare(PyObject *v1, PyObject *v2, int op);
|
||||
#define DTOOL_PyObject_HashPointer DtoolInstance_HashPointer
|
||||
#define DTOOL_PyObject_ComparePointers DtoolInstance_ComparePointers
|
||||
|
||||
EXPCL_INTERROGATEDB PyObject *
|
||||
copy_from_make_copy(PyObject *self, PyObject *noargs);
|
||||
|
@ -192,6 +192,7 @@ extern "C" {
|
||||
EXPCL_PYSTUB int _PyArg_Parse_SizeT(...);
|
||||
EXPCL_PYSTUB int _PyErr_BadInternalCall(...);
|
||||
EXPCL_PYSTUB int _PyLong_AsByteArray(...);
|
||||
EXPCL_PYSTUB int _PyLong_Sign(...);
|
||||
EXPCL_PYSTUB int _PyObject_CallFunction_SizeT(...);
|
||||
EXPCL_PYSTUB int _PyObject_CallMethod_SizeT(...);
|
||||
EXPCL_PYSTUB int _PyObject_DebugFree(...);
|
||||
@ -421,6 +422,7 @@ int _PyArg_ParseTupleAndKeywords_SizeT(...) { return 0; };
|
||||
int _PyArg_Parse_SizeT(...) { return 0; };
|
||||
int _PyErr_BadInternalCall(...) { return 0; };
|
||||
int _PyLong_AsByteArray(...) { return 0; };
|
||||
int _PyLong_Sign(...) { return 0; };
|
||||
int _PyObject_CallFunction_SizeT(...) { return 0; };
|
||||
int _PyObject_CallMethod_SizeT(...) { return 0; };
|
||||
int _PyObject_DebugFree(...) { return 0; };
|
||||
|
Loading…
x
Reference in New Issue
Block a user