106
137
/*------------------------------
107
138
* PyObjectPlus attributes -- attributes
108
139
------------------------------*/
109
PyObject *PyObjectPlus::_getattr(const STR_String& attr)
111
if (attr == "__doc__" && GetType()->tp_doc)
112
return PyString_FromString(GetType()->tp_doc);
114
//if (streq(attr, "type"))
115
// return Py_BuildValue("s", (*(GetParents()))->tp_name);
117
return Py_FindMethod(Methods, this, const_cast<char *>(attr.ReadPtr()));
120
int PyObjectPlus::_delattr(const STR_String& attr)
142
/* This should be the entry in Type since it takes the C++ class from PyObjectPlus_Proxy */
143
PyObject *PyObjectPlus::py_base_getattro(PyObject * self, PyObject *attr)
145
PyObjectPlus *self_plus= BGE_PROXY_REF(self);
146
if(self_plus==NULL) {
147
if(!strcmp("invalid", PyString_AsString(attr))) {
150
PyErr_SetString(PyExc_SystemError, BGE_PROXY_ERROR_MSG);
154
PyObject *ret= self_plus->py_getattro(attr);
156
/* Attribute not found, was this a __dict__ lookup?, otherwise set an error if none is set */
158
char *attr_str= PyString_AsString(attr);
160
if (strcmp(attr_str, "__dict__")==0)
162
/* the error string will probably not
163
* be set but just incase clear it */
165
ret= self_plus->py_getattro_dict();
167
else if (!PyErr_Occurred()) {
168
/* We looked for an attribute but it wasnt found
169
* since py_getattro didnt set the error, set it here */
170
PyErr_Format(PyExc_AttributeError, "'%s' object has no attribute '%s'", self->ob_type->tp_name, attr_str);
176
/* This should be the entry in Type since it takes the C++ class from PyObjectPlus_Proxy */
177
int PyObjectPlus::py_base_setattro(PyObject *self, PyObject *attr, PyObject *value)
179
PyObjectPlus *self_plus= BGE_PROXY_REF(self);
180
if(self_plus==NULL) {
181
PyErr_SetString(PyExc_SystemError, BGE_PROXY_ERROR_MSG);
186
return self_plus->py_delattro(attr);
188
return self_plus->py_setattro(attr, value);
191
PyObject *PyObjectPlus::py_base_repr(PyObject *self) // This should be the entry in Type.
194
PyObjectPlus *self_plus= BGE_PROXY_REF(self);
195
if(self_plus==NULL) {
196
PyErr_SetString(PyExc_SystemError, BGE_PROXY_ERROR_MSG);
200
return self_plus->py_repr();
203
PyObject *PyObjectPlus::py_getattro(PyObject* attr)
205
PyObject *descr = PyDict_GetItem(Type.tp_dict, attr); \
207
return NULL; /* py_base_getattro sets the error, this way we can avoid setting the error at many levels */
209
/* Copied from py_getattro_up */
210
if (PyCObject_Check(descr)) {
211
return py_get_attrdef((void *)this, (const PyAttributeDef*)PyCObject_AsVoidPtr(descr));
212
} else if (descr->ob_type->tp_descr_get) {
213
return PyCFunction_New(((PyMethodDescrObject *)descr)->d_method, this->m_proxy);
217
/* end py_getattro_up copy */
221
PyObject* PyObjectPlus::py_getattro_dict() {
222
return py_getattr_dict(NULL, Type.tp_dict);
225
int PyObjectPlus::py_delattro(PyObject* attr)
122
227
PyErr_SetString(PyExc_AttributeError, "attribute cant be deleted");
126
int PyObjectPlus::_setattr(const STR_String& attr, PyObject *value)
231
int PyObjectPlus::py_setattro(PyObject *attr, PyObject* value)
128
//return PyObject::_setattr(attr,value);
129
//cerr << "Unknown attribute" << endl;
130
233
PyErr_SetString(PyExc_AttributeError, "attribute cant be set");
234
return PY_SET_ATTR_MISSING;
237
PyObject *PyObjectPlus::py_get_attrdef(void *self, const PyAttributeDef *attrdef)
239
if (attrdef->m_type == KX_PYATTRIBUTE_TYPE_DUMMY)
241
// fake attribute, ignore
244
if (attrdef->m_type == KX_PYATTRIBUTE_TYPE_FUNCTION)
246
// the attribute has no field correspondance, handover processing to function.
247
if (attrdef->m_getFunction == NULL)
249
return (*attrdef->m_getFunction)(self, attrdef);
251
char *ptr = reinterpret_cast<char*>(self)+attrdef->m_offset;
252
if (attrdef->m_length > 1)
254
PyObject* resultlist = PyList_New(attrdef->m_length);
255
for (unsigned int i=0; i<attrdef->m_length; i++)
257
switch (attrdef->m_type) {
258
case KX_PYATTRIBUTE_TYPE_BOOL:
260
bool *val = reinterpret_cast<bool*>(ptr);
262
PyList_SET_ITEM(resultlist,i,PyInt_FromLong(*val));
265
case KX_PYATTRIBUTE_TYPE_SHORT:
267
short int *val = reinterpret_cast<short int*>(ptr);
268
ptr += sizeof(short int);
269
PyList_SET_ITEM(resultlist,i,PyInt_FromLong(*val));
272
case KX_PYATTRIBUTE_TYPE_ENUM:
273
// enum are like int, just make sure the field size is the same
274
if (sizeof(int) != attrdef->m_size)
276
Py_DECREF(resultlist);
280
case KX_PYATTRIBUTE_TYPE_INT:
282
int *val = reinterpret_cast<int*>(ptr);
284
PyList_SET_ITEM(resultlist,i,PyInt_FromLong(*val));
287
case KX_PYATTRIBUTE_TYPE_FLOAT:
289
float *val = reinterpret_cast<float*>(ptr);
290
ptr += sizeof(float);
291
PyList_SET_ITEM(resultlist,i,PyFloat_FromDouble(*val));
295
// no support for array of complex data
296
Py_DECREF(resultlist);
304
switch (attrdef->m_type) {
305
case KX_PYATTRIBUTE_TYPE_BOOL:
307
bool *val = reinterpret_cast<bool*>(ptr);
308
return PyInt_FromLong(*val);
310
case KX_PYATTRIBUTE_TYPE_SHORT:
312
short int *val = reinterpret_cast<short int*>(ptr);
313
return PyInt_FromLong(*val);
315
case KX_PYATTRIBUTE_TYPE_ENUM:
316
// enum are like int, just make sure the field size is the same
317
if (sizeof(int) != attrdef->m_size)
322
case KX_PYATTRIBUTE_TYPE_INT:
324
int *val = reinterpret_cast<int*>(ptr);
325
return PyInt_FromLong(*val);
327
case KX_PYATTRIBUTE_TYPE_FLOAT:
329
float *val = reinterpret_cast<float*>(ptr);
330
return PyFloat_FromDouble(*val);
332
case KX_PYATTRIBUTE_TYPE_VECTOR:
334
PyObject* resultlist = PyList_New(3);
335
MT_Vector3 *val = reinterpret_cast<MT_Vector3*>(ptr);
336
for (unsigned int i=0; i<3; i++)
338
PyList_SET_ITEM(resultlist,i,PyFloat_FromDouble((*val)[i]));
342
case KX_PYATTRIBUTE_TYPE_STRING:
344
STR_String *val = reinterpret_cast<STR_String*>(ptr);
345
return PyString_FromString(*val);
353
int PyObjectPlus::py_set_attrdef(void *self, const PyAttributeDef *attrdef, PyObject *value)
355
void *undoBuffer = NULL;
356
void *sourceBuffer = NULL;
357
size_t bufferSize = 0;
359
char *ptr = reinterpret_cast<char*>(self)+attrdef->m_offset;
360
if (attrdef->m_length > 1)
362
if (!PySequence_Check(value))
364
PyErr_Format(PyExc_TypeError, "expected a sequence for attribute \"%s\"", attrdef->m_name);
365
return PY_SET_ATTR_FAIL;
367
if (PySequence_Size(value) != attrdef->m_length)
369
PyErr_Format(PyExc_TypeError, "incorrect number of elements in sequence for attribute \"%s\"", attrdef->m_name);
370
return PY_SET_ATTR_FAIL;
372
switch (attrdef->m_type)
374
case KX_PYATTRIBUTE_TYPE_FUNCTION:
375
if (attrdef->m_setFunction == NULL)
377
PyErr_Format(PyExc_AttributeError, "function attribute without function for attribute \"%s\", report to blender.org", attrdef->m_name);
378
return PY_SET_ATTR_FAIL;
380
return (*attrdef->m_setFunction)(self, attrdef, value);
381
case KX_PYATTRIBUTE_TYPE_BOOL:
382
bufferSize = sizeof(bool);
384
case KX_PYATTRIBUTE_TYPE_SHORT:
385
bufferSize = sizeof(short int);
387
case KX_PYATTRIBUTE_TYPE_ENUM:
388
case KX_PYATTRIBUTE_TYPE_INT:
389
bufferSize = sizeof(int);
391
case KX_PYATTRIBUTE_TYPE_FLOAT:
392
bufferSize = sizeof(float);
396
PyErr_Format(PyExc_AttributeError, "Unsupported attribute type for attribute \"%s\", report to blender.org", attrdef->m_name);
397
return PY_SET_ATTR_FAIL;
399
// let's implement a smart undo method
400
bufferSize *= attrdef->m_length;
401
undoBuffer = malloc(bufferSize);
405
memcpy(undoBuffer, sourceBuffer, bufferSize);
407
for (int i=0; i<attrdef->m_length; i++)
409
PyObject *item = PySequence_GetItem(value, i); /* new ref */
410
// we can decrement the reference immediately, the reference count
411
// is at least 1 because the item is part of an array
413
switch (attrdef->m_type)
415
case KX_PYATTRIBUTE_TYPE_BOOL:
417
bool *var = reinterpret_cast<bool*>(ptr);
419
if (PyInt_Check(item))
421
*var = (PyInt_AsLong(item) != 0);
423
else if (PyBool_Check(item))
425
*var = (item == Py_True);
429
PyErr_Format(PyExc_TypeError, "expected an integer or a bool for attribute \"%s\"", attrdef->m_name);
434
case KX_PYATTRIBUTE_TYPE_SHORT:
436
short int *var = reinterpret_cast<short int*>(ptr);
437
ptr += sizeof(short int);
438
if (PyInt_Check(item))
440
long val = PyInt_AsLong(item);
441
if (attrdef->m_clamp)
443
if (val < attrdef->m_imin)
444
val = attrdef->m_imin;
445
else if (val > attrdef->m_imax)
446
val = attrdef->m_imax;
448
else if (val < attrdef->m_imin || val > attrdef->m_imax)
450
PyErr_Format(PyExc_ValueError, "item value out of range for attribute \"%s\"", attrdef->m_name);
453
*var = (short int)val;
457
PyErr_Format(PyExc_TypeError, "expected an integer for attribute \"%s\"", attrdef->m_name);
462
case KX_PYATTRIBUTE_TYPE_ENUM:
463
// enum are equivalent to int, just make sure that the field size matches:
464
if (sizeof(int) != attrdef->m_size)
466
PyErr_Format(PyExc_AttributeError, "Size check error for attribute, \"%s\", report to blender.org", attrdef->m_name);
470
case KX_PYATTRIBUTE_TYPE_INT:
472
int *var = reinterpret_cast<int*>(ptr);
474
if (PyInt_Check(item))
476
long val = PyInt_AsLong(item);
477
if (attrdef->m_clamp)
479
if (val < attrdef->m_imin)
480
val = attrdef->m_imin;
481
else if (val > attrdef->m_imax)
482
val = attrdef->m_imax;
484
else if (val < attrdef->m_imin || val > attrdef->m_imax)
486
PyErr_Format(PyExc_ValueError, "item value out of range for attribute \"%s\"", attrdef->m_name);
493
PyErr_Format(PyExc_TypeError, "expected an integer for attribute \"%s\"", attrdef->m_name);
498
case KX_PYATTRIBUTE_TYPE_FLOAT:
500
float *var = reinterpret_cast<float*>(ptr);
501
ptr += sizeof(float);
502
double val = PyFloat_AsDouble(item);
503
if (val == -1.0 && PyErr_Occurred())
505
PyErr_Format(PyExc_TypeError, "expected a float for attribute \"%s\"", attrdef->m_name);
508
else if (attrdef->m_clamp)
510
if (val < attrdef->m_fmin)
511
val = attrdef->m_fmin;
512
else if (val > attrdef->m_fmax)
513
val = attrdef->m_fmax;
515
else if (val < attrdef->m_fmin || val > attrdef->m_fmax)
517
PyErr_Format(PyExc_ValueError, "item value out of range for attribute \"%s\"", attrdef->m_name);
525
PyErr_Format(PyExc_AttributeError, "type check error for attribute \"%s\", report to blender.org", attrdef->m_name);
529
// no error, call check function if any
530
if (attrdef->m_checkFunction != NULL)
532
if ((*attrdef->m_checkFunction)(self, attrdef) != 0)
534
// if the checing function didnt set an error then set a generic one here so we dont set an error with no exception
535
if (PyErr_Occurred()==0)
536
PyErr_Format(PyExc_AttributeError, "type check error for attribute \"%s\", reasion unknown", attrdef->m_name);
538
// post check returned an error, restore values
542
memcpy(sourceBuffer, undoBuffer, bufferSize);
545
return PY_SET_ATTR_FAIL;
550
return PY_SET_ATTR_SUCCESS;
552
else // simple attribute value
554
if (attrdef->m_type == KX_PYATTRIBUTE_TYPE_FUNCTION)
556
if (attrdef->m_setFunction == NULL)
558
PyErr_Format(PyExc_AttributeError, "function attribute without function \"%s\", report to blender.org", attrdef->m_name);
559
return PY_SET_ATTR_FAIL;
561
return (*attrdef->m_setFunction)(self, attrdef, value);
563
if (attrdef->m_checkFunction != NULL || attrdef->m_type == KX_PYATTRIBUTE_TYPE_VECTOR)
565
// post check function is provided, prepare undo buffer
567
switch (attrdef->m_type)
569
case KX_PYATTRIBUTE_TYPE_BOOL:
570
bufferSize = sizeof(bool);
572
case KX_PYATTRIBUTE_TYPE_SHORT:
573
bufferSize = sizeof(short);
575
case KX_PYATTRIBUTE_TYPE_ENUM:
576
case KX_PYATTRIBUTE_TYPE_INT:
577
bufferSize = sizeof(int);
579
case KX_PYATTRIBUTE_TYPE_FLOAT:
580
bufferSize = sizeof(float);
582
case KX_PYATTRIBUTE_TYPE_STRING:
583
sourceBuffer = reinterpret_cast<STR_String*>(ptr)->Ptr();
585
bufferSize = strlen(reinterpret_cast<char*>(sourceBuffer))+1;
587
case KX_PYATTRIBUTE_TYPE_VECTOR:
588
bufferSize = sizeof(MT_Vector3);
591
PyErr_Format(PyExc_AttributeError, "unknown type for attribute \"%s\", report to blender.org", attrdef->m_name);
592
return PY_SET_ATTR_FAIL;
596
undoBuffer = malloc(bufferSize);
599
memcpy(undoBuffer, sourceBuffer, bufferSize);
604
switch (attrdef->m_type)
606
case KX_PYATTRIBUTE_TYPE_BOOL:
608
bool *var = reinterpret_cast<bool*>(ptr);
609
if (PyInt_Check(value))
611
*var = (PyInt_AsLong(value) != 0);
613
else if (PyBool_Check(value))
615
*var = (value == Py_True);
619
PyErr_Format(PyExc_TypeError, "expected an integer or a bool for attribute \"%s\"", attrdef->m_name);
624
case KX_PYATTRIBUTE_TYPE_SHORT:
626
short int *var = reinterpret_cast<short int*>(ptr);
627
if (PyInt_Check(value))
629
long val = PyInt_AsLong(value);
630
if (attrdef->m_clamp)
632
if (val < attrdef->m_imin)
633
val = attrdef->m_imin;
634
else if (val > attrdef->m_imax)
635
val = attrdef->m_imax;
637
else if (val < attrdef->m_imin || val > attrdef->m_imax)
639
PyErr_Format(PyExc_ValueError, "value out of range for attribute \"%s\"", attrdef->m_name);
642
*var = (short int)val;
646
PyErr_Format(PyExc_TypeError, "expected an integer for attribute \"%s\"", attrdef->m_name);
651
case KX_PYATTRIBUTE_TYPE_ENUM:
652
// enum are equivalent to int, just make sure that the field size matches:
653
if (sizeof(int) != attrdef->m_size)
655
PyErr_Format(PyExc_AttributeError, "attribute size check error for attribute \"%s\", report to blender.org", attrdef->m_name);
659
case KX_PYATTRIBUTE_TYPE_INT:
661
int *var = reinterpret_cast<int*>(ptr);
662
if (PyInt_Check(value))
664
long val = PyInt_AsLong(value);
665
if (attrdef->m_clamp)
667
if (val < attrdef->m_imin)
668
val = attrdef->m_imin;
669
else if (val > attrdef->m_imax)
670
val = attrdef->m_imax;
672
else if (val < attrdef->m_imin || val > attrdef->m_imax)
674
PyErr_Format(PyExc_ValueError, "value out of range for attribute \"%s\"", attrdef->m_name);
681
PyErr_Format(PyExc_TypeError, "expected an integer for attribute \"%s\"", attrdef->m_name);
686
case KX_PYATTRIBUTE_TYPE_FLOAT:
688
float *var = reinterpret_cast<float*>(ptr);
689
double val = PyFloat_AsDouble(value);
690
if (val == -1.0 && PyErr_Occurred())
692
PyErr_Format(PyExc_TypeError, "expected a float for attribute \"%s\"", attrdef->m_name);
695
else if (attrdef->m_clamp)
697
if (val < attrdef->m_fmin)
698
val = attrdef->m_fmin;
699
else if (val > attrdef->m_fmax)
700
val = attrdef->m_fmax;
702
else if (val < attrdef->m_fmin || val > attrdef->m_fmax)
704
PyErr_Format(PyExc_ValueError, "value out of range for attribute \"%s\"", attrdef->m_name);
710
case KX_PYATTRIBUTE_TYPE_VECTOR:
712
if (!PySequence_Check(value) || PySequence_Size(value) != 3)
714
PyErr_Format(PyExc_TypeError, "expected a sequence of 3 floats for attribute \"%s\"", attrdef->m_name);
715
return PY_SET_ATTR_FAIL;
717
MT_Vector3 *var = reinterpret_cast<MT_Vector3*>(ptr);
718
for (int i=0; i<3; i++)
720
PyObject *item = PySequence_GetItem(value, i); /* new ref */
721
// we can decrement the reference immediately, the reference count
722
// is at least 1 because the item is part of an array
724
double val = PyFloat_AsDouble(item);
725
if (val == -1.0 && PyErr_Occurred())
727
PyErr_Format(PyExc_TypeError, "expected a sequence of 3 floats for attribute \"%s\"", attrdef->m_name);
728
goto RESTORE_AND_ERROR;
730
else if (attrdef->m_clamp)
732
if (val < attrdef->m_fmin)
733
val = attrdef->m_fmin;
734
else if (val > attrdef->m_fmax)
735
val = attrdef->m_fmax;
737
else if (val < attrdef->m_fmin || val > attrdef->m_fmax)
739
PyErr_Format(PyExc_ValueError, "value out of range for attribute \"%s\"", attrdef->m_name);
740
goto RESTORE_AND_ERROR;
742
(*var)[i] = (MT_Scalar)val;
746
case KX_PYATTRIBUTE_TYPE_STRING:
748
STR_String *var = reinterpret_cast<STR_String*>(ptr);
749
if (PyString_Check(value))
751
char *val = PyString_AsString(value);
752
if (attrdef->m_clamp)
754
if (strlen(val) < attrdef->m_imin)
756
// can't increase the length of the string
757
PyErr_Format(PyExc_ValueError, "string length too short for attribute \"%s\"", attrdef->m_name);
760
else if (strlen(val) > attrdef->m_imax)
763
char c = val[attrdef->m_imax];
764
val[attrdef->m_imax] = 0;
766
val[attrdef->m_imax] = c;
769
} else if (strlen(val) < attrdef->m_imin || strlen(val) > attrdef->m_imax)
771
PyErr_Format(PyExc_ValueError, "string length out of range for attribute \"%s\"", attrdef->m_name);
778
PyErr_Format(PyExc_TypeError, "expected a string for attribute \"%s\"", attrdef->m_name);
785
PyErr_Format(PyExc_AttributeError, "unknown type for attribute \"%s\", report to blender.org", attrdef->m_name);
789
// check if post processing is needed
790
if (attrdef->m_checkFunction != NULL)
792
if ((*attrdef->m_checkFunction)(self, attrdef) != 0)
798
if (attrdef->m_type == KX_PYATTRIBUTE_TYPE_STRING)
800
// special case for STR_String: restore the string
801
STR_String *var = reinterpret_cast<STR_String*>(ptr);
802
*var = reinterpret_cast<char*>(undoBuffer);
806
// other field type have direct values
807
memcpy(ptr, undoBuffer, bufferSize);
134
823
/*------------------------------
135
824
* PyObjectPlus repr -- representations
136
825
------------------------------*/
137
PyObject *PyObjectPlus::_repr(void)
826
PyObject *PyObjectPlus::py_repr(void)
139
828
PyErr_SetString(PyExc_SystemError, "Representation not overridden by object.");
145
834
------------------------------*/
146
835
bool PyObjectPlus::isA(PyTypeObject *T) // if called with a Type, use "typename"
148
return isA(T->tp_name);
839
PyParentObject *Ps = GetParents();
841
for (P = Ps[i=0]; P != NULL; P = Ps[i++])
152
849
bool PyObjectPlus::isA(const char *mytypename) // check typename of each parent
156
PyParentObject *Ps = GetParents();
853
PyParentObject *Ps = GetParents();
158
for (P = Ps[i=0]; P != NULL; P = Ps[i++])
160
if (STR_String(P->tp_name) == STR_String(mytypename) )
167
PyObject *PyObjectPlus::Py_isA(PyObject *args) // Python wrapper for isA
170
if (!PyArg_ParseTuple(args, "s", &mytypename))
855
for (P = Ps[i=0]; P != NULL; P = Ps[i++])
856
if (strcmp(P->tp_name, mytypename)==0)
862
PyObject *PyObjectPlus::PyisA(PyObject *value) // Python wrapper for isA
864
if (PyType_Check(value)) {
865
return PyBool_FromLong(isA((PyTypeObject *)value));
866
} else if (PyString_Check(value)) {
867
return PyBool_FromLong(isA(PyString_AsString(value)));
869
PyErr_SetString(PyExc_TypeError, "object.isA(value): expected a type or a string");
874
void PyObjectPlus::ProcessReplica()
876
/* Clear the proxy, will be created again if needed with GetProxy()
877
* otherwise the PyObject will point to the wrong reference */
881
/* Sometimes we might want to manually invalidate a BGE type even if
882
* it hasnt been released by the BGE, say for example when an object
883
* is removed from a scene, accessing it may cause problems.
885
* In this case the current proxy is made invalid, disowned,
886
* and will raise an error on access. However if python can get access
887
* to this class again it will make a new proxy and work as expected.
889
void PyObjectPlus::InvalidateProxy() // check typename of each parent
892
BGE_PROXY_REF(m_proxy)=NULL;
898
/* Utility function called by the macro py_getattro_up()
899
* for getting ob.__dict__() values from our PyObject
900
* this is used by python for doing dir() on an object, so its good
901
* if we return a list of attributes and methods.
903
* Other then making dir() useful the value returned from __dict__() is not useful
904
* since every value is a Py_None
906
PyObject *py_getattr_dict(PyObject *pydict, PyObject *tp_dict)
908
if(pydict==NULL) { /* incase calling __dict__ on the parent of this object raised an error */
910
pydict = PyDict_New();
913
PyDict_Update(pydict, tp_dict);
919
PyObject *PyObjectPlus::GetProxy_Ext(PyObjectPlus *self, PyTypeObject *tp)
921
if (self->m_proxy==NULL)
923
self->m_proxy = reinterpret_cast<PyObject *>PyObject_NEW( PyObjectPlus_Proxy, tp);
924
BGE_PROXY_PYOWNS(self->m_proxy) = false;
926
//PyObject_Print(self->m_proxy, stdout, 0);
927
//printf("ref %d\n", self->m_proxy->ob_refcnt);
929
BGE_PROXY_REF(self->m_proxy) = self; /* Its possible this was set to NULL, so set it back here */
930
Py_INCREF(self->m_proxy); /* we own one, thos ones fore the return */
931
return self->m_proxy;
934
PyObject *PyObjectPlus::NewProxy_Ext(PyObjectPlus *self, PyTypeObject *tp, bool py_owns)
940
BGE_PROXY_REF(self->m_proxy) = NULL;
941
Py_DECREF(self->m_proxy);
945
Py_INCREF(self->m_proxy);
946
return self->m_proxy;
951
GetProxy_Ext(self, tp);
953
BGE_PROXY_PYOWNS(self->m_proxy) = py_owns;
954
Py_DECREF(self->m_proxy); /* could avoid thrashing here but for now its ok */
956
return self->m_proxy;
959
///////////////////////////////////////////////////////////////////////////////////////////////
960
///////////////////////////////////////////////////////////////////////////////////////////////
961
/* deprecation warning management */
963
bool PyObjectPlus::m_ignore_deprecation_warnings(false);
964
void PyObjectPlus::SetDeprecationWarnings(bool ignoreDeprecationWarnings)
966
m_ignore_deprecation_warnings = ignoreDeprecationWarnings;
969
void PyObjectPlus::ShowDeprecationWarning_func(const char* old_way,const char* new_way)
972
printf("Method %s is deprecated, please use %s instead.\n", old_way, new_way);
974
// import sys; print '\t%s:%d' % (sys._getframe(0).f_code.co_filename, sys._getframe(0).f_lineno)
976
PyObject *getframe, *frame;
977
PyObject *f_lineno, *f_code, *co_filename;
979
getframe = PySys_GetObject((char *)"_getframe"); // borrowed
981
frame = PyObject_CallObject(getframe, NULL);
983
f_lineno= PyObject_GetAttrString(frame, "f_lineno");
984
f_code= PyObject_GetAttrString(frame, "f_code");
985
if (f_lineno && f_code) {
986
co_filename= PyObject_GetAttrString(f_code, "co_filename");
989
printf("\t%s:%d\n", PyString_AsString(co_filename), (int)PyInt_AsLong(f_lineno));
993
Py_DECREF(co_filename);
999
Py_XDECREF(f_lineno);
1006
printf("\tERROR - Could not access sys._getframe(0).f_lineno or sys._getframe().f_code.co_filename\n");
1010
void PyObjectPlus::ClearDeprecationWarning()
1012
WarnLink *wlink_next;
1013
WarnLink *wlink = GetDeprecationWarningLinkFirst();
1017
wlink->warn_done= false; /* no need to NULL the link, its cleared before adding to the list next time round */
1018
wlink_next= reinterpret_cast<WarnLink *>(wlink->link);
1022
NullDeprecationWarning();
1025
WarnLink* m_base_wlink_first= NULL;
1026
WarnLink* m_base_wlink_last= NULL;
1028
WarnLink* PyObjectPlus::GetDeprecationWarningLinkFirst(void) {return m_base_wlink_first;}
1029
WarnLink* PyObjectPlus::GetDeprecationWarningLinkLast(void) {return m_base_wlink_last;}
1030
void PyObjectPlus::SetDeprecationWarningFirst(WarnLink* wlink) {m_base_wlink_first= wlink;}
1031
void PyObjectPlus::SetDeprecationWarningLinkLast(WarnLink* wlink) {m_base_wlink_last= wlink;}
1032
void PyObjectPlus::NullDeprecationWarning() {m_base_wlink_first= m_base_wlink_last= NULL;}
178
1034
#endif //NO_EXP_PYTHON_EMBEDDING