source: orange/source/orange/cls_example.cpp @ 10960:2bb772691bd8

Revision 10960:2bb772691bd8, 34.8 KB checked in by Ales Erjavec <ales.erjavec@…>, 21 months ago (diff)

Fixes for clang compiler support.

Added 'TOrangeVector::classDescription()' specialization to
'DEFINE_TOrangeVector_classDescription' macro and removed its default implementation
in the template class (static 'st_classDescription' member must be initialized/specialized before
its use).

A similar problem arises in the included '.ppp' files where st_classDescription is used. So I
moved all '.ppp. includes after the "DEFINE_*"s.

Removed unnecessary/duplicate VWRAPPER/WRAPPER uses.

Added 'this->...' qualifier in template classes (that inherit a from a template class) for
accessing base class methods, otherwise clang does not find them (as per C++ standard).

Moved the TVarList and TAttributed*List definitions/implementations from 'orvector' to 'vars'.
Fixed includes in other files using the two headers accordingly.

Fixed some casts to int with more appropriate casts to size_t/uintptr_t.

Added explicit casts of constants to template class in include/stat.hpp
statistics functions.

(references #1219).

RevLine 
[34]1/*
2    This file is part of Orange.
[6531]3   
4    Copyright 1996-2010 Faculty of Computer and Information Science, University of Ljubljana
5    Contact: janez.demsar@fri.uni-lj.si
[34]6
[6531]7    Orange is free software: you can redistribute it and/or modify
[34]8    it under the terms of the GNU General Public License as published by
[6531]9    the Free Software Foundation, either version 3 of the License, or
[34]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
[6531]18    along with Orange.  If not, see <http://www.gnu.org/licenses/>.
[34]19*/
20
21
[1337]22#include "orange.hpp"
[34]23
24class TMLClassDefinition;
25extern TMLClassDefinition MLDef_Domain;
26extern TMLClassDefinition MLDef_Variable;
27
28#include "vars.hpp"
29#include "domain.hpp"
30#include "examples.hpp"
31
32#include "cls_value.hpp"
33#include "cls_example.hpp"
34#include "cls_orange.hpp"
35#include "lib_kernel.hpp"
[62]36#include "converts.hpp"
[34]37
38#include "externs.px"
39
40
[7715]41DATASTRUCTURE(Example - Orange.data.Instance, TPyExample, 0)
[34]42
43
44bool convertFromPythonExisting(PyObject *lst, TExample &example)
45{
46  PDomain dom=example.domain;
47
[224]48  if (PyOrExample_Check(lst)) {
49    const TExample &orex = PyExample_AS_ExampleReference(lst);
50    if (orex.domain != dom)
[234]51      dom->convert(example, orex);
52    else
53      example = orex;
54    return true;
[224]55  }
56
[34]57  if (!PyList_Check(lst)) {
58    PyErr_Format(PyExc_TypeError, "invalid argument type (expected list, got '%s)", lst ? lst->ob_type->tp_name : "None");
59    return false;
60  }
61
[10588]62  int const nvars = dom->variables->size() + dom->classVars->size();
63  if (Py_ssize_t(nvars) != PyList_Size(lst)) {
64    PyErr_Format(PyExc_IndexError, "invalid list size (got %i, expected %i items)",
65        PyList_Size(lst), nvars);
[34]66    return false;
67  }
68
[6239]69  Py_ssize_t pos = 0;
[34]70  TExample::iterator ei(example.begin());
[10588]71  TVarList::iterator vi(dom->variables->begin());
72  TVarList::const_iterator const ve(dom->variables->end());
73  TVarList::const_iterator const ce(dom->classVars->end());
[10747]74  while(vi != ce && vi != ve) {
[34]75    PyObject *li=PyList_GetItem(lst, pos++);
76    if (!li)
77      PYERROR(PyExc_SystemError, "can't read the list", false);
78
79    if (PyOrValue_Check(li))
80      if (PyValue_AS_Variable(li) ? (PyValue_AS_Variable(li) != *vi) : (PyValue_AS_Value(li).varType=!(*vi)->varType) ) {
[7665]81        PyErr_Format(PyExc_TypeError, "wrong value type for attribute no. %i (%s)", pos, (*vi)->get_name().c_str());
[34]82        return false;
83      }
84      else
85        *(ei++)=PyValue_AS_Value(li);
86
87    else {
[5674]88      if (li == Py_None) {
89        *(ei++) = (*vi)->DK();
90      }
91       
92      else if (PyString_Check(li))
[34]93          (*vi)->str2val(string(PyString_AsString(li)), *(ei++));
94
95      else if ((*vi)->varType==TValue::INTVAR) {
96        if (PyInt_Check(li))
97          *(ei++)=TValue(int(PyInt_AsLong(li)));
98        else {
[7665]99          PyErr_Format(PyExc_TypeError, "attribute no. %i (%s) is ordinal, string value expected", pos, (*vi)->get_name().c_str());
[34]100          return false;
101        }
102      }
103      else if ((*vi)->varType==TValue::FLOATVAR) {
[281]104        float f;
105        if (PyNumber_ToFloat(li, f))
106          *(ei++) = TValue(f);
[34]107        else {
[7665]108          PyErr_Format(PyExc_TypeError, "attribute no. %i (%s) is continuous, float value expected", pos, (*vi)->get_name().c_str());
[34]109          return false;
110        }
111      }
112      else
113        ei++;
114    }
[10588]115    if (++vi == ve) {
116        vi = dom->classVars->begin();
117    }
[34]118  }
119
120  return true;
121}
122
123
124bool convertFromPython(PyObject *lst, TExample &example, PDomain dom)
125{ example=TExample(dom);
126  return convertFromPythonExisting(lst, example);
127}
128
129
[113]130int cc_Example(PyObject *obj, void *ptr)
131{ if (!PyOrExample_Check(obj))
132    return 0;
133  *(PExample *)(ptr) = PyExample_AS_Example(obj);
134  return 1;
135}
136
137int ccn_Example(PyObject *obj, void *ptr)
138{ if (obj == Py_None) {
139    *(PExample *)(ptr) = PExample();
140    return 1;
141  }
142  else
143    return cc_Example(obj, ptr);
144}
145
146
147int ptr_Example(PyObject *obj, void *ptr)
148{ if (!PyOrExample_Check(obj))
149    return 0;
150  *(TExample **)(ptr) = PyExample_AS_Example(obj).getUnwrappedPtr();
151  return 1;
152}
153
154int ptrn_Example(PyObject *obj, void *ptr)
155{ if (obj == Py_None) {
156    *(TExample **)(ptr) = NULL;
157    return 1;
158  }
159  else
160    return ptr_Example(obj, ptr);
161}
162
163
[34]164PyObject *Example_FromExample(PyTypeObject *type, PExample example, POrange lock)
165{ TPyExample *self=PyObject_GC_New(TPyExample, type);
166  self->example.init();
167  self->lock.init();
168  self->example = example;
169  self->lock = lock;
170  PyObject_GC_Track(self);
171  return (PyObject *)self;
172}
173
174
175void Example_dealloc(TPyExample *self)
176{ self->lock.~POrange();
177  self->example.~PExample();
178  /* Should not call tp_free if it is a reference
179     Destructor is also called by exit proc, not by wrapped */
180  if (PyObject_IsPointer(self)) {
181    PyObject_GC_UnTrack((PyObject *)self);
182    self->ob_type->tp_free((PyObject *)self); 
183  }
184}
185
186
187int Example_traverse(TPyExample *self, visitproc visit, void *arg)
188{ PVISIT(self->lock)
189  if (!self->lock) // don't visit if it's a reference!
190    PVISIT(self->example);
191
192  return 0;
193}
194
195int Example_clear(TPyExample *self)
196{ self->lock=POrange();
197  self->example=PExample();
198  return 0;
199}
200
201
[834]202bool readBoolFlag(PyObject *keywords, char *flag);
203
[7663]204CONSTRUCTOR_KEYWORDS(Example, "filterMetas filter_metas")
[834]205
206
207PyObject *Example_new(PyTypeObject *type, PyObject *args, PyObject *keywords) BASED_ON(ROOT, "(domain, [list of values])")
[34]208{ PyTRY
209    PyObject *list=PYNULL;
210    PDomain dom;
211
[224]212    if (PyArg_ParseTuple(args, "O&|O", cc_Domain, &dom, &list)) {
213      if (list && PyOrExample_Check(list)) {
[7663]214        PExample ex = mlnew TExample(dom, PyExample_AS_Example(list).getReference(), readBoolFlag(keywords, "filterMetas") || readBoolFlag(keywords, "filter_metas"));
[224]215        return Example_FromWrappedExample(ex);
216      }
[34]217
[224]218      PyObject *example = Example_FromDomain(dom);
219     
[580]220      if (list) {
221        if (PyList_Check(list) && PyList_Size(list) && PyOrExample_Check(PyList_GET_ITEM(list, 0))) {
222          TExampleList elist;
223          PyObject *iterator = PyObject_GetIter(list);
[581]224          PyObject *item = PyIter_Next(iterator);
225          for(; item; item = PyIter_Next(iterator)) {
[580]226            if (!PyOrExample_Check(item)) {
227              Py_DECREF(item);
228              break;
229            }
230            elist.push_back(PyExample_AS_Example(item));
231            Py_DECREF(item);
232          }
233          Py_DECREF(iterator);
234          if (item)
235            raiseError("invalid elements in list for example join");
236          else {
237            PExample ex = mlnew TExample(dom, PExampleList(elist));
238            return Example_FromWrappedExample(ex);
239          }
240        }
241        else if (!convertFromPythonExisting(list, PyExample_AS_ExampleReference(example))) {
[1091]242          Py_DECREF(example);
[580]243          return PYNULL;
244        }
[224]245      }
246
247      return example;
248    }
249
250    PyErr_Clear();
251
252    PExample example;
[4928]253    int keepId = 0;
254    if (PyArg_ParseTuple(args, "O&|i", cc_Example, &example, &keepId)) {
[224]255      PExample ex = mlnew TExample(example.getReference());
[4928]256      if (!keepId)
257        ex->id = getExampleId();
[34]258      return Example_FromWrappedExample(ex);
259    }
260     
[224]261    PYERROR(PyExc_TypeError, "domain and (optionally) list arguments accepted", PYNULL);
[34]262  PyCATCH
263}
264
265
266
267int getMetaIdFromPy(PExample example, PyObject *index, PVariable &var)
268{ if (PyInt_Check(index)) {
269    int idx=PyInt_AsLong(index);
270    var=example->domain->getMetaVar(idx, false); // it may also be NULL
271    return idx;
272  }
273  else if (PyString_Check(index)) {
[90]274    TMetaDescriptor const *desc=example->domain->metas[string(PyString_AsString(index))];
[34]275    if (!desc) {
276      PyErr_Format(PyExc_IndexError, "invalid meta variable name '%s'", PyString_AsString(index));
277      return 0;
278    }
279    var=desc->variable;
280    return desc->id;
281  }
282  else if (PyOrVariable_Check(index)) {
283    var = PyOrange_AsVariable(index);
284    int idx = example->domain->getMetaNum(var, false);
[131]285    if (idx == ILLEGAL_INT)
[34]286      PYERROR(PyExc_IndexError, "invalid meta variable", 0);
287    return idx;
288  }
289
290  PYERROR(PyExc_IndexError, "invalid meta variable", 0);
291}
292
293
[250]294int weightIndex(const TExample &example, PyObject *pyindex)
295{
296  if (pyindex == Py_None)
297    return 0;
298
299  if (PyInt_Check(pyindex))
300    return (int)PyInt_AsLong(pyindex);
301
302  PVariable var = varFromArg_byDomain(pyindex, example.domain);
303  if (!var) 
304    PYERROR(PyExc_TypeError, "invalid arguments or unknown attribute", ILLEGAL_INT);
305
306  return example.domain->getVarNum(var);
307}
308
309
[2123]310PyObject *Example_reference(TPyExample *pex) PYARGS(METH_NOARGS, "unique reference (pointer to) the object")
311{
[10960]312  return PyInt_FromSize_t(size_t(&PyExample_AS_ExampleReference(pex)));
[2123]313}
314
315
[7654]316PyObject *Example_get_weight(TPyExample *pex, PyObject *pyindex) PYARGS(METH_O, "(id) -> weight; Returns example's weight")
[250]317{
318  PyTRY
319    const TExample &example = PyExample_AS_ExampleReference(pex);
320    int index = weightIndex(example, pyindex);
321    if (index == ILLEGAL_INT)
322      return PYNULL;
[34]323
324    if (!index)
325      return PyFloat_FromDouble(1.0);
326
[250]327    TValue val = example.getMeta(index);
[34]328    if (val.isSpecial() || (val.varType!=TValue::FLOATVAR))
329      PYERROR(PyExc_TypeError, "invalid weight", PYNULL);
330
331    return PyFloat_FromDouble((double)val.floatV);
332  PyCATCH
333}
334
335
[7654]336PyObject *Example_set_weight(TPyExample *pex, PyObject *args) PYARGS(METH_VARARGS, "(id[, weight]); Sets example's weight to given value")
[34]337{ PyTRY
[250]338    PyObject *pyindex;
[34]339    float weight = 1;
340
[250]341    if (!PyArg_ParseTuple(args, "O|f:setweight", &pyindex, &weight))
[34]342      return PYNULL;
[250]343
344    TExample &example = PyExample_AS_ExampleReference(pex);
345    int index = weightIndex(example, pyindex);
346
347    if (index == ILLEGAL_INT)
348      return PYNULL;
349
350    if (index>0)
[34]351      PYERROR(PyExc_IndexError, "Example.setweight: invalid weight id", PYNULL);     
352
[250]353    if (index)
354      example.setMeta(index, TValue(weight));
[34]355
356    RETURN_NONE;
357  PyCATCH
358}
359
360
[7654]361PyObject *Example_remove_weight(TPyExample *pex, PyObject *pyindex) PYARGS(METH_O, "(id); Removes examples's weight")
[34]362{ PyTRY
[250]363    TExample &example = PyExample_AS_ExampleReference(pex);
364    int index = weightIndex(example, pyindex);
[34]365
[250]366    if (index == ILLEGAL_INT)
367      return PYNULL;
[34]368
[239]369    if (index>0)
[34]370      PYERROR(PyExc_IndexError, "Example.setweight: invalid weight id", PYNULL);     
371
[250]372    if (index)
373      example.removeMeta(index);
374
[34]375    RETURN_NONE;
376  PyCATCH
377}
378
379
[7654]380PyObject *Example_get_meta(TPyExample *pex, PyObject *index) PYARGS(METH_O, "(id | var) -> Value; Gets a meta-value")
[34]381{ PyTRY
382    PVariable var;
383    int idx = getMetaIdFromPy(PyExample_AS_Example(pex), index, var);
384    if (!idx)
385      return PYNULL; 
386
[131]387    return convertToPythonNative(PyExample_AS_Example(pex)->getMeta(idx), var);
[580]388
389    // This could be better, but I wouldn't dare to change this
390    // return Value_FromVariableValue(var, PyExample_AS_Example(pex)->getMeta(idx));
[34]391  PyCATCH
392}
393
394
[7654]395PyObject *Example_get_metas(TPyExample *pex, PyObject *args) PYARGS(METH_VARARGS, "([key-type]) -> dictionary with a copy of example's meta attributes")
[2664]396{
397  PyTRY
[4610]398    PyObject *pyoptional = NULL;
[6443]399    PyTypeObject *keytype = NULL;
[4357]400    int optional = ILLEGAL_INT;
[4610]401    if (!PyArg_ParseTuple(args, "|OO:Example.getmetas", &pyoptional, &keytype))
[2664]402      return NULL;
403
[6443]404    if (!keytype) {
405      if (pyoptional && PyType_Check(pyoptional)) {
406        keytype = (PyTypeObject *)pyoptional;
407        pyoptional = NULL;
408      }
409      else {
410        keytype = &PyInt_Type;
411      }
[4610]412    }
413   
414    if (pyoptional) {
415      if (!PyInt_Check(pyoptional)) {
416        PyErr_Format(PyExc_TypeError, "invalid type for argument 'optional' (expected int, got '%s')", pyoptional->ob_type->tp_name);
417        return NULL;
418      }
419      optional = PyInt_AsLong(pyoptional);
420    }
421   
[2664]422    if ((keytype != &PyInt_Type) && (keytype != &PyString_Type) && (keytype != (PyTypeObject *)&PyOrVariable_Type))
423      PYERROR(PyExc_TypeError, "invalid key type (should be nothing, int, str, or orange.Variable)", NULL);
424     
425    PExample ex = PyExample_AS_Example(pex);
426    const TDomain &dom = ex->domain.getReference();
427
428    PyObject *res = PyDict_New();
429
430    try {
431      const_ITERATE(TMetaValues, mi, ex->meta) {
[4357]432        const TMetaDescriptor *md = dom.getMetaDescriptor(mi->first, false);
433       
434        if ((optional != ILLEGAL_INT) && (!md || (md->optional != optional)))
435          continue;
436       
[2664]437        PyObject *key;
[4357]438        PVariable variable = md ? md->variable : PVariable();
439       
[2664]440        if (keytype == &PyInt_Type)
441          key = PyInt_FromLong(mi->first);
442        else {
443          if (!variable)
444            continue;
445          if (keytype == &PyString_Type)
[7665]446            key = PyString_FromString(variable->get_name().c_str());
[2664]447          else
448            key = WrapOrange(variable);
449        }
450
451        PyObject *value = Value_FromVariableValue(variable, mi->second);
452        PyDict_SetItem(res, key, value);
453        Py_DECREF(key);
454        Py_DECREF(value);
455      }
456
457      return res;
458    }
459    catch (...) {
460      Py_DECREF(res);
461      throw;
462    }
463
464  PyCATCH
465
466}
467
468
[7654]469PyObject *Example_has_meta(TPyExample *pex, PyObject *index) PYARGS(METH_O, "(id | var) -> bool")
[1995]470{ PyTRY
471    PVariable var;
472    int idx = getMetaIdFromPy(PyExample_AS_Example(pex), index, var);
473    PyErr_Clear();
474    return PyInt_FromLong(idx && PyExample_AS_Example(pex)->hasMeta(idx) ? 1 : 0);
475  PyCATCH
476}
477
478
[7654]479PyObject *Example_set_value(TPyExample *pex, PyObject *vala) PYARGS(METH_O, "(Value) -> None")
[250]480{ PyTRY
481    if (!PyOrValue_Check(vala))
482      PYERROR(PyExc_TypeError, "Example.setvalue: orange.Value expected", PYNULL);
483
484    PVariable var = PyValue_AS_Variable(vala);
485    if (!var)
486      PYERROR(PyExc_TypeError, "Example.setvalue: values 'variable' should not be None", PYNULL);
487
488    PExample example=PyExample_AS_Example(pex);
489    int idx = example->domain->getVarNum(var);
490
491    if (idx>=0)
492      example->operator[](idx) = PyValue_AS_Value(vala);
493    else
494      example->setMeta(idx, PyValue_AS_Value(vala));
495
496    RETURN_NONE;
497  PyCATCH
498}
499
500
[7654]501PyObject *Example_set_meta(TPyExample *pex, PyObject *args) PYARGS(METH_VARARGS, "(Value, int) | (variable, value); Sets a meta-value")
[34]502{ PyTRY
503    PExample example=PyExample_AS_Example(pex);
504 
505    PyObject *par1, *par2=PYNULL;
506    if (!PyArg_ParseTuple(args, "O|O", &par1, &par2))
507      PYERROR(PyExc_TypeError, "invalid arguments", PYNULL);
508
509    int idx=0;
510
511    if (PyOrValue_Check(par1)) {
512      // first parameter is a PyValue
513      // second parameter is an index and is accepted iff variable not among domain's meta variables
514      TMetaDescriptor *desc=PyValue_AS_Variable(par1) ? example->domain->metas[PyValue_AS_Variable(par1)] : (TMetaDescriptor *)NULL;
515      if (desc) 
516        if (par2)
517          PYERROR(PyExc_TypeError, "second argument (index) not expected", PYNULL)
518        else
519          idx=desc->id;
520      else
521       if (!par2)
522         PYERROR(PyExc_TypeError, "second argument (index) needed", PYNULL)
523       else
524         if (!PyInt_Check(par2))
525           PYERROR(PyExc_TypeError, "invalid index type (int expected)", PYNULL)
[224]526         else {
527           idx = int(PyInt_AsLong(par2));
528           if (idx>=0)
529             PYERROR(PyExc_TypeError, "invalid meta-id index (negative integer expected)", PYNULL);
530         }
[34]531
[131]532      example->setMeta(idx, PyValue_AS_Value(par1));
[34]533    }
534
535    else if (!par2)
536      PYERROR(PyExc_TypeError, "invalid arguments (second argument missing or the first is of wrong type)", PYNULL)
537
538    else if (PyOrVariable_Check(par1) || PyString_Check(par1) || PyInt_Check(par1)) {
539      // first parameter will denote the variable, the second the value
540      int idx;
541      PVariable var;
542
543      if (PyInt_Check(par1)) {
[224]544        idx = PyInt_AsLong(par1);
[34]545        TMetaDescriptor *desc=example->domain->metas[idx];
546        if (desc)
[224]547          var = desc->variable;
[34]548      }
549
550      else {
551        TMetaDescriptor *desc=example->domain->metas[
[7665]552            PyOrVariable_Check(par1) ? PyOrange_AsVariable(par1)->get_name()
[34]553                                     : string(PyString_AsString(par1))];
554        if (!desc)
555          PYERROR(PyExc_TypeError, "invalid variable", PYNULL);
[224]556        idx = desc->id;
557        var = desc->variable;
[34]558      }
559
[224]560      if (idx>=0)
561        PYERROR(PyExc_TypeError, "invalid meta-id index (negative integer expected)", PYNULL);
562
[34]563      TValue val;
564      if (!convertFromPython(par2, val, var))
565        return PYNULL;
[131]566      example->setMeta(idx, val);
[34]567    }
568
569    else
570      PYERROR(PyExc_TypeError, "invalid arguments", PYNULL)
571
572    RETURN_NONE;
573  PyCATCH
574}
575 
576
[7654]577PyObject *Example_remove_meta(TPyExample *pex, PyObject *index) PYARGS(METH_O, "(id); Removes a meta-value")
[34]578{ PyTRY
579    PVariable var;
580    int idx = getMetaIdFromPy(PyExample_AS_Example(pex), index, var);
581    if (!idx)
582      return PYNULL; 
583
[131]584    PyExample_AS_Example(pex)->removeMeta(idx);
[34]585    RETURN_NONE;
586  PyCATCH
587}
588
589
590
[7654]591PyObject *Example_get_class(TPyExample *pex) PYARGS(METH_NOARGS, "()  -> Value; Returns example's class")
[34]592{ PyTRY
593      const TExample &example = PyExample_AS_ExampleReference(pex);
594      const PVariable &classVar = example.domain->classVar;
595
596      if (!classVar)
597        raiseError("class-less domain");
598
599      return Value_FromVariableValue(classVar, example.getClass());
600  PyCATCH
601}
602
603
[9401]604PyObject *Example_get_classes(TPyExample *pex) PYARGS(METH_NOARGS, "()  -> [Values]; Returns example's class")
605{ PyTRY
606      const TExample &example = PyExample_AS_ExampleReference(pex);
607      PyObject *list=PyList_New(0);
[9410]608      TExample::const_iterator ei=example.values_end;
609      const_PITERATE(TVarList, vi, example.domain->classVars) {
610          PyObject *valo = Value_FromVariableValue(*vi, *ei++);
611          PyList_Append(list, valo);
612          Py_DECREF(valo);
[9401]613      }
614      return list;
615  PyCATCH
616}
617
618
[7654]619PyObject *Example_set_class(TPyExample *pex, PyObject *val) PYARGS(METH_O, "(value); Sets example's class")
[34]620{ PyTRY
621    PExample &example=PyExample_AS_Example(pex);
622    PVariable &classVar = example->domain->classVar;
623
624    if (!classVar)
625      PYERROR(PyExc_SystemError, "classless domain", PYNULL);
626
627    TValue value;
628    if (!convertFromPython(val, value, classVar)) 
629      return PYNULL;
630    example->setClass(value);
631
632    RETURN_NONE;
633  PyCATCH
634}
635
636
[9401]637PyObject *Example_set_classes(TPyExample *pex, PyObject *val) PYARGS(METH_O, "(list-of-Values); Returns example's class")
638{ PyTRY
639      const TExample &example = PyExample_AS_ExampleReference(pex);
640      if (!PyList_Check(val)) {
641          PYERROR(PyExc_TypeError, "list of values expected", PYNULL);
642      }
[9410]643      if (PyList_Size(val) != example.domain->classVars->size()) {
644          PyErr_Format(PyExc_IndexError, "expected %i values, got %i", example.domain->classVars->size(), PyList_Size(val));
[9401]645          return NULL;
646      }
647      TExample::iterator ei=example.values_end;
648      int pos = 0;
[9410]649      const_PITERATE(TVarList, vi, example.domain->classVars) {
[9401]650          if (!convertFromPython(PyList_GET_ITEM(val, pos++), *ei++, *vi))
651              return PYNULL;
652      }
653      RETURN_NONE;
654  PyCATCH
655}
656
657
658
[2501]659PyObject *Example_compatible(TPyExample *pex, PyObject *args) PYARGS(METH_VARARGS, "(example[, ignoreClass]); Returns true if examples are compatible")
[34]660{ PyTRY
[2501]661    PExample example;
662    int ic = 0;
663    if (!PyArg_ParseTuple(args, "O&|i", cc_Example, &example, &ic))
664      PYERROR(PyExc_TypeError, "example and, optionally, a flag for ignoring the class expected", PYNULL)
[113]665
[2501]666    return PyInt_FromLong(PyExample_AS_Example(pex)->compatible(example.getReference(), ic != 0) ? 1 : 0);
[34]667  PyCATCH
668}
669
670
[250]671PyObject *PyExampleIter_New(TPyExample *);
672
673PyObject *Example_iter(TPyExample *pex)
674{ return PyExampleIter_New(pex);
675}
676
677
[34]678int getAttributeIndex(PDomain domain, PyObject *vara)
679{
680    if (PyInt_Check(vara)) {
681      int ind = int(PyInt_AsLong(vara));
[250]682      if (ind >= (int)(domain->variables->size())) {
683        PyErr_Format(PyExc_IndexError, "index %i to large (> %i)", ind, domain->variables->size()-1);
[131]684        return ILLEGAL_INT;
[34]685      }
[250]686
687      // Exception: example[-1] gives class value
688      return ind==-1 ? domain->variables->size()-1 : ind;
[34]689    }
690
691    PVariable var=varFromArg_byDomain(vara, domain);
692    if (!var) 
[131]693      PYERROR(PyExc_TypeError, "invalid arguments or unknown attribute name", ILLEGAL_INT);
[34]694
695    return domain->getVarNum(var);
696}
697
698
699PyObject *Example_getitem(TPyExample *pex, PyObject *vara)
700{ PyTRY
701    PExample example = PyExample_AS_Example(pex);
[131]702
[34]703    int ind = getAttributeIndex(example->domain, vara);
[131]704    if (ind==ILLEGAL_INT)
[34]705      return PYNULL;
706
[4322]707    if ((ind < 0) && !example->hasMeta(ind)) {
708      TMetaDescriptor *metadesc = example->domain->metas[ind];
709      if (metadesc && metadesc->optional)
710        return Value_FromVariableValue(metadesc->variable, metadesc->variable->DK());
711    }
712   
[250]713    /* getVar will return NULL if ind is meta-attribute not registered with the domain.
714       That's OK - we don't need PVariable (Value_FromValue would do exactly the same).
715       operator[] will raise an exception if meta-value is requested and the example
716       doesn't have it. */
717    return Value_FromVariableValue(example->domain->getVar(ind, false), example->operator[](ind));
[34]718  PyCATCH
719}
720
721
[250]722int Example_setitem(TPyExample *pex, PyObject *vara, PyObject *vala)
[34]723{ PyTRY
[113]724    PExample example = PyExample_AS_Example(pex);
[250]725    const int ind = getAttributeIndex(example->domain, vara);
726    if (ind==ILLEGAL_INT)
727      return -1;
[34]728
[250]729    PVariable var = example->domain->getVar(ind, false);
[34]730
731    if (PyOrValue_Check(vala)) {
[250]732      if (PyValue_AS_Variable(vala) && var && (PyValue_AS_Variable(vala)!=var)) {
[34]733          string vals;
734          PyValue_AS_Variable(vala)->val2str(PyValue_AS_Value(vala), vals);
[224]735          if (ind>=0)
736            var->str2val(vals, example->operator[](ind));
737          else {
738            TValue val;
739            var->str2val(vals, val);
740            example->setMeta(ind, val);
741          }
[34]742        }
[224]743      else {
744        if (ind>=0)
745          example->operator[](ind) = PyValue_AS_Value(vala);
[34]746        else
[224]747          example->setMeta(ind, PyValue_AS_Value(vala));
748      }
[34]749    }
750
751    else {
752      TValue value;
753      if (!convertFromPython(vala, value, var)) 
754        return -1;
[224]755      if (ind>=0)
756        example->operator[](ind) = value;
757      else
758        example->setMeta(ind, value);
[34]759    }
760
761    return 0;
762
763  PyCATCH_1
764}
765
766
767
[874]768inline PyObject *toValue(const TValue &val, PVariable var, int natvt, PyObject *forDK, PyObject *forDC, PyObject *forSpecial)
[34]769{ switch (natvt) {
[874]770    case -1:
771      return (val.varType==TValue::INTVAR)
772            ? PyInt_FromLong(long(val.intV))
773            : PyFloat_FromDouble(double(val.floatV));
774
775    case  0:
776      if (val.isSpecial()) {
777        PyObject *res;
778        if (val.isDC())
779          res = forDC;
780        else if (val.isDK())
781          res = forDK;
782        else
783          res = forSpecial;
784        Py_INCREF(res);
785        return res;
786      }   
787      else
788        return convertToPythonNative(val, var);
789
790    default:
791      return Value_FromVariableValue(var, val);
[34]792  }
793}
794
[874]795PyObject *convertToPythonNative(const TExample &example, int natvt, bool tuples, PyObject *forDK, PyObject *forDC, PyObject *forSpecial)
[34]796{
[874]797  if (forDK)
798    Py_INCREF(forDK);
799  else
800    forDK = PyString_FromString("?");
801
802  if (forDC)
803    Py_INCREF(forDC);
804  else
805    forDC = PyString_FromString("~");
806
807  if (forSpecial)
808    Py_INCREF(forSpecial);
809  else
810    forSpecial = PyString_FromString(".");
811
[34]812  PyObject *list=PyList_New(0);
813  TExample::const_iterator ei=example.begin();
[5901]814  const_PITERATE(TVarList, vi, example.domain->attributes) {
815    PyObject *valo = toValue(*(ei++), *vi, natvt, forDK, forDC, forSpecial);
816    PyList_Append(list, valo);
817    Py_DECREF(valo);
818  }
[874]819
820  PyObject *res;
[34]821
[431]822  if (example.domain->classVar) {
[874]823    PyObject *pyclass = toValue(example.getClass(), example.domain->classVar, natvt, forDK, forDC, forSpecial);
[431]824    if (tuples)
[874]825      res = Py_BuildValue("NN", list, pyclass);
[431]826    else {
827      PyList_Append(list, pyclass);
[5901]828      Py_DECREF(pyclass);
[874]829      res = list;
[431]830    }
831  }
832   
[34]833  else {
[431]834    if (tuples)
[874]835      res = Py_BuildValue("NO", list, Py_None);
[431]836    else
[874]837      res = list;
[34]838  }
[874]839
840  Py_DECREF(forDK);
841  Py_DECREF(forDC);
842  Py_DECREF(forSpecial);
843
844  return res;
[34]845}
846
847
[7663]848PyObject *Example_native(TPyExample *pex, PyObject *args, PyObject *keyws) PYARGS(METH_VARARGS | METH_KEYWORDS, "([nativity, tuple=, substitute_DC=, substitute_DK=, substitute_Other=])  -> list; Converts an example to a list")
[34]849{ PyTRY
850    int natvt=1;
851    if (args && !PyArg_ParseTuple(args, "|i", &natvt))
852      PYERROR(PyExc_TypeError, "invalid arguments (no arguments or an integer expected)", PYNULL);
853
[874]854    bool tuples = false;
[890]855    PyObject *pytuples = keyws ? PyDict_GetItemString(keyws, "tuple") : PYNULL;
[874]856    tuples = pytuples && (PyObject_IsTrue(pytuples) != 0);
[34]857
[7663]858    PyObject *forDC = NULL, *forDK = NULL, *forSpecial = NULL;
859    if (keyws) {
860        forDC = PyDict_GetItemString(keyws, "substitute_DC");
861        if (!forDC) {
862            forDC = PyDict_GetItemString(keyws, "substituteDC");
863        }
864        forDC = PyDict_GetItemString(keyws, "substitute_DK");
865        if (!forDC) {
866            forDC = PyDict_GetItemString(keyws, "substituteDK");
867        }
868        forDC = PyDict_GetItemString(keyws, "substitute_other");
869        if (!forDC) {
870            forDC = PyDict_GetItemString(keyws, "substituteOther");
871        }
872    }
[874]873    return convertToPythonNative(PyExample_AS_ExampleReference(pex), natvt, tuples, forDK, forDC, forSpecial);
[34]874  PyCATCH
875}
876
877
[3407]878PyObject *Example_checksum(TPyExample *pex, PyObject *) PYARGS(METH_NOARGS, "() -> crc")
879{ return PyInt_FromLong(PyExample_AS_ExampleReference(pex).sumValues()); }
880
881
[2700]882#include "slist.hpp"
883
884void Example_pack(const TExample &example, TCharBuffer &buf, PyObject *&otherValues)
885{
[9401]886  for(TValue *vali = example.values; vali != example.classes_end; vali++)
[2700]887    Value_pack(*vali, buf, otherValues);
888
889  buf.writeInt(example.meta.size() | (example.name ? 1<<31 : 0));
[4928]890  buf.writeLong(example.id);
[2700]891
892  if (example.name) {
893    if (!otherValues)
894      otherValues = PyList_New(0);
895    PyObject *pyname = PyString_FromString(example.name->c_str());
896    PyList_Append(otherValues, pyname);
897    Py_DECREF(pyname);
898  }
899
900  const_ITERATE(TMetaValues, mi, example.meta) {
901    buf.writeInt((int)(mi->first));
902    buf.writeChar(mi->second.varType);
903    Value_pack(mi->second, buf, otherValues);
904  }
905}
906
907
908void Example_unpack(TExample &example, TCharBuffer &buf, PyObject *&otherValues, int &otherValuesIndex)
909{
[9415]910  TVarList::const_iterator vi;
911  TValue *vali = example.values;
912  for(vi = example.domain->variables->begin(); vali != example.values_end; vali++, vi++) {
913    vali->varType = (*vi)->varType;
914    Value_unpack(*vali, buf, otherValues, otherValuesIndex);
915  }
916  for(vi = example.domain->classVars->begin(); vali != example.classes_end; vali++, vi++) {
[2700]917    vali->varType = (*vi)->varType;
918    Value_unpack(*vali, buf, otherValues, otherValuesIndex);
919  }
920
921  int nMetas = buf.readInt();
[4928]922  example.id = buf.readLong();
[2700]923
924  if (nMetas & (1<<31)) {
925    PyObject *pyname = PyList_GetItem(otherValues, otherValuesIndex++);
926    example.name = new string(PyString_AsString(pyname));
927  }
928
929  for(int i = nMetas & 0x7fffffff; i--; ) {
930    const int id = buf.readInt();
931    TValue val((const unsigned char &)(buf.readChar()));
932    Value_unpack(val, buf, otherValues, otherValuesIndex);
933    example.meta.setValue(id, val);
934  }
935}
936
937
938PyObject *Example__reduce__(TPyExample *pex)
939{
940  PyTRY
941    if (pex->lock)
942      PYERROR(PyExc_TypeError, "examples that reference tables cannot be pickled", PYNULL);
943
944    TExample &example = PyExample_AS_ExampleReference(pex);
945
946    TCharBuffer buf(1024);
947    PyObject *otherValues = NULL;
948    Example_pack(example, buf, otherValues);
949    if (!otherValues) {
950      otherValues = Py_None;
951      Py_INCREF(otherValues);
952    }
953   
954    if (pex->example.counter->orange_dict)
955      return Py_BuildValue("O(Ns#N)O", getExportedFunction("__pickleLoaderExample"),
956                                      WrapOrange(example.domain),
957                                      buf.buf, buf.length(),
958                                      otherValues,
959                                      pex->example.counter->orange_dict);
960    else
961      return Py_BuildValue("O(Ns#N)", getExportedFunction("__pickleLoaderExample"),
962                                      WrapOrange(example.domain),
963                                      buf.buf, buf.length(),
964                                      otherValues);
965  PyCATCH
966}
967
968
969PyObject *__pickleLoaderExample(PyObject *, PyObject *args) PYARGS(METH_VARARGS, "(domain, packed_values, other_values)")
970{
971  PyTRY
972    PDomain domain;
[2736]973    char *pbuf;
[2700]974    int bufSize;
975    PyObject *otherValues;
976
[2736]977    if (!PyArg_ParseTuple(args, "O&s#O:__pickleLoaderExample", cc_Domain, &domain, &pbuf, &bufSize, &otherValues))
[2700]978      return NULL;
979
980    TExample *newEx = new TExample(domain);
981    PExample wex = newEx;
982    int otherValuesIndex = 0;
[2736]983
984    TCharBuffer buf(pbuf);
985    Example_unpack(*newEx, buf, otherValues, otherValuesIndex);
[2700]986    return Example_FromWrappedExample(wex);
987  PyCATCH
988}
[34]989
990inline void addValue(string &res, const TValue &val, PVariable var)
991{ string str;
992  var->val2str(val, str);
993  if (var->varType!=TValue::FLOATVAR) res+="'"+str+"'";
994  else res+=str;
995}
996
997string TPyExample2string(TPyExample *pex)
[113]998{ PExample example = PyExample_AS_Example(pex);
[34]999  string res("[");
1000  TVarList::iterator vi(example->domain->variables->begin());
[9415]1001  TVarList::iterator ve(example->domain->variables->end());
1002  TExample::const_iterator ei = example->values;
1003  for(; vi != ve; vi++, ei++) {
1004    if (ei != example->values)
[34]1005      res+=", ";
[9415]1006    addValue(res, *ei, *vi);
[34]1007  }
1008  res+="]";
1009
[9415]1010  vi = example->domain->classVars->begin();
1011  ve = example->domain->classVars->end();
1012  if (vi != ve) {
1013      res += " (";
1014      for(; vi != ve; vi++, ei++) {
1015          if (ei != example->values_end)
1016              res += ", ";
1017          addValue(res, *ei, *vi);
1018      }
1019      res += ")";
1020  }
1021
[34]1022  int madded=0;
1023  ITERATE(TMetaValues, mi, example->meta) {
1024    res+= (madded++) ? ", " : ", {";
1025   
1026    TMetaDescriptor *desc=example->domain->metas[(*mi).first];
1027    if (desc) {
[7665]1028      res+="\""+desc->variable->get_name()+"\":";
[34]1029      addValue(res, (*mi).second, desc->variable);
1030    }
1031    else
1032      if ((*mi).second.varType==TValue::FLOATVAR) {
1033        char buf[128];
1034        sprintf(buf, "%i:%.2f", int((*mi).first), (*mi).second.floatV);
1035        res += buf;
1036      }
1037      else
1038        res+="???";
1039  }
1040
1041  if (madded) res+="}";
1042
1043  return res;
1044}
1045
1046PyObject *Example_repr(TPyExample *pex)
1047{ PyTRY
1048    return PyString_FromString(TPyExample2string(pex).c_str()); 
1049  PyCATCH
1050}
1051
1052PyObject *Example_str(TPyExample *pex)
1053{ PyTRY
1054    return PyString_FromString(TPyExample2string(pex).c_str()); 
1055  PyCATCH
1056}
1057
1058PyObject *Example_get_domain(TPyExample *self)
1059{ PyTRY
1060    return WrapOrange(PyExample_AS_Example(self)->domain);
1061  PyCATCH
1062}
1063
[4928]1064PyObject *Example_get_id(TPyExample *self)
1065{ PyTRY
1066    return PyInt_FromLong(PyExample_AS_Example(self)->id);
1067  PyCATCH
1068}
1069
1070PyObject *Example_newId(TPyExample *self)
1071{
1072  PyTRY
1073    PyExample_AS_Example(self)->id = getExampleId();
1074    RETURN_NONE;
1075  PyCATCH
1076}
1077
[10589]1078PyObject *richcmp_from_sign(const int &i, const int &op);
1079
1080PyObject *Example_richcmp(TPyExample *one, TPyExample *another, int op)
[34]1081{ PyTRY
[10589]1082    PExample rone = PyExample_AS_Example(one);
1083    TExample &ranother = PyExample_AS_ExampleReference(another);
1084    if (rone->domain != ranother.domain) {
1085        if ((op == Py_EQ) || (op == Py_NE)) {
1086            PyObject *res = op == Py_NE ? Py_True : Py_False;
1087            Py_INCREF(res);
1088            return res;
1089        }
1090        else {
1091            PYERROR(PyExc_ValueError, "examples are from different domains", NULL);
1092        }
1093    }
1094    return richcmp_from_sign(rone->compare(ranother), op);
1095  PyCATCH
[34]1096}
1097
1098
[281]1099int Example_hash(TPyExample *ex)
1100{ PyTRY
1101    return PyExample_AS_Example(ex)->sumValues();
1102  PyCATCH_1
1103}
1104
1105
[34]1106int Example_len(TPyExample *pex)
1107{ PyTRY
1108    return PyExample_AS_Example(pex)->domain->variables->size();
1109  PyCATCH_1
1110}
1111
1112
[7654]1113char *example_underscores[][2] = {
1114    {"getweight", "get_weight"},
1115    {"setweight", "set_weight"},
1116    {"removeweight", "remove_weight"},
1117    {"getmeta", "get_meta"},
1118    {"getmetas", "get_metas"},
1119    {"hasmetas", "has_meta"},
1120    {"setvalue", "set_value"},
1121    {"setmeta", "set_meta"},
1122    {"removemeta", "remove_meta"},
1123    {"getclass", "get_class"},
1124    {"setclass", "set_class"},
1125    {NULL, NULL}
1126};
1127
[823]1128PyObject *Example_getattr(TPyExample *self, PyObject *name)
1129{
[7654]1130  char *orig = PyString_AsString(name);
1131  for(char *(*ei)[2] = example_underscores; **ei; ei++) {
1132      if (!strcmp(orig, **ei)) {
1133          PyObject *trans = PyString_FromString((*ei)[1]);
1134          PyObject *value = PyObject_GenericGetAttr((PyObject *)self, trans);
1135          Py_DECREF(trans);
1136          return value;
1137      }
1138  }
1139
1140  if (!PyString_Check(name) || strcmp(orig, "name"))
[823]1141    return PyObject_GenericGetAttr((PyObject *)self, name);
1142
1143  const string *ename = self->example->name;
1144  return PyString_FromString(ename ? ename->c_str() : "");
1145}
1146
1147
1148int Example_setattr(TPyExample *self, PyObject *name, PyObject *text)
1149{
1150  if (!PyString_Check(name) || strcmp(PyString_AsString(name), "name"))
1151    return PyObject_GenericSetAttr((PyObject *)self, name, text);
1152
1153  string *&ename = self->example->name;
1154
1155  if (text == Py_None) {
1156    if (ename) {
1157      delete ename;
1158      ename = NULL;
1159    }
1160    return 0;
1161  }
1162
1163  if (PyString_Check(text)) {
1164    if (ename)
1165      delete ename;
[906]1166    ename = new string(PyString_AsString(text));
[823]1167    return 0;
1168  }
1169
1170  PYERROR(PyExc_AttributeError, "Example.name must be a string", -1);
1171}
[250]1172
1173
1174extern PyTypeObject PyExampleIter_Type;
1175
1176class TPyExampleIter {
1177public:
1178  PyObject_HEAD
1179
1180  long index;
1181  TPyExample *example; /* Set to NULL when iterator is exhausted */
1182};
1183
1184PyObject *PyExampleIter_New(TPyExample *ex)
1185{
1186  TPyExampleIter *self = PyObject_GC_New(TPyExampleIter, &PyExampleIter_Type);
1187  if (self == NULL)
1188    return NULL;
1189
1190  self->index = 0;
1191
1192  Py_INCREF(ex);
1193    self->example = ex;
1194    PyObject_GC_Track(self);
1195    return (PyObject *)self;
1196}
1197
1198static void PyExampleIter_Dealloc(TPyExampleIter *self)
1199{
1200  PyObject_GC_UnTrack(self);
1201  Py_XDECREF(self->example);
1202  PyObject_GC_Del(self);
1203}
1204
1205static int PyExampleIter_Traverse(TPyExampleIter *self, visitproc visit, void *arg)
1206{
1207    return self->example ? visit((PyObject *)(self->example), arg) : 0;
1208}
1209
1210
1211int PyExampleIter_Clear(TPyExampleIter *self)
1212{ Py_XDECREF((PyObject *)(self->example));
1213  self->example = NULL;
1214  return 0;
1215}
1216
1217
1218static PyObject *PyExampleIter_Iternext(TPyExampleIter *self)
1219{
1220  if (!self->example)
1221    return NULL;
1222
1223  if (self->index >= PyExample_AS_ExampleReference(self->example).domain->variables->size()) {
1224    Py_DECREF(self->example);
1225    self->example = NULL;
1226    PYERROR(PyExc_StopIteration, "", PYNULL);
1227  }
1228
1229  TExample &ex = PyExample_AS_ExampleReference(self->example);
1230  PyObject *result = Value_FromVariableValue(ex.domain->getVar(self->index), ex[self->index]);
1231  self->index++;
1232  return result;
1233}
1234
1235
[265]1236PyObject *PyExampleIter_Iter(PyObject *self)
1237{ Py_INCREF(self);
1238  return self;
1239}
1240
[250]1241
1242PyTypeObject PyExampleIter_Type = {
1243    PyObject_HEAD_INIT(&PyType_Type)
1244    0,
1245    "orange.Example iterator",
1246    sizeof(TPyExampleIter),
1247    0,
1248    (destructor)PyExampleIter_Dealloc,
1249    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1250    PyObject_GenericGetAttr,
1251    0, 0,
1252    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
1253    0,
1254    (traverseproc)PyExampleIter_Traverse,
1255    (inquiry)PyExampleIter_Clear, 0, 0,
[265]1256    PyExampleIter_Iter,
[250]1257    (iternextfunc)PyExampleIter_Iternext,
1258    0, 0, 0, 0, 0, 0, 0,
1259};
1260
1261
[34]1262#include "cls_example.px"
Note: See TracBrowser for help on using the repository browser.