📄 cls_orange.cpp
字号:
/*
This file is part of Orange.
Orange is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
Orange is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Orange; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Authors: Janez Demsar, Blaz Zupan, 1996--2002
Contact: janez.demsar@fri.uni-lj.si
*/
#include <string.h>
#include "stladdon.hpp"
#include "vars.hpp"
#include "domain.hpp"
#include "cls_value.hpp"
#include "cls_example.hpp"
#include "cls_orange.hpp"
#include "externs.px"
BASED_ON(Orange, ROOT)
DATASTRUCTURE(Orange, TPyOrange, orange_dict)
RECOGNIZED_ATTRIBUTES(Orange, "name shortDescription description")
PyObject *PyOrType_GenericAbstract(PyTypeObject *thistype, PyTypeObject *type, PyObject *args, PyObject *kwds)
{ PyTRY
// if the user wants to create an instance of abstract class, we stop him
if ((thistype == type) || !thistype->tp_base || !thistype->tp_base->tp_new) {
PyErr_Format(PyExc_TypeError, "cannot create instances of abstract class '%s'", type->tp_name);
return NULL;
}
// if he derived a new class, we may let him
return thistype->tp_base->tp_new(type, args, kwds);
PyCATCH
}
PyObject *PyOrType_GenericNew(PyTypeObject *type, PyObject *args, PyObject *)
{ PyTRY
PyObject *old = NULL;
if (args && !PyArg_ParseTuple(args, "|O", &old)) {
PyErr_Format(PyExc_TypeError, "%s: invalid arguments: nothing or an existing object expected", type->tp_name);
return NULL;
}
if (old)
if (PyType_IsSubtype(old->ob_type, type)) {
Py_INCREF(old);
return old;
}
else {
PyErr_Format(PyExc_TypeError, "%s: '%s' is not a subtype of '%s'", type->tp_name, old->ob_type->tp_name, type->tp_name);
return NULL;
}
// we assert PyOrange_OrangeBaseClass will succeed and that ot_defaultconstruct is defined.
// the latter is pyxtract responsibility and pyxtract shouldn't be doubted ;)
POrange obj = PyOrange_OrangeBaseClass(type)->ot_defaultconstruct(type);
if (!obj) {
PyErr_Format(PyExc_SystemError, "constructor for '%s' failed", type->tp_name);
return NULL;
}
return WrapOrange(obj);
PyCATCH
}
PyObject *PyOrType_GenericNamedNew(PyTypeObject *type, PyObject *args, PyObject *)
{
PyTRY
PyObject *name=NULL;
if (args && !PyArg_ParseTuple(args, "|O", &name)) {
PyErr_Format(PyExc_TypeError, "%s: invalid arguments: nothing, a name or an existing object expected", type->tp_name);
return NULL;
}
if (name && !PyString_Check(name))
if (PyType_IsSubtype(name->ob_type, type)) {
Py_INCREF(name);
return name;
}
else {
PyErr_Format(PyExc_TypeError, "%s: '%s' is not a subtype of '%s'", type->tp_name, name->ob_type->tp_name, type->tp_name);
return NULL;
}
// we assert PyOrange_OrangeBaseClass will succeed and that ot_defaultconstruct is defined.
// the latter is pyxtract responsibility and pyxtract shouldn't be doubted
POrange obj = PyOrange_OrangeBaseClass(type)->ot_defaultconstruct(type);
if (!obj) {
PyErr_Format(PyExc_SystemError, "constructor for '%s' failed", type->tp_name);
return NULL;
}
PyObject *self=WrapOrange(obj);
if (!name || (PyObject_SetAttrString(self, "name", name)==0))
return self;
else {
Py_DECREF(self);
return PYNULL;
}
PyCATCH
}
int Orange_init(PyObject *self, PyObject *args, PyObject *keywords);
// Rewrapping: this is not a toy - use it cautiously
void rewrap(TPyOrange *&obj, PyTypeObject *type)
{ if (obj && (type!=obj->ob_type)) {
if (obj->ob_refcnt>1) {
#ifdef _MSC_VER
throw exception("cannot rewrap (refcnt>1)");
#else
throw exception();
#endif
}
PyObject_GC_UnTrack((PyObject *)obj);
TPyOrange *newobj = (TPyOrange *)type->tp_alloc(type, 0);
newobj->orange_dict = obj->orange_dict;
newobj->ptr = obj->ptr;
newobj->call_constructed = obj->call_constructed;
newobj->is_reference = obj->is_reference;
obj->orange_dict = NULL;
obj->ptr = NULL;
obj->freeRef();
obj = newobj;
}
}
PyObject *PyOrType_GenericCallableNew(PyTypeObject *type, PyObject *args, PyObject *kwds)
{ PyObject *self1 = NULL,
*self2 = NULL,
*ccReturn = NULL;
PyTRY
// we assert PyOrange_OrangeBaseClass will succeed and that ot_defaultconstruct is defined.
// the latter is pyxtract responsibility and pyxtract shouldn't be doubted
POrange obj=PyOrange_OrangeBaseClass(type)->ot_defaultconstruct(PyTuple_Size(args) ? (PyTypeObject *)&PyOrOrange_Type : type);
if (!obj) {
PyErr_Format(PyExc_SystemError, "constructor for '%s' failed", type->tp_name);
goto err;
}
PyObject *self1 = WrapOrange(obj);
if (!PyTuple_Size(args))
return self1;
else {
/* if (self1->ob_type != type) {
PyErr_Format(PyExc_SystemError, "Subclassed orange classes are not call-constructable", type->tp_name);
Py_DECREF(self1);
return NULL;
}
*/
if (!self1->ob_type->tp_call) {
PyErr_Format(PyExc_SystemError, "error in orange class structure ('%s' not callable)", type->tp_name);
goto err;
}
/* We should manually call init - Python will call init on self2, and it won't do anything.
It's important to call it prior to setting call_constructed (below) */
if (Orange_init(self1, args, kwds) < 0)
goto err;
/* this is to tell tp_call(self1) not to complain about keyword arguments;
self1 is disposed later in this function, so this should cause no problems */
((TPyOrange *)self1)->call_constructed = true;
PyObject *self2=self1->ob_type->tp_call(self1, args, kwds);
if (self2) {
if (type!=self1->ob_type) {
char *oname = new char[30 + strlen(type->tp_name)];
sprintf(oname, "_%s__call_construction_type", type->tp_name);
PyObject *ccReturn = PyObject_GetAttrString((PyObject *)type, oname);
delete oname;
if (!ccReturn) {
PyErr_Format(PyExc_SystemError, "no return type specified for call-construction of '%s'", type->tp_name);
goto err;
}
if (!PyType_Check(ccReturn)) {
PyErr_Format(PyExc_SystemError, "no return type specified for call-construction of '%s'", type->tp_name);
goto err;
}
if (self2->ob_refcnt>1) { // Object might have a reference to itself...
PyErr_Format(PyExc_SystemError, "cannot rewrap the class '%s' - too many references", self2->ob_type->tp_name);
goto err;
}
rewrap((TPyOrange *&)self2, (PyTypeObject *)ccReturn);
}
Py_DECREF(self1);
if (PyOrOrange_Check(self2))
((TPyOrange *)self2)->call_constructed = true;
return self2;
}
}
PyCATCH
err:
Py_XDECREF(self1);
Py_XDECREF(self2);
Py_XDECREF(ccReturn);
return NULL;
}
int Orange_traverse(TPyOrange *self, visitproc visit, void *arg)
{
if (self->orange_dict) {
int err = visit(self->orange_dict, arg);
if (err)
return err;
}
return ((TOrange *)self->ptr)->traverse(visit, arg);
}
int Orange_clear(TPyOrange *self)
{
return ((TOrange *)self->ptr)->dropReferences();
}
PyObject *PyOrange__dict__(TPyOrange *self)
{
if (!self->orange_dict)
self->orange_dict = PyOrange_DictProxy_New(self);
Py_INCREF(self->orange_dict);
return (PyObject *)(self->orange_dict);
}
PyObject *PyOrange__members__(TPyOrange *self)
{
const TPropertyDescription *ppd = PyOrange_AS_Orange(self)->classDescription()->properties;
const TPropertyDescription *pd;
for(pd = ppd; pd->name; pd++);
PyObject *res = PyList_New(pd-ppd);
for(pd = ppd; pd->name; pd++)
PyList_SetItem(res, pd-ppd, PyString_FromString(pd->name));
return res;
}
PyObject *PyOrange_translateObsolete(PyObject *self, PyObject *pyname)
{
char *name=PyString_AsString(pyname);
for(TOrangeType *selftype = PyOrange_OrangeBaseClass(self->ob_type); PyOrange_CheckType((PyTypeObject *)selftype); selftype=(TOrangeType *)(selftype->ot_inherited.tp_base))
if (selftype->ot_aliases)
for(TAttributeAlias *aliases=selftype->ot_aliases; aliases->alias; aliases++)
if (!strcmp(name, aliases->alias))
return PyString_FromString(aliases->realName);
return NULL;
}
PyObject *Orange_getattr1(TPyOrange *self, const char *name)
// This is a getattr, without translation of obsolete names and without looking into the associated dictionary
{ PyTRY
if (!self)
PYERROR(PyExc_SystemError, "NULL Orange object", PYNULL);
TOrange *me = (TOrange *)self->ptr;
if (me->hasProperty(name)) {
try {
const type_info &propertyType = me->propertyType(name);
if (propertyType==typeid(bool)) {
bool value;
me->getProperty(name, value);
return Py_BuildValue("i", value ? 1 : 0);
}
if (propertyType==typeid(int)) {
int value;
me->getProperty(name, value);
return Py_BuildValue("i", value);
}
if (propertyType==typeid(float)) {
float value;
me->getProperty(name, value);
return Py_BuildValue("f", value);
}
if (propertyType==typeid(string)) {
string value;
me->getProperty(name, value);
return Py_BuildValue("s", value.c_str());
}
if (propertyType==typeid(TValue)) {
TValue value;
me->getProperty(name, value);
return Value_FromValue(value);
}
if (propertyType==typeid(TExample)) {
POrange mlobj;
me->wr_getProperty(name, mlobj);
if (mlobj)
return Example_FromWrappedExample(PExample(mlobj));
else
RETURN_NONE;
}
POrange mlobj;
me->wr_getProperty(name, mlobj);
return (PyObject *)WrapOrange(mlobj);
} catch (exception err)
{}
}
if (!strcmp(name, "name") || !strcmp(name, "shortDescription") || !strcmp(name, "description"))
return PyString_FromString("");
PyErr_Format(PyExc_AttributeError, "'%s' has no attribute '%s'", self->ob_type->tp_name, name);
return PYNULL;
PyCATCH;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -