source: orange/source/orange/cls_value.cpp @ 8937:9645b18b2b07

Revision 8937:9645b18b2b07, 37.4 KB checked in by ales_erjavec <ales.erjavec@…>, 3 years ago (diff)

Fixed Value pickling in case the valueType is invalid (e.g. 127 if default Value is default constructed).
The pickled flags would in that case also signal that the value has svalV and would read from the otherValues (which is None).
This would raise an 'SystemError: Objects/listobject.c:182: bad argument to internal function'.

Line 
1/*
2    This file is part of Orange.
3   
4    Copyright 1996-2010 Faculty of Computer and Information Science, University of Ljubljana
5    Contact: janez.demsar@fri.uni-lj.si
6
7    Orange is free software: you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation, either version 3 of the License, or
10    (at your option) any later version.
11
12    Orange is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with Orange.  If not, see <http://www.gnu.org/licenses/>.
19*/
20
21
22#ifdef _MSC_VER
23 #pragma warning (disable : 4786 4114 4018 4267 4244)
24#endif
25
26#include "cls_value.hpp"
27#include "cls_orange.hpp"
28#include "vars.hpp"
29#include "stringvars.hpp"
30#include "pythonvars.hpp"
31#include "values.hpp"
32
33#include "vectortemplates.hpp"
34
35#include "externs.px"
36
37
38#define CHECK_VARIABLE \
39  if (!self->variable) PYERROR(PyExc_TypeError, "'variable' not set", PYNULL);
40
41#define CHECK_SPECIAL_OTHER \
42  if (self->value.isSpecial()) \
43    PYERROR(PyExc_TypeError, "attribute value unknown", PYNULL); \
44  if ((self->value.varType!=TValue::INTVAR) && (self->value.varType!=TValue::FLOATVAR)) \
45    PYERROR(PyExc_TypeError, "attribute is not an ordinary discrete or continuous", PYNULL);
46
47
48
49DATASTRUCTURE(Value - Orange.data.Value, TPyValue, 0)
50ABSTRACT(SomeValue - Orange.core.SomeValue, Orange)
51
52/* Converts a value into an appropriate python variable.
53   Behaves as convertToPythonNative(const TValue &, PVariable)
54   when the variable is not given. */
55
56PyObject *convertToPythonNative(const TValue &val)
57{ return convertToPythonNative(val, PVariable()); }
58
59
60
61/* Converts a value into an appropriate python variable.
62   Behaves as convertToPythonNative(const TValue &, PVariable);
63   variable can be there or not. */
64
65PyObject *convertToPythonNative(const TPyValue *value)
66{ return convertToPythonNative(value->value, value->variable); }
67
68
69
70/* Converts a value into an appropriate python variable.
71   If value is known (e.g. not DC, DK...)
72    - continuous values are returned as ordinary python floats
73    - discrete are returned as strings (variable is required)
74    - string values are returned as strings
75    - other values are return as ordinary orange objects
76   If value is special
77    - if the variable is given, its val2str is used to get a string
78    - if the variable is not given, '?', '~' and '.' are returned
79      for DK, DC and other, respectively.
80
81   FAILS if the value is discrete and variable is not given
82*/
83
84PyObject *convertToPythonNative(const TValue &val, PVariable var)
85{
86  if ((val.varType==TValue::FLOATVAR) && !val.isSpecial())
87    return PyFloat_FromDouble(double(val.floatV));
88
89  if (val.varType == PYTHONVAR) {
90    PyObject *res = val.svalV ? ((TPythonValue &)(val.svalV.getReference())).value : Py_None;
91    Py_INCREF(res);
92    return res;
93  }
94
95  if ((val.varType == STRINGVAR) && val.svalV) {
96    string s;
97    val.svalV.AS(TStringValue)->val2str(s);
98    return PyString_FromString(s.c_str());
99  }
100
101  if ((val.varType!=TValue::INTVAR) && val.svalV)
102    return WrapOrange((const_cast<TValue &>(val)).svalV);
103
104  if (var) { // && (val.varType == TValue::INTVAR || val.isSpecial)
105    string vs;
106    var->val2str(val, vs);
107    return PyString_FromString(vs.c_str());
108  }
109
110  if (val.isSpecial())
111    if (val.isDK())
112      return PyString_FromString("?");
113    else if (val.isDC()) 
114      return PyString_FromString("~");
115    else
116      return PyString_FromString(".");
117
118  PYERROR(PyExc_TypeError, "unknown value type", PYNULL);
119}
120
121
122/* The main routine for converting values from python to TValue.
123   If arguments are given as a
124   - Value, it is simply copied.
125       The variable is checked if given.
126   - SomeValue, it is copied as such.
127       If the variable is discrete or continuous, SomeValue must
128       be DiscDistribution or ContDistribution.
129   - string, we convert it to a value
130       The variable must be given unless the string is '?', '~'
131       (in this case INTVAR is ocnstructed)
132       We could return a StringValue here, but if user passes a
133       string without descriptor it is more probable that he just
134       forgot it. I doubt that many would construct StringValues.)
135   - int - if variable is given and is discrete, an integer value
136           is constructed. If the variable is derived from
137           EnumVariable the range is also tested
138         - if variable is given and is continuous, a continuous
139           value is constructed
140         - if variable is given and is of other type, an error is
141           raised
142         - if the variable is not given, an integer value is constructed
143   - float - a continuous value is constructed.
144       If the variable is given, it is checked that it is continuous
145   - other types: if it can be converted to float and the variable is
146       given and is continuous, a continuous value is constructed.
147       Otherwise, an exception is raised.         
148*/
149
150bool convertFromPython(PyObject *args, TValue &value, PVariable var)
151{
152  if (PyOrValue_Check(args)) {
153    if (var && PyValue_AS_Variable(args) && (PyValue_AS_Variable(args)!=var)) {
154      PyErr_Format(PyExc_TypeError, "wrong attribute value (expected value of '%s', got value of '%s')", var->get_name().c_str(), PyValue_AS_Variable(args)->get_name().c_str());
155      return false;
156    }
157    else
158      value = PyValue_AS_Value(args);
159    return true;
160  }
161
162  if (PyOrSomeValue_Check(args)) {
163    if (var) {
164      if ((var->varType==TValue::INTVAR) && !PyOrDiscDistribution_Check(args)) {
165        PyErr_Format(PyExc_TypeError, "attribute '%s' expects DiscDistribution, '%s' given", var->get_name().c_str(), args->ob_type->tp_name);
166        return false;
167      }
168      if ((var->varType==TValue::FLOATVAR) && !PyOrContDistribution_Check(args)) {
169        PyErr_Format(PyExc_TypeError, "attribute '%s' expects ContDistribution, '%s' given", var->get_name().c_str(), args->ob_type->tp_name);
170        return false;
171      }
172    }
173    int vtype;
174    if (PyOrDiscDistribution_Check(args))
175      vtype = TValue::INTVAR;
176    else if (PyOrContDistribution_Check(args))
177      vtype = TValue::FLOATVAR;
178    else if (PyOrStringValue_Check(args))
179      vtype = STRINGVAR;
180    else if (PyOrPythonValue_Check(args))
181      vtype = PYTHONVAR;
182    else
183      raiseError("unknovn variable type");
184
185    value = TValue(PyOrange_AsSomeValue(args), vtype);
186    return true;
187  }
188 
189  if (PyString_Check(args)) {
190    char *str = PyString_AsString(args);
191    if (var)
192      var->str2val(str, value);
193    else
194      if (!strcmp(str, "?"))
195        value = TValue(TValue::INTVAR, valueDK);
196      else if (!strcmp(str, "~"))
197        value = TValue(TValue::INTVAR, valueDC);
198      else {
199        PyErr_Format(PyExc_TypeError, "cannot convert '%s' to a value of an unknown attribute", str);
200        return false;
201      }
202    return true;
203  }
204 
205  if (var && var->varType == PYTHONVAR) {
206    value = TValue(mlnew TPythonValue(args), PYTHONVAR);
207    return true;
208  }
209 
210  if (args == Py_None) {
211    value = var ? var->DK() : TValue(TValue::INTVAR, valueDK);
212    return true;
213  }
214
215  if (PyInt_Check(args)) {
216    int ii = int(PyInt_AsLong(args));
217
218    if (var) {
219      if (var->varType == TValue::FLOATVAR) {
220        value = TValue(float(ii));
221        return true;
222      }
223
224      if (var->varType == TValue::INTVAR) {
225        if (var.is_derived_from(TEnumVariable)) {
226          int nv = var.AS(TEnumVariable)->noOfValues();
227          if (ii >= nv) {
228            PyErr_Format(PyExc_TypeError, "value index %i out of range (0 - %i)", ii, nv-1);
229            return false;
230          }
231        }
232
233        value = TValue(ii);
234        return true;
235      }
236
237      PyErr_Format(PyExc_TypeError,  "cannot convert an integer to a value of attribute '%s'", var->get_name().c_str());
238      return false;
239    }
240
241    value = TValue(ii);
242    return true;
243  }
244
245  if (PyFloat_Check(args)) {
246    if (var && (var->varType != TValue::FLOATVAR)) {
247      PyErr_Format(PyExc_TypeError,  "cannot convert a float to a value of attribute '%s'", var->get_name().c_str());
248      return false;
249    }
250
251    value = TValue(float(PyFloat_AsDouble(args)));
252    return true;
253  }
254
255  if (var && (var->varType == TValue::FLOATVAR)) {
256    PyObject *pyfloat = PyNumber_Float(args);
257    if (!pyfloat) {
258      PyErr_Format(PyExc_TypeError, "cannot convert an object of type '%s' to value of attribute '%s'", args->ob_type->tp_name, var->get_name().c_str());
259      return false;
260    }
261
262    value = TValue(float(PyFloat_AsDouble(pyfloat)));
263    Py_DECREF(pyfloat);
264    return true;
265  }
266
267  if (var)
268    PyErr_Format(PyExc_TypeError,  "cannot convert an object of type '%s' to value of attribute '%s'", args->ob_type->tp_name, var->get_name().c_str());
269  else
270    PyErr_Format(PyExc_TypeError,  "cannot convert an object of type '%s' to value of attribute", args->ob_type->tp_name);
271
272  return false;
273}
274
275
276/* Builds a TPyValue from arguments given in Python.
277   See Value_FromArguments for details. */
278
279bool convertFromPython(PyObject *args, TPyValue *&value)
280{
281  value = (TPyValue *)Value_FromArguments((PyTypeObject *)&PyOrValue_Type, args);
282  return value!=NULL;
283}
284
285
286
287/* The main constructor for TPyValue.
288   Gets a value and descriptor, allocates the memory and assigns fields. */
289
290PyObject *Value_FromVariableValueType(PyTypeObject *type, PVariable var, const TValue &val)
291{ 
292  TPyValue *value = PyObject_GC_New(TPyValue, type);
293  if (!value)
294    return PYNULL;
295
296  /* The below is needed since 'value' was allocated in C code, so it's
297     constructor has never been called and the below fields (wrapped pointers)
298     contain random data, which would lead to crash when trying to deallocate
299     them. */
300  value->value.svalV.init();
301  value->variable.init();
302
303  value->value = val;
304  value->variable = var;
305
306  PyObject_GC_Track(value);
307
308  return (PyObject *)value;
309}
310
311
312
313/* Constructs a value from arguments in Python. Arguments must be given as a tuple
314   with at least one element.
315   - If the single element is a variable, a DK() value for that attribute is returned
316   - Otherwise, it is converted using convertFromPython, without descriptor given
317
318   If there are two elements
319   - If one is variable, convertFromPython is used, passing the variable and the other
320   - Otherwise, both must be integers and are used for varType and valueType.
321*/
322
323PyObject *Value_FromArguments(PyTypeObject *type, PyObject *args)
324{   
325  PyTRY
326    PyObject *obj1;
327    PyObject *obj2 = NULL;
328
329    if (!PyArg_ParseTuple(args, "O|O:Value", &obj1, &obj2))
330      return PYNULL;
331
332    if (!obj2) {
333      if (PyOrVariable_Check(obj1))
334        return Value_FromVariableType(type, PyOrange_AsVariable(obj1));
335      else {
336        TValue val;
337        return convertFromPython(obj1, val) ? Value_FromValueType(type, val) : PYNULL;
338      }
339    }
340
341    TValue val;
342    if (PyOrVariable_Check(obj1)) {
343      const PVariable &var = PyOrange_AsVariable(obj1);
344      return convertFromPython(obj2, val, var) ? Value_FromVariableValueType(type, var, val) : PYNULL;
345    }
346    else if (PyOrVariable_Check(obj2)) {
347      const PVariable &var = PyOrange_AsVariable(obj2);
348      return convertFromPython(obj1, val, var) ? Value_FromVariableValueType(type, var, val) : PYNULL;
349    }
350    else if (PyInt_Check(obj1) && PyInt_Check(obj2)) {
351      int vartype = int(PyInt_AsLong(obj1));
352
353      if (vartype == STRINGVAR)
354        return Value_FromValueType(type, TValue(STRINGVAR, (signed char)PyInt_AsLong(obj2)));
355
356      if (vartype > TValue::FLOATVAR) {
357        PyErr_Format(PyExc_IndexError, "invalid value type (%i)", vartype);
358        return PYNULL;
359      }
360       
361      return Value_FromValueType(type, TValue((char)vartype, (signed char)PyInt_AsLong(obj2)));
362    }
363
364    PYERROR(PyExc_TypeError, "Value(): invalid arguments", PYNULL);
365  PyCATCH
366}
367
368
369
370
371PyObject *Value_new(PyTypeObject *type, PyObject *args, PyObject *keywords)  BASED_ON(ROOT, "([Variable], [int | float | Value | ...])")
372{ return Value_FromArguments(type, args); }
373
374
375void Value_dealloc(TPyValue *self)
376{ self->variable = PVariable();
377  self->value.~TValue();
378
379  if (PyObject_IsPointer(self)) {
380    PyObject_GC_UnTrack((PyObject *)self);
381    self->ob_type->tp_free((PyObject *)self); 
382  }
383}
384
385
386int Value_traverse(TPyValue *self, visitproc visit, void *arg)
387{ PVISIT(self->variable);
388  PVISIT(self->value.svalV);
389  return 0;
390}
391
392
393void Value_clear(TPyValue *self)
394{ self->variable=PVariable();
395  self->value.~TValue();
396}
397
398
399/* Returns a string representations for a value.
400   - If descriptor is given, its val2str should take care of everything
401   - If the value is special, we know that to do
402   - If value is
403     - FLOATVAR, convert a floatV
404     - INTVAR, print a intV in brackets
405     - else if svalV is given, it should take care of itself
406     - else, we return "###"
407*/
408
409char *pvs = NULL;
410const char *TPyValue2string(TPyValue *self)
411{ if (self->variable) {
412    string str;
413    self->variable->val2str(self->value, str);
414    pvs = (char *)realloc(pvs, str.size()+1);
415    strcpy(pvs, str.c_str());
416  }
417  else {
418    if (self->value.isDK())
419      return "?";
420    if (self->value.isDC())
421      return "~";
422    if (self->value.isSpecial())
423      return ".";
424
425    pvs = (char *)realloc(pvs, 16);
426    if (self->value.varType==TValue::FLOATVAR)
427      sprintf(pvs, "%f", self->value.floatV);
428    else if (self->value.varType==TValue::INTVAR)
429      sprintf(pvs, "<%i>", self->value.intV);
430    else if (self->value.svalV) {
431      string str;
432      self->value.svalV->val2str(str);
433      pvs = (char *)realloc(pvs, str.size()+1);
434      strcpy(pvs, str.c_str());
435    }
436    else
437      return "###";
438  }
439
440  return pvs;
441}
442
443
444
445/* Compares two values. The first is always TPyValue.
446   Comparisons of discrete are based on intV not on string representations
447   If both are TPyValue, the values must be of same type
448     - If both are special, they are equal/different if the valueType is
449       equal/different. Operators >, <, <= and >= are not defined.
450     - If only one is special, it's an error
451     - If they are discrete and descriptors are known but different,
452       each value's string representation is compared to the other's,
453       both comparisons are made and must give the same result.
454       If not, it's an error.
455     - Otherwise, intV's r floatV's are compared
456   If the other is an integer, it can be compared with discrete and
457     continuous attributes
458   If the other is a float, it can be compared with continuous attrs.
459   If the first value is special and the other is string "~" or "?",
460     they are compared as described above.
461   Otherwise, the descriptor for the first value must be known and is
462     used to convert the second value (if possible). The values are
463     then compared by the same rules as if both were PyValues
464     (except that both obviously have the same descriptor).
465*/
466
467#define errUndefinedIf(cond) if (cond) PYERROR(PyExc_TypeError, "Value.compare: cannot compare with undefined values", PYNULL);
468
469PyObject *richcmp_from_sign(const int &i, const int &op)
470{ int cmp;
471  switch (op) {
472        case Py_LT: cmp = (i<0); break;
473        case Py_LE: cmp = (i<=0); break;
474        case Py_EQ: cmp = (i==0); break;
475        case Py_NE: cmp = (i!=0); break;
476        case Py_GT: cmp = (i>0); break;
477        case Py_GE: cmp = (i>=0); break;
478    default:
479      Py_INCREF(Py_NotImplemented);
480      return Py_NotImplemented;
481  }
482 
483  PyObject *res;
484  if (cmp)
485    res = Py_True;
486  else
487    res = Py_False;
488  Py_INCREF(res);
489  return res;
490}
491
492
493PyObject *Value_richcmp(TPyValue *i, PyObject *j, int op)
494{ 
495  PyTRY
496
497    const TValue &val1 = i->value;
498
499    if (PyOrValue_Check(j)) {
500      const TValue &val2 = PyValue_AS_Value(j);
501
502      if (val1.varType != val2.varType)
503        PYERROR(PyExc_TypeError, "Value.compare: can't compare values of different types", PYNULL)
504
505      if (val1.isSpecial() || val2.isSpecial())
506        if ((op==Py_EQ) || (op==Py_NE)) {
507          PyObject *res = (val1.valueType==val2.valueType) == (op==Py_EQ) ? Py_True : Py_False;
508          Py_INCREF(res);
509          return res;
510        }
511        else {
512          Py_INCREF(Py_NotImplemented);
513          return Py_NotImplemented;
514        }
515
516      // Nominal values of different attributes are treated separately
517      PVariable &var1 = i->variable;
518      PVariable &var2 = PyValue_AS_Variable(j);
519      if ((val1.varType==TValue::INTVAR) && var1 && var2 && (var1 != var2)) {
520        TValue tempval;
521        string tempstr;
522
523        var2->val2str(val2, tempstr);
524        if (var1->str2val_try(tempstr, tempval)) {
525          int cmp1 = val1.compare(tempval);
526
527          var1->val2str(val1, tempstr);
528          if (var2->str2val_try(tempstr, tempval)) {
529            int cmp2 = tempval.compare(val2);
530            bool err = true;
531            switch (op) {
532              case Py_LE:
533              case Py_GE: err = ((cmp1*cmp2) == -1); break;
534              case Py_LT:
535              case Py_GT: err = (cmp1!=cmp2); break;
536              case Py_EQ:
537              case Py_NE: err = ((cmp1==0) != (cmp2==0)); break;
538            }
539
540            if (err)
541              PYERROR(PyExc_TypeError, "Value.compare: values are of different types and have different orders", PYNULL);
542          }
543
544          return richcmp_from_sign(cmp1, op);
545        }
546
547        var1->val2str(val1, tempstr);
548        if (var2->str2val_try(tempstr, tempval))
549          return richcmp_from_sign(tempval.compare(val2), op);
550
551        PYERROR(PyExc_TypeError, "Value.compare: values are of different types and cannot be compared", PYNULL);
552      }
553
554      // Not nominal OR both values or of the same attribute
555      return richcmp_from_sign(val1.compare(val2), op);
556    }
557
558
559    if (PyInt_Check(j)) {
560      errUndefinedIf(val1.isSpecial());
561
562      if (val1.varType==TValue::INTVAR)
563        return richcmp_from_sign(val1.intV - (int)PyInt_AsLong(j), op);
564      else if (val1.varType==TValue::FLOATVAR)
565        return richcmp_from_sign(sign(val1.floatV - (int)PyInt_AsLong(j)), op);
566    }
567
568    else if (PyFloat_Check(j)) {
569      errUndefinedIf(val1.isSpecial());
570      if (val1.varType==TValue::FLOATVAR)
571        return richcmp_from_sign(sign(val1.floatV - (float)PyFloat_AsDouble(j)), op);
572    }
573
574    else if (PyString_Check(j) && val1.isSpecial() && ((op==Py_EQ) || (op==Py_NE))) {
575      char *s = PyString_AsString(j);
576      PyObject *res = NULL;
577      if (!strcmp(s, "~"))
578        res = (val1.valueType==valueDC) == (op==Py_EQ) ? Py_True : Py_False;
579      else if (!strcmp(s, "?"))
580        res = (val1.valueType==valueDK) == (op==Py_EQ) ? Py_True : Py_False;
581      if (res) {
582        Py_INCREF(res);
583        return res;
584      }
585    }
586
587    if (i->variable) {
588      TValue val2;
589      if (!convertFromPython(j, val2, i->variable))
590        return PYNULL;
591
592      if (val1.isSpecial() || val2.isSpecial())
593        if ((op==Py_EQ) || (op==Py_NE)) {
594          PyObject *res = (val1.valueType==val2.valueType) == (op==Py_EQ) ? Py_True : Py_False;
595          Py_INCREF(res);
596          return res;
597        }
598        else {
599          Py_INCREF(Py_NotImplemented);
600          return Py_NotImplemented;
601        }
602
603      return richcmp_from_sign(val1.compare(val2), op);
604    }
605     
606    Py_INCREF(Py_NotImplemented);
607    return Py_NotImplemented;
608
609  PyCATCH
610}
611#undef errUndefinedIf
612
613
614
615PyObject *Value_str(TPyValue *self)
616{ PyTRY
617    return PyString_FromString(TPyValue2string(self)); 
618  PyCATCH
619}
620
621
622PyObject *Value_repr(TPyValue *self)
623{ PyTRY
624    if (self->variable)
625      return PyString_FromFormat("<orange.Value '%s'='%s'>", self->variable->get_name().c_str(), TPyValue2string(self));
626    else
627      return PyString_FromFormat("<orange.Value '%s'>", TPyValue2string(self)); 
628  PyCATCH
629}
630
631
632bool checkSpecial(TPyValue *self, char *casttype)
633{
634  if (self->value.isSpecial()) {
635    if (self->variable && self->variable->get_name().length())
636      PyErr_Format(PyExc_TypeError, "value of '%s' is unknown and cannot be %s", self->variable->get_name().c_str(), casttype);
637    else
638      PyErr_Format(PyExc_TypeError, "attribute value is unknown and cannot be %s", casttype);
639    return false;
640  }
641
642  return true;
643}
644
645PyObject *Value_int(TPyValue *self)
646{ PyTRY
647    if (!checkSpecial(self, "cast to an integer"))
648      return PYNULL;
649
650    return Py_BuildValue("i", (self->value.varType==TValue::INTVAR) ? self->value.intV : int(self->value.floatV)); 
651  PyCATCH
652}
653
654
655PyObject *Value_long(TPyValue *self)
656{ PyTRY
657    if (!checkSpecial(self, "cast to a long integer"))
658      return PYNULL;
659
660    return Py_BuildValue("l", (self->value.varType==TValue::INTVAR) ? long(self->value.intV) : long(self->value.floatV)); 
661  PyCATCH
662}
663
664
665PyObject *Value_float(TPyValue *self)
666{ PyTRY
667    if (!checkSpecial(self, "cast to a float"))
668      return PYNULL;
669
670    return Py_BuildValue("f", (self->value.varType==TValue::INTVAR) ? float(self->value.intV) : self->value.floatV); 
671  PyCATCH
672}
673
674
675inline bool checkForNumerical(const TValue &val1, const TValue &val2, const char *op)
676{
677  if (val1.isSpecial() || val2.isSpecial())
678    PYERROR(PyExc_TypeError, "cannot %s unknown values", false);
679  if ((val1.varType!=TValue::FLOATVAR) || (val2.varType!=TValue::FLOATVAR))
680    PYERROR(PyExc_TypeError, "cannot %s non-continuous values", false);
681  return true;
682}
683
684
685#define VALUEOP(opname,FUN,opverb) \
686PyObject *Value_##opname(TPyValue *self, PyObject *other) \
687{ PyTRY \
688    const TValue &val1 = self->value; \
689\
690    if (PyOrValue_Check(other)) { \
691      const TValue &val2 = PyValue_AS_Value(other); \
692      return checkForNumerical(val1, val2, opverb) ? PyFloat_FromDouble(val1.floatV FUN val2.floatV) : PYNULL; \
693    } \
694\
695    TValue val2; \
696    return convertFromPython(other, val2, self->variable) && checkForNumerical(val1, val2, opverb) ? PyFloat_FromDouble(val1.floatV FUN val2.floatV) : PYNULL; \
697  PyCATCH \
698}
699
700
701PyObject *Value_add(TPyValue *self, PyObject *other);
702PyObject *Value_sub(TPyValue *self, PyObject *other);
703PyObject *Value_mul(TPyValue *self, PyObject *other);
704PyObject *Value_div(TPyValue *self, PyObject *other);
705
706VALUEOP(add,+,"sum")
707VALUEOP(sub,-,"subtract")
708VALUEOP(mul,*,"multiply")
709VALUEOP(div,/,"divide")
710
711
712PyObject *Value_pow(TPyValue *self, PyObject *other, PyObject *)
713{ PyTRY
714    const TValue &val1 = self->value;
715   
716    if (!val1.isSpecial() && (val1.varType==TValue::FLOATVAR) && (val1.floatV<=0))
717      PYERROR(PyExc_TypeError, "negative base value", false);
718
719    if (PyOrValue_Check(other)) { 
720      const TValue &val2 = PyValue_AS_Value(other); 
721      return checkForNumerical(val1, val2, "add") ? PyFloat_FromDouble(exp(val2.floatV*log(val1.floatV))) : PYNULL;
722    }
723    else {
724      TValue val2; 
725      return    convertFromPython(other, val2, self->variable)
726             && checkForNumerical(val1, val2, "add")
727           ? PyFloat_FromDouble(exp(val2.floatV*log(val1.floatV)))
728           : PYNULL;
729    }
730  PyCATCH
731}
732
733
734PyObject *Value_neg(TPyValue *self)
735{ PyTRY
736    if (!checkSpecial(self, "negated"))
737      return PYNULL;
738
739    const TValue &val1 = self->value;
740    if (val1.varType!=TValue::FLOATVAR)
741      PYERROR(PyExc_TypeError, "cannot negate non-continuous value", false);
742    return PyFloat_FromDouble(-val1.floatV);
743  PyCATCH
744}
745
746
747PyObject *Value_abs(TPyValue *self)
748{ PyTRY
749    if (self->value.isSpecial())
750      if (self->variable && self->variable->get_name().length()) {
751        PyErr_Format(PyExc_TypeError, "cannot compute an absolute value of '%s' since its value is unknown", self->variable->get_name().c_str());
752        return PYNULL;
753      }
754      else
755        PYERROR(PyExc_TypeError, "cannot compute an absolute value of attribute since its value is unknown", PYNULL);
756
757    const TValue &val1 = self->value;
758    if (val1.varType!=TValue::FLOATVAR)
759      PYERROR(PyExc_TypeError, "cannot compute abs of non-continuous value", false);
760    return PyFloat_FromDouble(fabs(val1.floatV));
761  PyCATCH
762}
763
764
765int Value_nonzero(TPyValue *i)
766{ PyTRY
767    return !i->value.isSpecial();
768  PyCATCH_1
769}
770
771
772int Value_coerce(PyObject **i, PyObject **obj)
773{ PyTRY
774    if (PyString_Check(*obj)) {
775      *i = Value_str(*(TPyValue **)i);
776      if (!*i)
777        return -1;
778      Py_INCREF(*obj);
779      return 0;
780    }
781
782    if (PyInt_Check(*obj)) {
783      TPyValue *val = *(TPyValue **)i;
784      if (val->value.varType==TValue::INTVAR) {
785        *i = Value_int(val);
786        if (!*i)
787          return -1;
788        Py_INCREF(*obj);
789        return 0;
790      }
791      else if (val->value.varType==TValue::FLOATVAR) {
792        *i = Value_float(val);
793        if (!*i)
794          return -1;
795        double x = PyFloat_AsDouble(*obj);
796            *obj = PyFloat_FromDouble(x);
797        return 0;
798      }
799      else
800        return -1;
801    }
802
803    if (PyFloat_Check(*obj)) {
804      *i = Value_float(*(TPyValue **)i);
805      if (!*i)
806        return -1;
807      Py_INCREF(*obj);
808      return 0;
809    }
810
811    if (PyLong_Check(*obj)) {
812      *i = Value_long(*(TPyValue **)i);
813      if (!*i)
814        return -1;
815      Py_INCREF(*obj);
816      return 0;
817    }
818
819    return -1;
820  PyCATCH_1
821}
822
823
824
825PyObject *Value_get_svalue(TPyValue *self)
826{ PyTRY
827    if (self->value.varType == PYTHONVAR) {
828      PyObject *res = self->value.svalV ? ((TPythonValue &)(self->value.svalV.getReference())).value : Py_None;
829      Py_INCREF(res);
830      return res;
831    }
832
833    return WrapOrange(self->value.svalV);
834  PyCATCH
835}
836
837
838int Value_set_svalue(TPyValue *self, PyObject *arg)
839{ PyTRY
840
841    if (arg == Py_None) {
842      self->value.svalV = PSomeValue();
843      return 0;
844    }
845
846    if (PyOrSomeValue_Check(arg)) {
847      self->value.svalV = PyOrange_AsSomeValue(arg);
848      return 0;
849    }
850
851    self->value.svalV = mlnew TPythonValue(arg);
852    return 0;
853
854  PyCATCH_1
855}
856
857
858PyObject *Value_get_value(TPyValue *self)
859{ PyTRY
860    return convertToPythonNative(self);
861  PyCATCH
862}
863
864
865int Value_set_value(TPyValue *self, PyObject *arg)
866{ PyTRY
867    return convertFromPython(arg, self->value, self->variable) ? 0 : -1;
868  PyCATCH_1
869}
870
871
872PyObject *PyValue_Type_FromLong(long);
873
874PyObject *Value_get_valueType(TPyValue *self)
875{ return PyValue_Type_FromLong((long)self->value.valueType); }
876
877
878PyObject *Value_get_variable(TPyValue *self)
879{ return WrapOrange(self->variable); }
880
881
882int Value_set_variable(TPyValue *self, PyObject *arg)
883{ PyTRY
884    if (arg == Py_None) {
885      self->variable = PVariable();
886      return 0;
887    }
888    if (!PyOrVariable_Check(arg))
889      PYERROR(PyExc_TypeError, "invalid argument for attribute 'variable'", -1)
890    else {
891      self->variable = PyOrange_AsVariable(arg);
892      return 0;
893    }
894  PyCATCH_1
895}
896
897
898PyObject *PyVariable_Type_FromLong(long);
899
900PyObject *Value_get_varType(TPyValue *self)
901{ return PyVariable_Type_FromLong((long)self->value.varType); }
902
903
904
905
906char *value_underscores[][2] = {
907    {"firstvalue", "first_value"},
908    {"nextvalue", "next_value"},
909    {"randomvalue", "random_value"},
910    {"isDC", "is_DC"},
911    {"isDK", "is_DK"},
912    {"isSpecial", "is_special"},
913    {"varType", "var_type"},
914    {"valueType", "value_type"},   
915    {NULL, NULL}
916};
917
918PyObject *Value_getattr(PyObject *self, PyObject *name)
919{
920  char *orig = PyString_AsString(name);
921  for(char *(*ei)[2] = value_underscores; **ei; ei++) {
922      if (!strcmp(orig, **ei)) {
923          PyObject *trans = PyString_FromString((*ei)[1]);
924          PyObject *value = PyObject_GenericGetAttr((PyObject *)self, trans);
925          Py_DECREF(trans);
926          return value;
927      }
928  }
929
930  return PyObject_GenericGetAttr((PyObject *)self, name);
931
932}
933
934PyObject *Value_random_value(TPyValue *self) PYARGS(METH_NOARGS, "(); Sets the value to a random")
935{ PyTRY
936    CHECK_VARIABLE
937    self->value = self->variable->randomValue();
938    RETURN_NONE
939  PyCATCH
940}
941
942
943PyObject *Value_first_value(TPyValue *self)  PYARGS(METH_NOARGS, "() -> bool; Sets the value to the first value")
944{ PyTRY
945    CHECK_VARIABLE
946    return PyInt_FromLong(self->variable->firstValue(self->value) ? 1 : 0);
947  PyCATCH
948}
949
950
951PyObject *Value_next_value(TPyValue *self)  PYARGS(METH_NOARGS, "() -> bool; Increases the value (if possible)")
952{ PyTRY
953    CHECK_VARIABLE
954    return PyInt_FromLong(self->variable->nextValue(self->value) ? 1 : 0);
955  PyCATCH
956}
957
958
959PyObject *Value_isSpecial(TPyValue *self)  PYARGS(METH_NOARGS, "() -> bool; Returns true if value is DK, DC...")
960{ return PyInt_FromLong(self->value.isSpecial() ? 1 : 0); }
961
962
963PyObject *Value_isDK(TPyValue *self)  PYARGS(METH_NOARGS, "() -> bool; Returns true if value is DK")
964{ return PyInt_FromLong(self->value.isDK() ? 1 : 0); }
965
966
967PyObject *Value_isDC(TPyValue *self)  PYARGS(METH_NOARGS, "() -> bool; Returns true if value is DC")
968{ return PyInt_FromLong(self->value.isDC() ? 1 : 0); }
969
970
971PyObject *Value_native(TPyValue *self)   PYARGS(METH_NOARGS, "() -> bool; Converts the value into string or float")
972{ PyTRY
973    return convertToPythonNative(self);
974  PyCATCH
975}
976
977
978#include "slist.hpp"
979
980bool Value_pack(const TValue &value, TCharBuffer &buf, PyObject *&otherValues)
981{
982  const char svalFlag = value.svalV ? 1 << 5 : 0;
983  if (svalFlag) {
984    if (!otherValues)
985      otherValues = PyList_New(0);
986    PyObject *sv = WrapOrange(value.svalV);
987    PyList_Append(otherValues, sv);
988    Py_DECREF(sv);
989  }
990
991  if (value.valueType) {
992    buf.writeChar(svalFlag | (value.valueType & 0x1f));
993    return true;
994  }
995
996  if (value.varType == TValue::INTVAR) {
997    if (value.intV < (1 << (sizeof(char) << 3))) {
998      buf.writeChar((1 << 6) | svalFlag);
999      buf.writeChar(char(value.intV));
1000    }
1001
1002    else if (value.intV < (1 << (sizeof(short) << 3))) {
1003      buf.writeChar((2 << 6) | svalFlag);
1004      buf.writeShort((unsigned short)(value.intV));
1005    }
1006
1007    else {
1008      buf.writeChar((3 << 6) | svalFlag);
1009      buf.writeInt(value.intV);
1010    }
1011
1012    return true;
1013  }
1014
1015  else if (value.varType == TValue::FLOATVAR) {
1016    buf.writeChar(svalFlag);
1017    buf.writeFloat(value.floatV);
1018  }
1019
1020  else
1021    buf.writeChar(svalFlag);
1022
1023  return true;
1024}
1025
1026
1027bool Value_unpack(TValue &value, TCharBuffer &buf, PyObject *otherValues, int &otherValuesIndex)
1028{
1029  unsigned char flags = (unsigned char) buf.readChar();
1030
1031  if (flags & (1 << 5))
1032    value.svalV = PyOrange_AsSomeValue(PyList_GetItem(otherValues, otherValuesIndex++));
1033
1034  value.valueType = flags & 0x1f;
1035
1036  if (value.valueType) {
1037    value.floatV = numeric_limits<float>::quiet_NaN();
1038    value.intV = numeric_limits<int>::max();
1039    return true;
1040  }
1041
1042  if (value.varType == TValue::INTVAR) {
1043    flags >>= 6;
1044    if (flags == 1)
1045      value.intV = (unsigned char) buf.readChar();
1046    else if (flags == 2)
1047      value.intV = buf.readShort();
1048    else if (flags == 3)
1049      value.intV = buf.readInt();
1050    value.floatV = numeric_limits<float>::quiet_NaN();
1051  }
1052
1053  else if (value.varType == TValue::FLOATVAR) {
1054    value.floatV = buf.readFloat();
1055    value.intV = numeric_limits<int>::max();
1056  }
1057   
1058  return true;
1059}
1060
1061PyObject *Value__reduce__(PyObject *self)
1062{
1063  PyTRY
1064    TCharBuffer buf(16);
1065    PyObject *otherValues = NULL;
1066    buf.writeChar(PyValue_AS_Value(self).varType);
1067    Value_pack(PyValue_AS_Value(self), buf, otherValues);
1068    if (!otherValues) {
1069      otherValues = Py_None;
1070      Py_INCREF(otherValues);
1071    }
1072   
1073    return Py_BuildValue("O(Ns#N)", getExportedFunction("__pickleLoaderValue"),
1074                                   WrapOrange(PyValue_AS_Variable(self)),
1075                                   buf.buf, buf.length(),
1076                                   otherValues);
1077  PyCATCH
1078}
1079
1080
1081PyObject *__pickleLoaderValue(PyObject *, PyObject *args) PYARGS(METH_VARARGS, "(variable, packed_values, other_values)")
1082{
1083  PyTRY
1084    PVariable var;
1085    char *pbuf;
1086    int bufSize;
1087    PyObject *otherValues;
1088    if (!PyArg_ParseTuple(args, "O&s#O:__pickleLoaderValue", ccn_Variable, &var, &pbuf, &bufSize, &otherValues))
1089      return PYNULL;
1090
1091    TCharBuffer buf(pbuf);
1092    int otherValuesIndex = 0;
1093    TValue val((const unsigned char &)(buf.readChar()));
1094    Value_unpack(val, buf, otherValues, otherValuesIndex);
1095    return Value_FromVariableValue(var, val);
1096  PyCATCH
1097}
1098
1099#undef CHECK_VARIABLE
1100#undef CHECK_SPECIAL_OTHER
1101
1102
1103// This is in a separate file to avoid scanning by pyxtract
1104#include "valuelisttemplate.hpp"
1105
1106// Modified new and related stuff, removed rich_cmp (might be added later, but needs to be programmed specifically)
1107PValueList PValueList_FromArguments(PyObject *arg, PVariable var = PVariable())
1108{ return TValueListMethods::P_FromArguments(arg, var); }
1109
1110
1111PyObject *ValueList_FromArguments(PyTypeObject *type, PyObject *arg, PVariable var = PVariable())
1112{ return TValueListMethods::_FromArguments(type, arg, var); }
1113
1114
1115PyObject *ValueList_new(PyTypeObject *type, PyObject *arg, PyObject *kwds) BASED_ON(Orange, "(<list of Value>)")  ALLOWS_EMPTY
1116{ return TValueListMethods::_new(type, arg, kwds); }
1117
1118
1119PyObject *ValueList_getitem_sq(TPyOrange *self, Py_ssize_t index) { return TValueListMethods::_getitem(self, index); }
1120int       ValueList_setitem_sq(TPyOrange *self, Py_ssize_t index, PyObject *item) { return TValueListMethods::_setitem(self, index, item); }
1121PyObject *ValueList_getslice(TPyOrange *self, Py_ssize_t start, Py_ssize_t stop) { return TValueListMethods::_getslice(self, start, stop); }
1122int       ValueList_setslice(TPyOrange *self, Py_ssize_t start, Py_ssize_t stop, PyObject *item) { return TValueListMethods::_setslice(self, start, stop, item); }
1123Py_ssize_t ValueList_len_sq(TPyOrange *self) { return TValueListMethods::_len(self); }
1124PyObject *ValueList_concat(TPyOrange *self, PyObject *obj) { return TValueListMethods::_concat(self, obj); }
1125PyObject *ValueList_repeat(TPyOrange *self, Py_ssize_t times) { return TValueListMethods::_repeat(self, times); }
1126PyObject *ValueList_str(TPyOrange *self) { return TValueListMethods::_str(self); }
1127PyObject *ValueList_repr(TPyOrange *self) { return TValueListMethods::_str(self); }
1128int       ValueList_contains(TPyOrange *self, PyObject *obj) { return TValueListMethods::_contains(self, obj); }
1129PyObject *ValueList_append(TPyOrange *self, PyObject *item) PYARGS(METH_O, "(Value) -> None") { return TValueListMethods::_append(self, item); }
1130PyObject *ValueList_extend(TPyOrange *self, PyObject *obj) PYARGS(METH_O, "(sequence) -> None") { return TValueListMethods::_extend(self, obj); }
1131PyObject *ValueList_count(TPyOrange *self, PyObject *obj) PYARGS(METH_O, "(Value) -> int") { return TValueListMethods::_count(self, obj); }
1132PyObject *ValueList_filter(TPyOrange *self, PyObject *args) PYARGS(METH_VARARGS, "([filter-function]) -> ValueList") { return TValueListMethods::_filter(self, args); }
1133PyObject *ValueList_index(TPyOrange *self, PyObject *obj) PYARGS(METH_O, "(Value) -> int") { return TValueListMethods::_index(self, obj); }
1134PyObject *ValueList_insert(TPyOrange *self, PyObject *args) PYARGS(METH_VARARGS, "(index, item) -> None") { return TValueListMethods::_insert(self, args); }
1135PyObject *ValueList_native(TPyOrange *self) PYARGS(METH_NOARGS, "() -> list") { return TValueListMethods::_native(self); }
1136PyObject *ValueList_pop(TPyOrange *self, PyObject *args) PYARGS(METH_VARARGS, "() -> Value") { return TValueListMethods::_pop(self, args); }
1137PyObject *ValueList_remove(TPyOrange *self, PyObject *obj) PYARGS(METH_O, "(Value) -> None") { return TValueListMethods::_remove(self, obj); }
1138PyObject *ValueList_reverse(TPyOrange *self) PYARGS(METH_NOARGS, "() -> None") { return TValueListMethods::_reverse(self); }
1139PyObject *ValueList_sort(TPyOrange *self, PyObject *args) PYARGS(METH_VARARGS, "([cmp-func]) -> None") { return TValueListMethods::_sort(self, args); }
1140PyObject *ValueList__reduce__(TPyOrange *self, PyObject *) { return TValueListMethods::_reduce(self); }
1141
1142
1143
1144PyObject *VarTypes()
1145{ PyObject *vartypes=PyModule_New("Orange.data.Type");
1146  PyModule_AddObject(vartypes, "None", PyVariable_Type_FromLong((int)TValue::NONE));
1147  PyModule_AddObject(vartypes, "Discrete", PyVariable_Type_FromLong((int)TValue::INTVAR));
1148  PyModule_AddObject(vartypes, "Continuous", PyVariable_Type_FromLong((int)TValue::FLOATVAR));
1149  PyModule_AddObject(vartypes, "Other", PyVariable_Type_FromLong((int)TValue::FLOATVAR+1)); // for compatibility; don't use!
1150  PyModule_AddObject(vartypes, "String", PyVariable_Type_FromLong((int)STRINGVAR));
1151  return vartypes;
1152}
1153
1154/* Left here for compatibility */
1155
1156PYCONSTANTFUNC(VarTypes, VarTypes)
1157
1158/* This cannot be done in the header since Value is not derived from Orange */
1159
1160TNamedConstantsDef Value_Type_values[] = {{"Regular", 0}, {"DC", valueDC}, {"DK", valueDK}, {0, 0}};
1161
1162PYXTRACT_IGNORE static PyObject *Value_Type_repr(PyObject *self)
1163{
1164  return stringFromList(self, Value_Type_values);
1165}
1166
1167PYXTRACT_IGNORE PyObject *Value_Type__reduce__(PyObject *self);
1168PyMethodDef Value_Type_methods[] = { {"__reduce__", (binaryfunc)Value_Type__reduce__, METH_NOARGS, "reduce"}, {NULL, NULL}};
1169PyTypeObject PyValue_Type_Type = {PyObject_HEAD_INIT(&PyType_Type) 0, "Value.Type", sizeof(PyIntObject), 0, 0, 0, 0, 0, 0, (reprfunc)Value_Type_repr, 0, 0, 0, 0, 0, (reprfunc)Value_Type_repr, 0, 0, 0, Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES, 0, 0, 0, 0, 0, 0, 0, Value_Type_methods, 0, 0, &PyInt_Type};
1170
1171PyObject *PyValue_Type_FromLong(long ok)
1172{ PyIntObject *r = PyObject_New(PyIntObject, &PyValue_Type_Type);
1173  r->ob_ival = ok;
1174  return (PyObject *)r;
1175}
1176
1177void *PTValue_Type(void *l)
1178{ return PyValue_Type_FromLong(*(long *)l); }
1179
1180
1181PYXTRACT_IGNORE PyObject *Value_Type__reduce__(PyObject *self)
1182{ return Py_BuildValue("O(i)", getExportedFunction("__pickleLoaderValueType"), ((PyIntObject *)(self))->ob_ival); }
1183
1184PyObject *__pickleLoaderValueType(PyObject *, PyObject *args) PYARGS(METH_O, "")
1185{ return PyValue_Type_FromLong(PyInt_AsLong(args)); }
1186
1187/* Left for backward compatibility; also used the opportunity to initialize the type */
1188
1189PyObject *ValueTypes()
1190{ PyType_Ready(&PyValue_Type_Type);
1191  PyValue_Type_Type.tp_print = 0;
1192  PyObject *valuetypes=PyModule_New("ValueTypes");
1193  PyModule_AddObject(valuetypes, "Regular", PyValue_Type_FromLong(valueRegular));
1194  PyModule_AddObject(valuetypes, "DC", PyValue_Type_FromLong(valueDC));
1195  PyModule_AddObject(valuetypes, "DK", PyValue_Type_FromLong(valueDK));
1196  return valuetypes;
1197}
1198
1199PYCONSTANTFUNC(ValueTypes, ValueTypes)
1200
1201PYCLASSCONSTANT(Value, Regular, PyValue_Type_FromLong(valueRegular))
1202PYCLASSCONSTANT(Value, DC, PyValue_Type_FromLong(valueDC))
1203PYCLASSCONSTANT(Value, DK, PyValue_Type_FromLong(valueDK))
1204
1205#include "cls_value.px"
Note: See TracBrowser for help on using the repository browser.