BGE Python API
[blender.git] / source / gameengine / Expressions / Value.cpp
1 // Value.cpp: implementation of the CValue class.
2 // developed at Eindhoven University of Technology, 1997
3 // by the OOPS team
4 //////////////////////////////////////////////////////////////////////
5 /*
6  * Copyright (c) 1996-2000 Erwin Coumans <coockie@acm.org>
7  *
8  * Permission to use, copy, modify, distribute and sell this software
9  * and its documentation for any purpose is hereby granted without fee,
10  * provided that the above copyright notice appear in all copies and
11  * that both that copyright notice and this permission notice appear
12  * in supporting documentation.  Erwin Coumans makes no
13  * representations about the suitability of this software for any
14  * purpose.  It is provided "as is" without express or implied warranty.
15  *
16  */
17 #include "Value.h"
18 #include "FloatValue.h"
19 #include "IntValue.h"
20 #include "VectorValue.h"
21 #include "VoidValue.h"
22 #include "StringValue.h"
23 #include "ErrorValue.h"
24 #include "ListValue.h"
25
26 #ifdef HAVE_CONFIG_H
27 #include <config.h>
28 #endif
29
30 //////////////////////////////////////////////////////////////////////
31 // Construction/Destruction
32 //////////////////////////////////////////////////////////////////////
33
34 double CValue::m_sZeroVec[3] = {0.0,0.0,0.0};
35 bool CValue::m_ignore_deprecation_warnings(false);
36
37 #ifndef NO_EXP_PYTHON_EMBEDDING
38
39 PyObject* cvalue_add(PyObject*v, PyObject*w)
40 {
41         return  ((CValue*)v)->Calc(VALUE_ADD_OPERATOR,(CValue*)w);
42 }
43 PyObject* cvalue_sub(PyObject*v, PyObject*w)
44 {
45         return  ((CValue*)v)->Calc(VALUE_SUB_OPERATOR,(CValue*)w);
46 }
47 PyObject* cvalue_mul(PyObject*v, PyObject*w)
48 {
49         return  ((CValue*)v)->Calc(VALUE_MUL_OPERATOR,(CValue*)w);
50 }
51 PyObject* cvalue_div(PyObject*v, PyObject*w)
52 {
53         return  ((CValue*)v)->Calc(VALUE_DIV_OPERATOR,(CValue*)w);
54 }
55 PyObject* cvalue_mod(PyObject*v, PyObject*w)
56 {
57         return  ((CValue*)v)->Calc(VALUE_MOD_OPERATOR,(CValue*)w);
58 }
59 PyObject* cvalue_neg(PyObject*v)
60 {
61         return  ((CValue*)v)->Calc(VALUE_NEG_OPERATOR,(CValue*)v);
62 }
63 PyObject* cvalue_pos(PyObject*v)
64 {
65         return  ((CValue*)v)->Calc(VALUE_POS_OPERATOR,(CValue*)v);
66 }
67
68
69 int MyPyCompare (PyObject* v,PyObject* w)
70 {
71         CValue* eqval =  ((CValue*)v)->Calc(VALUE_EQL_OPERATOR,(CValue*)w);
72         STR_String txt = eqval->GetText();
73         eqval->Release();
74         if (txt=="TRUE")
75                 return 0;
76         CValue* lessval =  ((CValue*)v)->Calc(VALUE_LES_OPERATOR,(CValue*)w);
77         txt = lessval->GetText();
78         lessval->Release();
79         if (txt=="TRUE")
80                 return -1;
81
82         return 1;
83 }
84
85
86 int cvalue_coerce(PyObject** pv,PyObject** pw)
87 {
88         if (PyInt_Check(*pw)) {
89                 *pw = new CIntValue((cInt)PyInt_AsLong(*pw));
90                 Py_INCREF(*pv);
91                 return 0;
92         }
93         else if (PyLong_Check(*pw)) {
94                 *pw = new CIntValue((cInt)PyLong_AsLongLong(*pw));
95                 Py_INCREF(*pv);
96                 return 0;
97         }
98         else if (PyFloat_Check(*pw)) {
99                 *pw = new CFloatValue((float)PyFloat_AsDouble(*pw));
100                 Py_INCREF(*pv);
101                 return 0;
102         } else if (PyString_Check(*pw)) {
103                 const STR_String str = PyString_AsString(*pw);
104                 *pw = new CStringValue(str,"");
105                 Py_INCREF(*pv);
106                 return 0;
107         }
108         
109         PyErr_SetString(PyExc_TypeError, "unable to coerce python type to cvalue");
110         return 1; /* Can't do it */
111
112 }
113 static PyNumberMethods cvalue_as_number = {
114         (binaryfunc)cvalue_add, /*nb_add*/
115         (binaryfunc)cvalue_sub, /*nb_subtract*/
116         (binaryfunc)cvalue_mul, /*nb_multiply*/
117         (binaryfunc)cvalue_div, /*nb_divide*/
118         (binaryfunc)cvalue_mod, /*nb_remainder*/
119         0,//(binaryfunc)cvalue_divmod,  /*nb_divmod*/
120         0,//0,//0,//0,//(ternaryfunc)cvalue_pow, /*nb_power*/
121         (unaryfunc)cvalue_neg, /*nb_negative*/
122         0,//(unaryfunc)cvalue_pos, /*nb_positive*/
123         0,//(unaryfunc)cvalue_abs, /*nb_absolute*/
124         0,//(inquiry)cvalue_nonzero, /*nb_nonzero*/
125         0,              /*nb_invert*/
126         0,              /*nb_lshift*/
127         0,              /*nb_rshift*/
128         0,              /*nb_and*/
129         0,              /*nb_xor*/
130         0,              /*nb_or*/
131         (coercion)cvalue_coerce, /*nb_coerce*/
132         0,//(unaryfunc)cvalue_int, /*nb_int*/
133         0,//(unaryfunc)cvalue_long, /*nb_long*/
134         0,//(unaryfunc)cvalue_float, /*nb_float*/
135         0,              /*nb_oct*/
136         0,              /*nb_hex*/
137 };
138
139
140 PyTypeObject CValue::Type = {
141         PyObject_HEAD_INIT(NULL)
142         0,
143         "CValue",
144         sizeof(CValue),
145         0,
146         PyDestructor,
147         0,
148         0,
149         0,
150         &MyPyCompare,
151         py_base_repr,
152         &cvalue_as_number,
153         0,0,0,0,0,
154         py_base_getattro,
155         py_base_setattro,
156         0,0,0,0,0,0,0,0,0,
157         Methods
158 };
159
160 PyParentObject CValue::Parents[] = {
161         &CValue::Type,
162                 NULL
163 };
164
165 PyMethodDef CValue::Methods[] = {
166 //      { "printHello", (PyCFunction) CValue::sPyPrintHello, METH_VARARGS},
167         { "getName", (PyCFunction) CValue::sPyGetName, METH_NOARGS},
168         {NULL,NULL} //Sentinel
169 };
170
171 PyObject* CValue::PyGetName(PyObject* self)
172 {
173         return PyString_FromString(this->GetName());
174 }
175
176 /*#define CVALUE_DEBUG*/
177 #ifdef CVALUE_DEBUG
178 int gRefCount;
179 struct SmartCValueRef 
180 {
181         CValue *m_ref;
182         int m_count;
183         SmartCValueRef(CValue *ref)
184         {
185                 m_ref = ref;
186                 m_count = gRefCount++;
187         }
188 };
189
190 #include <vector>
191
192 std::vector<SmartCValueRef> gRefList;
193 #endif
194
195 #ifdef _DEBUG
196 //int gRefCountValue;
197 #endif
198
199 CValue::CValue(PyTypeObject *T)
200                 : PyObjectPlus(T),
201 #else
202 CValue::CValue()
203
204 #endif //NO_EXP_PYTHON_EMBEDDING
205         
206 m_pNamedPropertyArray(NULL),
207 m_refcount(1)
208 /*
209 pre: false
210 effect: constucts a CValue
211 */
212 {
213         //debug(gRefCountValue++)       // debugging
214 #ifdef _DEBUG
215         //gRefCountValue++;
216 #ifdef CVALUE_DEBUG
217         gRefList.push_back(SmartCValueRef(this));
218 #endif
219 #endif
220 }
221
222
223
224 CValue::~CValue()
225 /*
226 pre:
227 effect: deletes the object
228 */
229 {
230         ClearProperties();
231
232         assertd (m_refcount==0);
233 #ifdef CVALUE_DEBUG
234         std::vector<SmartCValueRef>::iterator it;
235         for (it=gRefList.begin(); it!=gRefList.end(); it++)
236         {
237                 if (it->m_ref == this)
238                 {
239                         *it = gRefList.back();
240                         gRefList.pop_back();
241                         break;
242                 }
243         }
244 #endif
245 }
246
247
248
249
250 #define VALUE_SUB(val1, val2) (val1)->Calc(VALUE_SUB_OPERATOR, val2)
251 #define VALUE_MUL(val1, val2) (val1)->Calc(VALUE_MUL_OPERATOR, val2)
252 #define VALUE_DIV(val1, val2) (val1)->Calc(VALUE_DIV_OPERATOR, val2)
253 #define VALUE_NEG(val1)       (val1)->Calc(VALUE_NEG_OPERATOR, val1)
254 #define VALUE_POS(val1)       (val1)->Calc(VALUE_POS_OPERATOR, val1)
255
256
257 STR_String CValue::op2str (VALUE_OPERATOR op)
258 {
259         //pre:
260         //ret: the stringrepresentation of operator op
261         
262         STR_String opmsg;
263         switch (op) {
264         case VALUE_MOD_OPERATOR:
265                 opmsg = " % ";
266                 break;
267         case VALUE_ADD_OPERATOR:
268                 opmsg = " + ";
269                 break;
270         case VALUE_SUB_OPERATOR:
271                 opmsg = " - ";
272                 break;
273         case VALUE_MUL_OPERATOR:
274                 opmsg = " * ";
275                 break;
276         case VALUE_DIV_OPERATOR:
277                 opmsg = " / ";
278                 break;
279         case VALUE_NEG_OPERATOR:
280                 opmsg = " -";
281                 break;
282         case VALUE_POS_OPERATOR:
283                 opmsg = " +";
284                 break;
285         case VALUE_AND_OPERATOR:
286                 opmsg = " & ";
287                 break;
288         case VALUE_OR_OPERATOR:
289                 opmsg = " | ";
290                 break;
291         case VALUE_EQL_OPERATOR:
292                 opmsg = " = ";
293                 break;
294         case VALUE_NEQ_OPERATOR:
295                 opmsg = " != ";
296                 break;
297         case VALUE_NOT_OPERATOR:
298                 opmsg = " !";
299                 break;
300         default:
301                 opmsg="Error in Errorhandling routine.";
302                 //              AfxMessageBox("Invalid operator");
303                 break;
304         }
305         return opmsg;
306 }
307
308
309
310
311
312 //---------------------------------------------------------------------------------------------------------------------
313 //      Property Management
314 //---------------------------------------------------------------------------------------------------------------------
315
316
317
318 //
319 // Set property <ioProperty>, overwrites and releases a previous property with the same name if needed
320 //
321 void CValue::SetProperty(const STR_String & name,CValue* ioProperty)
322 {
323         if (ioProperty==NULL)
324         {       // Check if somebody is setting an empty property
325                 trace("Warning:trying to set empty property!");
326                 return;
327         }
328
329         if (m_pNamedPropertyArray)
330         {       // Try to replace property (if so -> exit as soon as we replaced it)
331                 CValue* oldval = (*m_pNamedPropertyArray)[name];
332                 if (oldval)
333                         oldval->Release();
334         }
335         else { // Make sure we have a property array
336                 m_pNamedPropertyArray = new std::map<STR_String,CValue *>;
337         }
338         
339         // Add property at end of array
340         (*m_pNamedPropertyArray)[name] = ioProperty->AddRef();//->Add(ioProperty);
341 }
342
343 void CValue::SetProperty(const char* name,CValue* ioProperty)
344 {
345         if (ioProperty==NULL)
346         {       // Check if somebody is setting an empty property
347                 trace("Warning:trying to set empty property!");
348                 return;
349         }
350
351         if (m_pNamedPropertyArray)
352         {       // Try to replace property (if so -> exit as soon as we replaced it)
353                 CValue* oldval = (*m_pNamedPropertyArray)[name];
354                 if (oldval)
355                         oldval->Release();
356         }
357         else { // Make sure we have a property array
358                 m_pNamedPropertyArray = new std::map<STR_String,CValue *>;
359         }
360         
361         // Add property at end of array
362         (*m_pNamedPropertyArray)[name] = ioProperty->AddRef();//->Add(ioProperty);
363 }
364
365 //
366 // Get pointer to a property with name <inName>, returns NULL if there is no property named <inName>
367 //
368 CValue* CValue::GetProperty(const STR_String & inName)
369 {
370         if (m_pNamedPropertyArray) {
371                 std::map<STR_String,CValue*>::iterator it = m_pNamedPropertyArray->find(inName);
372                 if (it != m_pNamedPropertyArray->end())
373                         return (*it).second;
374         }
375         return NULL;
376 }
377
378 CValue* CValue::GetProperty(const char *inName)
379 {
380         if (m_pNamedPropertyArray) {
381                 std::map<STR_String,CValue*>::iterator it = m_pNamedPropertyArray->find(inName);
382                 if (it != m_pNamedPropertyArray->end())
383                         return (*it).second;
384         }
385         return NULL;
386 }
387
388 //
389 // Get text description of property with name <inName>, returns an empty string if there is no property named <inName>
390 //
391 STR_String CValue::GetPropertyText(const STR_String & inName,const STR_String& deftext)
392 {
393         CValue *property = GetProperty(inName);
394         if (property)
395                 return property->GetText();
396         else
397                 return deftext;//String::sEmpty;
398 }
399
400 float CValue::GetPropertyNumber(const STR_String& inName,float defnumber)
401 {
402         CValue *property = GetProperty(inName);
403         if (property)
404                 return property->GetNumber(); 
405         else
406                 return defnumber;
407 }
408
409
410
411 //
412 // Remove the property named <inName>, returns true if the property was succesfully removed, false if property was not found or could not be removed
413 //
414 bool CValue::RemoveProperty(const char *inName)
415 {
416         // Check if there are properties at all which can be removed
417         if (m_pNamedPropertyArray)
418         {
419                 std::map<STR_String,CValue*>::iterator it = m_pNamedPropertyArray->find(inName);
420                 if (it != m_pNamedPropertyArray->end())
421                 {
422                         ((*it).second)->Release();
423                         m_pNamedPropertyArray->erase(it);
424                         return true;
425                 }
426         }
427         
428         return false;
429 }
430
431 //
432 // Get Property Names
433 //
434 vector<STR_String> CValue::GetPropertyNames()
435 {
436         vector<STR_String> result;
437         if(!m_pNamedPropertyArray) return result;
438         result.reserve(m_pNamedPropertyArray->size());
439         
440         std::map<STR_String,CValue*>::iterator it;
441         for (it= m_pNamedPropertyArray->begin(); (it != m_pNamedPropertyArray->end()); it++)
442         {
443                 result.push_back((*it).first);
444         }
445         return result;
446 }
447
448 //
449 // Clear all properties
450 //
451 void CValue::ClearProperties()
452 {               
453         // Check if we have any properties
454         if (m_pNamedPropertyArray == NULL)
455                 return;
456
457         // Remove all properties
458         std::map<STR_String,CValue*>::iterator it;
459         for (it= m_pNamedPropertyArray->begin();(it != m_pNamedPropertyArray->end()); it++)
460         {
461                 CValue* tmpval = (*it).second;
462                 //STR_String name = (*it).first;
463                 tmpval->Release();
464         }
465
466         // Delete property array
467         delete m_pNamedPropertyArray;
468         m_pNamedPropertyArray=NULL;
469 }
470
471
472
473 //
474 // Set all properties' modified flag to <inModified>
475 //
476 void CValue::SetPropertiesModified(bool inModified)
477 {
478         if(!m_pNamedPropertyArray) return;
479         std::map<STR_String,CValue*>::iterator it;
480         
481         for (it= m_pNamedPropertyArray->begin();(it != m_pNamedPropertyArray->end()); it++)
482                 ((*it).second)->SetModified(inModified);
483 }
484
485
486
487 //
488 // Check if any of the properties in this value have been modified
489 //
490 bool CValue::IsAnyPropertyModified()
491 {
492         if(!m_pNamedPropertyArray) return false;
493         std::map<STR_String,CValue*>::iterator it;
494         
495         for (it= m_pNamedPropertyArray->begin();(it != m_pNamedPropertyArray->end()); it++)
496                 if (((*it).second)->IsModified())
497                         return true;
498         
499         return false;
500 }
501
502
503
504 //
505 // Get property number <inIndex>
506 //
507 CValue* CValue::GetProperty(int inIndex)
508 {
509
510         int count=0;
511         CValue* result = NULL;
512
513         if (m_pNamedPropertyArray)
514         {
515                 std::map<STR_String,CValue*>::iterator it;
516                 for (it= m_pNamedPropertyArray->begin(); (it != m_pNamedPropertyArray->end()); it++)
517                 {
518                         if (count++==inIndex)
519                         {
520                                 result = (*it).second;
521                                 break;
522                         }
523                 }
524
525         }
526         return result;
527 }
528
529
530
531 //
532 // Get the amount of properties assiocated with this value
533 //
534 int CValue::GetPropertyCount()
535 {
536         if (m_pNamedPropertyArray)
537                 return m_pNamedPropertyArray->size();
538         else
539                 return 0;
540 }
541
542
543
544
545
546 void CValue::CloneProperties(CValue *replica)
547 {
548         
549         if (m_pNamedPropertyArray)
550         {
551                 replica->m_pNamedPropertyArray=NULL;
552                 std::map<STR_String,CValue*>::iterator it;
553                 for (it= m_pNamedPropertyArray->begin(); (it != m_pNamedPropertyArray->end()); it++)
554                 {
555                         CValue *val = (*it).second->GetReplica();
556                         replica->SetProperty((*it).first,val);
557                         val->Release();
558                 }
559         }
560
561         
562 }
563
564 double*         CValue::GetVector3(bool bGetTransformedVec)
565 {
566         assertd(false); // don;t get vector from me
567         return m_sZeroVec;//::sZero;
568 }
569
570
571 /*---------------------------------------------------------------------------------------------------------------------
572         Reference Counting
573 ---------------------------------------------------------------------------------------------------------------------*/
574 //
575 // Add a reference to this value
576 //
577 CValue *CValue::AddRef()
578 {
579         // Increase global reference count, used to see at the end of the program
580         // if all CValue-derived classes have been dereferenced to 0
581         //debug(gRefCountValue++);
582 #ifdef _DEBUG
583         //gRefCountValue++;
584 #endif
585         m_refcount++; 
586         return this;
587 }
588
589
590
591 //
592 // Release a reference to this value (when reference count reaches 0, the value is removed from the heap)
593 //
594 int     CValue::Release()
595 {
596         // Decrease global reference count, used to see at the end of the program
597         // if all CValue-derived classes have been dereferenced to 0
598         //debug(gRefCountValue--);
599 #ifdef _DEBUG
600         //gRefCountValue--;
601 #endif
602         // Decrease local reference count, if it reaches 0 the object should be freed
603         if (--m_refcount > 0)
604         {
605                 // Reference count normal, return new reference count
606                 return m_refcount;
607         }
608         else
609         {
610                 // Reference count reached 0, delete ourselves and return 0
611 //              MT_assert(m_refcount==0, "Reference count reached sub-zero, object released too much");
612                 delete this;
613                 return 0;
614         }
615
616 }
617
618
619
620 //
621 // Disable reference counting for this value
622 //
623 void CValue::DisableRefCount()
624 {
625         assertd(m_refcount == 1);
626         m_refcount--;
627
628         //debug(gRefCountValue--);
629 #ifdef _DEBUG
630         //gRefCountValue--;
631 #endif
632         m_ValFlags.RefCountDisabled=true;
633 }
634
635
636
637 void CValue::AddDataToReplica(CValue *replica)
638 {
639         replica->m_refcount = 1;
640
641         //register with Python
642         _Py_NewReference(replica);
643
644 #ifdef _DEBUG
645         //gRefCountValue++;
646 #endif
647         replica->m_ValFlags.RefCountDisabled = false;
648
649         replica->ReplicaSetName(GetName());
650
651         //copy all props
652         CloneProperties(replica);
653 }
654
655
656
657 CValue* CValue::FindIdentifier(const STR_String& identifiername)
658 {
659
660         CValue* result = NULL;
661
662         int pos = 0;
663         // if a dot exists, explode the name into pieces to get the subcontext
664         if ((pos=identifiername.Find('.'))>=0)
665         {
666                 const STR_String rightstring = identifiername.Right(identifiername.Length() -1 - pos);
667                 const STR_String leftstring = identifiername.Left(pos);
668                 CValue* tempresult = GetProperty(leftstring);
669                 if (tempresult)
670                 {
671                         result=tempresult->FindIdentifier(rightstring);
672                 } 
673         } else
674         {
675                 result = GetProperty(identifiername);
676                 if (result)
677                         return result->AddRef();
678         }
679         if (!result)
680         {
681                 // warning here !!!
682                 result = new CErrorValue(identifiername+" not found");
683         }
684         return result;
685 }
686
687
688 #ifndef NO_EXP_PYTHON_EMBEDDING
689
690
691 static PyMethodDef      CValueMethods[] = 
692 {
693         //{ "new", CValue::PyMake , METH_VARARGS},
694         { NULL,NULL}    // Sentinel
695 };
696
697 PyAttributeDef CValue::Attributes[] = {
698         { NULL }        //Sentinel
699 };
700
701
702 PyObject*       CValue::py_getattro(PyObject *attr)
703 {
704         char *attr_str= PyString_AsString(attr);
705         CValue* resultattr = GetProperty(attr_str);
706         if (resultattr)
707         {
708                 PyObject* pyconvert = resultattr->ConvertValueToPython();
709         
710                 if (pyconvert)
711                         return pyconvert;
712                 else
713                         return resultattr; // also check if it's already in pythoninterpreter!
714         }
715         py_getattro_up(PyObjectPlus);
716 }
717
718 CValue* CValue::ConvertPythonToValue(PyObject* pyobj)
719 {
720
721         CValue* vallie = NULL;
722
723         if (PyList_Check(pyobj))
724         {
725                 CListValue* listval = new CListValue();
726                 bool error = false;
727
728                 int i;
729                 int numitems = PyList_Size(pyobj);
730                 for (i=0;i<numitems;i++)
731                 {
732                         PyObject* listitem = PyList_GetItem(pyobj,i); /* borrowed ref */
733                         CValue* listitemval = ConvertPythonToValue(listitem);
734                         if (listitemval)
735                         {
736                                 listval->Add(listitemval);
737                         } else
738                         {
739                                 error = true;
740                         }
741                 }
742                 if (!error)
743                 {
744                         // jippie! could be converted
745                         vallie = listval;
746                 } else
747                 {
748                         // list could not be converted... bad luck
749                         listval->Release();
750                 }
751
752         } else
753         if (PyFloat_Check(pyobj))
754         {
755                 vallie = new CFloatValue( (float)PyFloat_AsDouble(pyobj) );
756         } else
757         if (PyInt_Check(pyobj))
758         {
759                 vallie = new CIntValue( (cInt)PyInt_AS_LONG(pyobj) );
760         } else
761         if (PyLong_Check(pyobj))
762         {
763                 vallie = new CIntValue( (cInt)PyLong_AsLongLong(pyobj) );
764         } else
765         if (PyString_Check(pyobj))
766         {
767                 vallie = new CStringValue(PyString_AsString(pyobj),"");
768         } else
769         if (pyobj->ob_type==&CValue::Type || pyobj->ob_type==&CListValue::Type)
770         {
771                 vallie = ((CValue*) pyobj)->AddRef();
772         } else
773         {
774                 /* return an error value from the caller */
775                 PyErr_SetString(PyExc_TypeError, "This python value could not be assigned to a game engine property");
776         }
777         return vallie;
778
779 }
780
781 int     CValue::py_delattro(PyObject *attr)
782 {
783         char *attr_str= PyString_AsString(attr);
784         if (RemoveProperty(STR_String(attr_str)))
785                 return 0;
786         
787         PyErr_Format(PyExc_AttributeError, "attribute \"%s\" dosnt exist", attr_str);
788         return 1;
789 }
790
791 int     CValue::py_setattro(PyObject *attr, PyObject* pyobj)
792 {
793         CValue* vallie = ConvertPythonToValue(pyobj);
794         if (vallie)
795         {
796                 char *attr_str= PyString_AsString(attr);
797                 CValue* oldprop = GetProperty(attr_str);
798                 
799                 if (oldprop)
800                         oldprop->SetValue(vallie);
801                 else
802                         SetProperty(attr_str, vallie);
803                 
804                 vallie->Release();
805         } else
806         {
807                 return PY_SET_ATTR_FAIL; /* ConvertPythonToValue sets the error message */
808         }
809         
810         //PyObjectPlus::py_setattro(attr,value);
811         return PY_SET_ATTR_SUCCESS;
812 };
813
814 PyObject*       CValue::ConvertKeysToPython( void )
815 {
816         PyObject *pylist = PyList_New( 0 );
817         PyObject *pystr;
818         
819         if (m_pNamedPropertyArray)
820         {
821                 std::map<STR_String,CValue*>::iterator it;
822                 for (it= m_pNamedPropertyArray->begin(); (it != m_pNamedPropertyArray->end()); it++)
823                 {
824                         pystr = PyString_FromString( (*it).first );
825                         PyList_Append(pylist, pystr);
826                         Py_DECREF( pystr );
827                 }
828         }
829         return pylist;
830 }
831
832 /*
833 PyObject*       CValue::PyMake(PyObject* ignored,PyObject* args)
834 {
835
836         //if (!PyArg_ParseTuple(args,"s:make",&name)) return NULL;
837         Py_RETURN_NONE;//new CValue();
838 }
839 */
840
841 extern "C" {
842         void initCValue(void)
843         {
844                 Py_InitModule("CValue",CValueMethods);
845         }
846 }
847
848
849
850 #endif //NO_EXP_PYTHON_EMBEDDING
851
852 ///////////////////////////////////////////////////////////////////////////////////////////////
853 ///////////////////////////////////////////////////////////////////////////////////////////////
854 /* These implementations were moved out of the header */
855
856 void CValue::SetOwnerExpression(class CExpression* expr)
857 {
858         /* intentionally empty */
859 }
860
861 void CValue::SetColorOperator(VALUE_OPERATOR op)
862 {
863         /* intentionally empty */
864 }
865 void CValue::SetValue(CValue* newval)
866
867         // no one should get here
868         assertd(newval->GetNumber() == 10121969);       
869 }
870 ///////////////////////////////////////////////////////////////////////////////////////////////
871 ///////////////////////////////////////////////////////////////////////////////////////////////
872 /* deprecation warning management */
873 void CValue::SetDeprecationWarnings(bool ignoreDeprecationWarnings)
874 {
875         m_ignore_deprecation_warnings = ignoreDeprecationWarnings;
876 }
877
878 void CValue::ShowDeprecationWarning(const char* old_way,const char* new_way)
879 {
880         if (!m_ignore_deprecation_warnings) {
881                 printf("Method %s is deprecated, please use %s instead.\n", old_way, new_way);
882                 
883                 // import sys; print '\t%s:%d' % (sys._getframe(0).f_code.co_filename, sys._getframe(0).f_lineno)
884                 
885                 PyObject *getframe, *frame;
886                 PyObject *f_lineno, *f_code, *co_filename;
887                 
888                 getframe = PySys_GetObject("_getframe"); // borrowed
889                 if (getframe) {
890                         frame = PyObject_CallObject(getframe, NULL);
891                         if (frame) {
892                                 f_lineno= PyObject_GetAttrString(frame, "f_lineno");
893                                 f_code= PyObject_GetAttrString(frame, "f_code");
894                                 if (f_lineno && f_code) {
895                                         co_filename= PyObject_GetAttrString(f_code, "co_filename");
896                                         if (co_filename) {
897                                                 
898                                                 printf("\t%s:%d\n", PyString_AsString(co_filename), (int)PyInt_AsLong(f_lineno));
899                                                 
900                                                 Py_DECREF(f_lineno);
901                                                 Py_DECREF(f_code);
902                                                 Py_DECREF(co_filename);
903                                                 Py_DECREF(frame);
904                                                 return;
905                                         }
906                                 }
907                                 
908                                 Py_XDECREF(f_lineno);
909                                 Py_XDECREF(f_code);
910                                 Py_DECREF(frame);
911                         }
912                         
913                 }
914                 PyErr_Clear();
915                 printf("\tERROR - Could not access sys._getframe(0).f_lineno or sys._getframe().f_code.co_filename\n");
916         }
917 }
918