mirror of
https://github.com/worldforge/cyphesis
synced 2026-08-13 12:26:04 -04:00
896 lines
29 KiB
C++
896 lines
29 KiB
C++
// Cyphesis Online RPG Server and AI Engine
|
|
// Copyright (C) 2000 Alistair Riddoch
|
|
//
|
|
// This program 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.
|
|
//
|
|
// This program 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 this program; if not, write to the Free Software Foundation,
|
|
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
|
|
|
|
#include "Py_Operation.h"
|
|
#include "Py_RootEntity.h"
|
|
#include "Py_Oplist.h"
|
|
#include "Py_Message.h"
|
|
#include "Py_Thing.h"
|
|
|
|
#include "common/log.h"
|
|
|
|
#include <Atlas/Objects/Generic.h>
|
|
|
|
#include <iostream>
|
|
|
|
using Atlas::Message::Element;
|
|
using Atlas::Message::ListType;
|
|
using Atlas::Objects::Root;
|
|
using Atlas::Objects::Factories;
|
|
using Atlas::Objects::Operation::RootOperation;
|
|
using Atlas::Objects::Operation::Generic;
|
|
using Atlas::Objects::Entity::RootEntity;
|
|
|
|
/*
|
|
* Beginning of Operation section.
|
|
*
|
|
* This is a python type that wraps up operation objects from
|
|
* Atlas::Objects::Operation namespace.
|
|
*
|
|
*/
|
|
|
|
/*
|
|
* Beginning of Operation methods section.
|
|
*/
|
|
|
|
static PyObject * Operation_setSerialno(PyOperation * self, PyObject * py_sno)
|
|
{
|
|
#ifndef NDEBUG
|
|
if (!self->operation.isValid()) {
|
|
PyErr_SetString(PyExc_AssertionError,"NULL Operation in Operation.setSerialno");
|
|
return NULL;
|
|
}
|
|
#endif // NDEBUG
|
|
// Takes integer, returns none
|
|
if (!PyInt_CheckExact(py_sno)) {
|
|
PyErr_SetString(PyExc_TypeError, "serialno not an integer");
|
|
return NULL;
|
|
}
|
|
int serialno = PyInt_AsLong(py_sno);
|
|
self->operation->setSerialno(serialno);
|
|
|
|
Py_INCREF(Py_None);
|
|
return Py_None;
|
|
}
|
|
|
|
static PyObject * Operation_setRefno(PyOperation * self, PyObject * py_rno)
|
|
{
|
|
// Takes integer, returns none
|
|
#ifndef NDEBUG
|
|
if (!self->operation.isValid()) {
|
|
PyErr_SetString(PyExc_AssertionError,"NULL Operation in Operation.setRefno");
|
|
return NULL;
|
|
}
|
|
#endif // NDEBUG
|
|
if (!PyInt_CheckExact(py_rno)) {
|
|
PyErr_SetString(PyExc_TypeError, "refno not an integer");
|
|
return NULL;
|
|
}
|
|
int refno = PyInt_AsLong(py_rno);
|
|
self->operation->setRefno(refno);
|
|
|
|
Py_INCREF(Py_None);
|
|
return Py_None;
|
|
}
|
|
|
|
static PyObject * Operation_setFrom(PyOperation * self, PyObject * py_from)
|
|
{
|
|
// Takes string, returns none
|
|
#ifndef NDEBUG
|
|
if (!self->operation.isValid()) {
|
|
PyErr_SetString(PyExc_AssertionError,"NULL Operation in Operation.setFrom");
|
|
return NULL;
|
|
}
|
|
#endif // NDEBUG
|
|
if (!PyString_CheckExact(py_from)) {
|
|
PyErr_SetString(PyExc_TypeError, "from not a string");
|
|
return NULL;
|
|
}
|
|
char * from = PyString_AsString(py_from);
|
|
self->operation->setFrom(from);
|
|
|
|
Py_INCREF(Py_None);
|
|
return Py_None;
|
|
}
|
|
|
|
static PyObject * Operation_setTo(PyOperation * self, PyObject * py_to)
|
|
{
|
|
// Takes string, returns none
|
|
#ifndef NDEBUG
|
|
if (!self->operation.isValid()) {
|
|
PyErr_SetString(PyExc_AssertionError,"NULL Operation in Operation.setTo");
|
|
return NULL;
|
|
}
|
|
#endif // NDEBUG
|
|
if (!PyString_CheckExact(py_to)) {
|
|
PyErr_SetString(PyExc_TypeError, "to not a string");
|
|
return NULL;
|
|
}
|
|
char * to = PyString_AsString(py_to);
|
|
self->operation->setTo(to);
|
|
|
|
Py_INCREF(Py_None);
|
|
return Py_None;
|
|
}
|
|
|
|
static PyObject * Operation_setSeconds(PyOperation * self, PyObject * py_secs)
|
|
{
|
|
// Takes float, returns none
|
|
#ifndef NDEBUG
|
|
if (!self->operation.isValid()) {
|
|
PyErr_SetString(PyExc_AssertionError,"NULL Operation in Operation.setSeconds");
|
|
return NULL;
|
|
}
|
|
#endif // NDEBUG
|
|
double seconds;
|
|
if (PyFloat_CheckExact(py_secs)) {
|
|
seconds = PyFloat_AsDouble(py_secs);
|
|
} else if (PyInt_CheckExact(py_secs)) {
|
|
seconds = PyInt_AsLong(py_secs);
|
|
} else {
|
|
PyErr_SetString(PyExc_TypeError, "seconds not a number");
|
|
return NULL;
|
|
}
|
|
self->operation->setSeconds(seconds);
|
|
|
|
Py_INCREF(Py_None);
|
|
return Py_None;
|
|
}
|
|
|
|
static PyObject * Operation_setFutureSeconds(PyOperation * self,
|
|
PyObject * py_fsecs)
|
|
{
|
|
// Takes float, returns none
|
|
#ifndef NDEBUG
|
|
if (!self->operation.isValid()) {
|
|
PyErr_SetString(PyExc_AssertionError,"NULL Operation in Operation.setFutureSeconds");
|
|
return NULL;
|
|
}
|
|
#endif // NDEBUG
|
|
double futureseconds;
|
|
if (PyFloat_CheckExact(py_fsecs)) {
|
|
futureseconds = PyFloat_AsDouble(py_fsecs);
|
|
} else if (PyInt_CheckExact(py_fsecs)) {
|
|
futureseconds = PyInt_AsLong(py_fsecs);
|
|
} else {
|
|
PyErr_SetString(PyExc_TypeError, "future_seconds not a number");
|
|
return NULL;
|
|
}
|
|
self->operation->setFutureSeconds(futureseconds);
|
|
|
|
Py_INCREF(Py_None);
|
|
return Py_None;
|
|
}
|
|
|
|
static PyObject * Operation_setName(PyOperation * self, PyObject * py_name)
|
|
{
|
|
// Takes string, returns none
|
|
#ifndef NDEBUG
|
|
if (!self->operation.isValid()) {
|
|
PyErr_SetString(PyExc_AssertionError,"NULL Operation in Operation.setName");
|
|
return NULL;
|
|
}
|
|
#endif // NDEBUG
|
|
if (!PyString_CheckExact(py_name)) {
|
|
PyErr_SetString(PyExc_TypeError, "name not a string");
|
|
return NULL;
|
|
}
|
|
char * name = PyString_AsString(py_name);
|
|
self->operation->setName(name);
|
|
|
|
Py_INCREF(Py_None);
|
|
return Py_None;
|
|
}
|
|
|
|
static PyObject * Operation_setArgs(PyOperation * self, PyObject * args)
|
|
{
|
|
// Takes List, returns none
|
|
#ifndef NDEBUG
|
|
if (!self->operation.isValid()) {
|
|
PyErr_SetString(PyExc_AssertionError,"NULL Operation in Operation.setArgs");
|
|
return NULL;
|
|
}
|
|
#endif // NDEBUG
|
|
// FIXME This is a big mess - either get rid of it in entirity, or
|
|
// make something better.
|
|
|
|
if (!PyList_Check(args)) {
|
|
PyErr_SetString(PyExc_TypeError, "args not a list");
|
|
return NULL;
|
|
}
|
|
std::vector<Root> argslist;
|
|
for(int i = 0; i < PyList_Size(args); i++) {
|
|
PyObject * item = PyList_GetItem(args, i);
|
|
if (PyMessage_Check(item)) {
|
|
Element & e = *((PyMessage*)item)->m_obj;
|
|
if (!e.isMap()) {
|
|
PyErr_SetString(PyExc_TypeError,"args contains non map");
|
|
return NULL;
|
|
}
|
|
argslist.push_back(Factories::instance()->createObject(e.Map()));
|
|
} else if (PyOperation_Check(item)) {
|
|
argslist.push_back(((PyOperation*)item)->operation);
|
|
} else if (PyRootEntity_Check(item)) {
|
|
argslist.push_back(((PyRootEntity*)item)->entity);
|
|
} else {
|
|
std::cout << "o: " << i << item->ob_type->tp_name << std::endl << std::flush;
|
|
PyErr_SetString(PyExc_TypeError,"args contains non Atlas Object");
|
|
return NULL;
|
|
}
|
|
}
|
|
self->operation->setArgs(argslist);
|
|
|
|
Py_INCREF(Py_None);
|
|
return Py_None;
|
|
}
|
|
|
|
static PyObject * Operation_getSerialno(PyOperation * self)
|
|
{
|
|
// Returns int
|
|
#ifndef NDEBUG
|
|
if (!self->operation.isValid()) {
|
|
PyErr_SetString(PyExc_AssertionError,"NULL Operation in Operation.getSerialno");
|
|
return NULL;
|
|
}
|
|
#endif // NDEBUG
|
|
return PyInt_FromLong(self->operation->getSerialno());
|
|
}
|
|
|
|
static PyObject * Operation_isDefaultSerialno(PyOperation * self)
|
|
{
|
|
// Returns int
|
|
#ifndef NDEBUG
|
|
if (!self->operation.isValid()) {
|
|
PyErr_SetString(PyExc_AssertionError,"NULL Operation in Operation.isDefaultSerialno");
|
|
return NULL;
|
|
}
|
|
#endif // NDEBUG
|
|
if (self->operation->isDefaultSerialno()) {
|
|
Py_INCREF(Py_True);
|
|
return Py_True;
|
|
} else {
|
|
Py_INCREF(Py_False);
|
|
return Py_False;
|
|
}
|
|
}
|
|
|
|
static PyObject * Operation_getRefno(PyOperation * self)
|
|
{
|
|
// Returns int
|
|
#ifndef NDEBUG
|
|
if (!self->operation.isValid()) {
|
|
PyErr_SetString(PyExc_AssertionError,"NULL Operation in Operation.getRefno");
|
|
return NULL;
|
|
}
|
|
#endif // NDEBUG
|
|
return PyInt_FromLong(self->operation->getRefno());
|
|
}
|
|
|
|
static PyObject * Operation_getFrom(PyOperation * self)
|
|
{
|
|
// Returns string
|
|
#ifndef NDEBUG
|
|
if (!self->operation.isValid()) {
|
|
PyErr_SetString(PyExc_AssertionError,"NULL Operation in Operation.getFrom");
|
|
return NULL;
|
|
}
|
|
#endif // NDEBUG
|
|
return PyString_FromString(self->operation->getFrom().c_str());
|
|
}
|
|
|
|
static PyObject * Operation_getTo(PyOperation * self)
|
|
{
|
|
// Returns string
|
|
#ifndef NDEBUG
|
|
if (!self->operation.isValid()) {
|
|
PyErr_SetString(PyExc_AssertionError,"NULL Operation in Operation.getTo");
|
|
return NULL;
|
|
}
|
|
#endif // NDEBUG
|
|
return PyString_FromString(self->operation->getTo().c_str());
|
|
}
|
|
|
|
static PyObject * Operation_getSeconds(PyOperation * self)
|
|
{
|
|
// Returns float
|
|
#ifndef NDEBUG
|
|
if (!self->operation.isValid()) {
|
|
PyErr_SetString(PyExc_AssertionError,"NULL Operation in Operation.getSeconds");
|
|
return NULL;
|
|
}
|
|
#endif // NDEBUG
|
|
return PyFloat_FromDouble(self->operation->getSeconds());
|
|
}
|
|
|
|
static PyObject * Operation_getFutureSeconds(PyOperation * self)
|
|
{
|
|
// Returns float
|
|
#ifndef NDEBUG
|
|
if (!self->operation.isValid()) {
|
|
PyErr_SetString(PyExc_AssertionError,"NULL Operation in Operation.getFutureSeconds");
|
|
return NULL;
|
|
}
|
|
#endif // NDEBUG
|
|
return PyFloat_FromDouble(self->operation->getFutureSeconds());
|
|
}
|
|
|
|
static PyObject * Operation_getName(PyOperation * self)
|
|
{
|
|
// Returns float
|
|
#ifndef NDEBUG
|
|
if (!self->operation.isValid()) {
|
|
PyErr_SetString(PyExc_AssertionError,"NULL Operation in Operation.getName");
|
|
return NULL;
|
|
}
|
|
#endif // NDEBUG
|
|
return PyString_FromString(self->operation->getName().c_str());
|
|
}
|
|
|
|
static PyObject * Operation_getArgs(PyOperation * self)
|
|
{
|
|
// Returns list
|
|
#ifndef NDEBUG
|
|
if (!self->operation.isValid()) {
|
|
PyErr_SetString(PyExc_AssertionError,"NULL Operation in Operation.getArgs");
|
|
return NULL;
|
|
}
|
|
#endif // NDEBUG
|
|
// Here we go:-
|
|
|
|
// FIXME
|
|
// Here we need a generic way to make a Root object into a python object,
|
|
// either by wrapping as a Operation, or as an Entity. New Entity binding
|
|
// thus required. Once written this code should also be used in
|
|
// Operation_seq_item(), and the code there is a better starting point.
|
|
|
|
const std::vector<Root> & args_list = self->operation->getArgs();
|
|
PyObject * args_pylist = PyList_New(args_list.size());
|
|
if (args_pylist == NULL) {
|
|
return NULL;
|
|
}
|
|
int j = 0;
|
|
PyMessage * item;
|
|
std::vector<Root>::const_iterator Iend = args_list.end();
|
|
std::vector<Root>::const_iterator I = args_list.begin();
|
|
for (; I != Iend; ++I, ++j) {
|
|
item = newPyMessage();
|
|
if (item == NULL) {
|
|
Py_DECREF(args_pylist);
|
|
return NULL;
|
|
}
|
|
item->m_obj = new Element((*I)->asMessage());
|
|
PyList_SetItem(args_pylist, j, (PyObject *)item);
|
|
}
|
|
return args_pylist;
|
|
}
|
|
|
|
static PyObject* Operation_get_name(PyOperation * self)
|
|
{
|
|
#ifndef NDEBUG
|
|
if (!self->operation.isValid()) {
|
|
PyErr_SetString(PyExc_AssertionError,"NULL Operation in Operation.get_name");
|
|
return NULL;
|
|
}
|
|
#endif // NDEBUG
|
|
return PyString_FromString("op");
|
|
}
|
|
|
|
/*
|
|
* Operation sequence methods.
|
|
*/
|
|
|
|
#if PY_VERSION_HEX < 0x02050000
|
|
typedef int Py_ssize_t;
|
|
#endif
|
|
|
|
static Py_ssize_t Operation_seq_length(PyOperation * self)
|
|
{
|
|
#ifndef NDEBUG
|
|
if (!self->operation.isValid()) {
|
|
PyErr_SetString(PyExc_AssertionError,"NULL Operation in Operation.seq_length");
|
|
return -1;
|
|
}
|
|
#endif // NDEBUG
|
|
return self->operation->getArgs().size();
|
|
}
|
|
|
|
static PyObject * Operation_seq_item(PyOperation * self, Py_ssize_t item)
|
|
{
|
|
#ifndef NDEBUG
|
|
if (!self->operation.isValid()) {
|
|
PyErr_SetString(PyExc_AssertionError,"NULL Operation in Operation.seq_item");
|
|
return 0;
|
|
}
|
|
#endif // NDEBUG
|
|
const std::vector<Root> & args= self->operation->getArgs();
|
|
if (item < 0 || item >= (Py_ssize_t)args.size()) {
|
|
PyErr_SetString(PyExc_IndexError,"Operation.[]: Not enough op arguments");
|
|
return 0;
|
|
}
|
|
const Root & arg = args[item];
|
|
RootOperation op = Atlas::Objects::smart_dynamic_cast<RootOperation>(arg);
|
|
if (op.isValid()) {
|
|
PyOperation * ret_op = newPyOperation();
|
|
if (ret_op != NULL) {
|
|
ret_op->operation = op;
|
|
}
|
|
return (PyObject *)ret_op;
|
|
}
|
|
RootEntity ent = Atlas::Objects::smart_dynamic_cast<RootEntity>(arg);
|
|
if (ent.isValid()) {
|
|
PyRootEntity * ret_ent = newPyRootEntity();
|
|
if (ret_ent != NULL) {
|
|
ret_ent->entity = ent;
|
|
}
|
|
return (PyObject *)ret_ent;
|
|
}
|
|
log(WARNING, "Non operation or entity being returned as arg of operation");
|
|
PyMessage * ret = newPyMessage();
|
|
if (ret != NULL) {
|
|
ret->m_obj = new Element(arg->asMessage());
|
|
}
|
|
return (PyObject *)ret;
|
|
}
|
|
|
|
static PyObject * Operation_num_add(PyOperation *self, PyObject *other)
|
|
{
|
|
#ifndef NDEBUG
|
|
if (!self->operation.isValid()) {
|
|
PyErr_SetString(PyExc_AssertionError, "NULL Operation in Operation.num_add");
|
|
return NULL;
|
|
}
|
|
#endif // NDEBUG
|
|
if (other == Py_None) {
|
|
#if 0
|
|
PyOplist * res = newPyOplist();
|
|
res->ops = new OpVector();
|
|
res->ops->push_back(self->operation);
|
|
return (PyObject*)res;
|
|
#else
|
|
Py_INCREF(self);
|
|
return (PyObject*)self;
|
|
#endif
|
|
}
|
|
if (PyOplist_Check(other)) {
|
|
PyOplist * opl = (PyOplist*)other;
|
|
#ifndef NDEBUG
|
|
if (opl->ops == NULL) {
|
|
PyErr_SetString(PyExc_AssertionError, "invalid OpVector");
|
|
return NULL;
|
|
}
|
|
#endif // NDEBUG
|
|
PyOplist * res = newPyOplist();
|
|
if (res != NULL) {
|
|
res->ops = new OpVector(*opl->ops);
|
|
res->ops->push_back(self->operation);
|
|
}
|
|
return (PyObject*)res;
|
|
}
|
|
if (PyOperation_Check(other)) {
|
|
PyOperation * op = (PyOperation*)other;
|
|
#ifndef NDEBUG
|
|
if (!op->operation.isValid()) {
|
|
PyErr_SetString(PyExc_AssertionError, "NULL Operation in other of Operation.num_add");
|
|
return NULL;
|
|
}
|
|
#endif // NDEBUG
|
|
PyOplist * res = newPyOplist();
|
|
if (res != NULL) {
|
|
res->ops = new OpVector();
|
|
res->ops->push_back(op->operation);
|
|
res->ops->push_back(self->operation);
|
|
}
|
|
return (PyObject*)res;
|
|
}
|
|
PyErr_SetString(PyExc_TypeError, "Unknown other in Operation.num_add");
|
|
return NULL;
|
|
}
|
|
|
|
/*
|
|
* Operation numerical methods.
|
|
*/
|
|
|
|
static int Operation_num_coerce(PyObject ** self, PyObject ** other)
|
|
{
|
|
//if (*other == Py_None) {
|
|
Py_INCREF(*self);
|
|
Py_INCREF(*other);
|
|
return 0;
|
|
//}
|
|
//return -1;
|
|
}
|
|
|
|
|
|
/*
|
|
* Operation numerical methods structure.
|
|
*/
|
|
|
|
static PyNumberMethods Operation_num = {
|
|
(binaryfunc)Operation_num_add,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
Operation_num_coerce,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0
|
|
};
|
|
|
|
#if PY_MINOR_VERSION < 5
|
|
#define lenfunc inquiry
|
|
#define ssizeargfunc intargfunc
|
|
#endif
|
|
|
|
/*
|
|
* Operation sequence methods structure.
|
|
*/
|
|
|
|
static PySequenceMethods Operation_seq = {
|
|
(lenfunc)Operation_seq_length, /* sq_length */
|
|
NULL, /* sq_concat */
|
|
NULL, /* sq_repeat */
|
|
(ssizeargfunc)Operation_seq_item, /* sq_item */
|
|
NULL, /* sq_slice */
|
|
NULL, /* sq_ass_item */
|
|
NULL /* sq_ass_slice */
|
|
};
|
|
|
|
/*
|
|
* Operation methods structure.
|
|
*
|
|
* Generated from a macro in case we need one for each type of operation.
|
|
*
|
|
*/
|
|
|
|
PyMethodDef Operation_methods[] = {
|
|
{"setSerialno", (PyCFunction)Operation_setSerialno, METH_O},
|
|
{"setRefno", (PyCFunction)Operation_setRefno, METH_O},
|
|
{"setFrom", (PyCFunction)Operation_setFrom, METH_O},
|
|
{"setTo", (PyCFunction)Operation_setTo, METH_O},
|
|
{"setSeconds", (PyCFunction)Operation_setSeconds, METH_O},
|
|
{"setFutureSeconds",(PyCFunction)Operation_setFutureSeconds,METH_O},
|
|
{"setArgs", (PyCFunction)Operation_setArgs, METH_O},
|
|
{"setName", (PyCFunction)Operation_setName, METH_O},
|
|
{NULL, NULL}
|
|
};
|
|
|
|
PyMethodDef ConstOperation_methods[] = {
|
|
{"getSerialno", (PyCFunction)Operation_getSerialno, METH_NOARGS},
|
|
{"isDefaultSerialno",(PyCFunction)Operation_isDefaultSerialno, METH_NOARGS},
|
|
{"getRefno", (PyCFunction)Operation_getRefno, METH_NOARGS},
|
|
{"getFrom", (PyCFunction)Operation_getFrom, METH_NOARGS},
|
|
{"getTo", (PyCFunction)Operation_getTo, METH_NOARGS},
|
|
{"getSeconds", (PyCFunction)Operation_getSeconds, METH_NOARGS},
|
|
{"getFutureSeconds",(PyCFunction)Operation_getFutureSeconds,METH_NOARGS},
|
|
{"getArgs", (PyCFunction)Operation_getArgs, METH_NOARGS},
|
|
{"get_name", (PyCFunction)Operation_get_name, METH_NOARGS},
|
|
{"getName", (PyCFunction)Operation_getName, METH_NOARGS},
|
|
{NULL, NULL}
|
|
};
|
|
|
|
|
|
/*
|
|
* Beginning of Operation standard methods section.
|
|
*/
|
|
|
|
static void Operation_dealloc(PyOperation *self)
|
|
{
|
|
self->operation.~RootOperation();
|
|
self->ob_type->tp_free((PyObject*)self);
|
|
}
|
|
|
|
static PyObject * Operation_getattro(PyOperation * self, PyObject * oname)
|
|
{
|
|
#ifndef NDEBUG
|
|
if (!self->operation.isValid()) {
|
|
PyErr_SetString(PyExc_AssertionError, "NULL Operation in Operation.getattr");
|
|
return NULL;
|
|
}
|
|
#endif // NDEBUG
|
|
char * name = PyString_AsString(oname);
|
|
if (strcmp(name, "from_") == 0) {
|
|
return PyString_FromString(self->operation->getFrom().c_str());
|
|
} else if (strcmp(name, "to") == 0) {
|
|
return PyString_FromString(self->operation->getTo().c_str());
|
|
} else if (strcmp(name, "id") == 0) {
|
|
const std::list<std::string> & parents = self->operation->getParents();
|
|
if (parents.empty()) {
|
|
PyErr_SetString(PyExc_AttributeError, "Operation has no parents");
|
|
return NULL;
|
|
}
|
|
return PyString_FromString(parents.front().c_str());
|
|
}
|
|
return PyObject_GenericGetAttr((PyObject *)self, oname);
|
|
}
|
|
|
|
static int Operation_setattro(PyOperation *self, PyObject * oname, PyObject *v)
|
|
{
|
|
#ifndef NDEBUG
|
|
if (!self->operation.isValid()) {
|
|
PyErr_SetString(PyExc_AssertionError, "NULL Operation in Operation.setattr");
|
|
return -1;
|
|
}
|
|
#endif // NDEBUG
|
|
char * name = PyString_AsString(oname);
|
|
if (strcmp(name, "from_") == 0) {
|
|
PyObject * thing_id = PyObject_GetAttrString(v, "id");
|
|
if (thing_id == NULL || !PyString_Check(thing_id)) {
|
|
PyErr_SetString(PyExc_TypeError, "invalid from");
|
|
if (thing_id != NULL) {
|
|
Py_DECREF(thing_id);
|
|
}
|
|
return -1;
|
|
}
|
|
self->operation->setFrom(PyString_AsString(thing_id));
|
|
Py_DECREF(thing_id);
|
|
return 0;
|
|
}
|
|
if (strcmp(name, "to") == 0) {
|
|
PyObject * thing_id = PyObject_GetAttrString(v, "id");
|
|
if (thing_id == NULL || !PyString_Check(thing_id)) {
|
|
PyErr_SetString(PyExc_TypeError, "invalid to");
|
|
if (thing_id != NULL) {
|
|
Py_DECREF(thing_id);
|
|
}
|
|
return -1;
|
|
}
|
|
self->operation->setTo(PyString_AsString(thing_id));
|
|
Py_DECREF(thing_id);
|
|
return 0;
|
|
}
|
|
PyErr_SetString(PyExc_AttributeError, "unknown attribute");
|
|
return -1;
|
|
}
|
|
|
|
static int addToArgs(std::vector<Root> & args, PyObject * arg)
|
|
{
|
|
if (PyMessage_Check(arg)) {
|
|
PyMessage * obj = (PyMessage*)arg;
|
|
#ifndef NDEBUG
|
|
if (obj->m_obj == NULL) {
|
|
PyErr_SetString(PyExc_AssertionError,"NULL MessageElement in Operation constructor argument");
|
|
return -1;
|
|
}
|
|
#endif // NDEBUG
|
|
const Element & o = *obj->m_obj;
|
|
if (o.isMap()) {
|
|
args.push_back(Atlas::Objects::Factories::instance()->createObject(o.asMap()));
|
|
} else {
|
|
PyErr_SetString(PyExc_TypeError, "Operation arg is not a map");
|
|
return -1;
|
|
}
|
|
} else if (PyOperation_Check(arg)) {
|
|
PyOperation * op = (PyOperation*)arg;
|
|
#ifndef NDEBUG
|
|
if (!op->operation.isValid()) {
|
|
PyErr_SetString(PyExc_AssertionError,"Invalid operation in Operation constructor argument");
|
|
return -1;
|
|
}
|
|
#endif // NDEBUG
|
|
args.push_back(op->operation);
|
|
} else if (PyRootEntity_Check(arg)) {
|
|
PyRootEntity * ent = (PyRootEntity*)arg;
|
|
#ifndef NDEBUG
|
|
if (!ent->entity.isValid()) {
|
|
PyErr_SetString(PyExc_AssertionError,"Invalid rootentity in Operation constructor argument");
|
|
return -1;
|
|
}
|
|
#endif // NDEBUG
|
|
args.push_back(ent->entity);
|
|
} else {
|
|
PyErr_SetString(PyExc_TypeError, "Operation arg is of unknown type");
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int Operation_init(PyOperation * self, PyObject * args, PyObject * kwds)
|
|
{
|
|
char * type;
|
|
PyObject * arg1 = NULL;
|
|
PyObject * arg2 = NULL;
|
|
PyObject * arg3 = NULL;
|
|
|
|
if (!PyArg_ParseTuple(args, "s|OOO", &type, &arg1, &arg2, &arg3)) {
|
|
return -1;
|
|
}
|
|
Root r = Atlas::Objects::Factories::instance()->createObject(type);
|
|
self->operation = Atlas::Objects::smart_dynamic_cast<RootOperation>(r);
|
|
if (!self->operation.isValid()) {
|
|
// PyErr_SetString(PyExc_TypeError, "Operation() unknown operation type requested");
|
|
// return -1;
|
|
self->operation = Generic();
|
|
self->operation->setParents(std::list<std::string>(1, type));
|
|
}
|
|
if (kwds != NULL) {
|
|
PyObject * from = PyDict_GetItemString(kwds, "from_");
|
|
if (from != NULL) {
|
|
PyObject * from_id = 0;
|
|
if (PyString_Check(from)) {
|
|
from_id = from;
|
|
Py_INCREF(from_id);
|
|
} else if ((from_id = PyObject_GetAttrString(from, "id")) == NULL) {
|
|
PyErr_SetString(PyExc_TypeError, "from is not a string and has no id");
|
|
return -1;
|
|
}
|
|
if (!PyString_Check(from_id)) {
|
|
Py_DECREF(from_id);
|
|
PyErr_SetString(PyExc_TypeError, "id of from is not a string");
|
|
return -1;
|
|
}
|
|
self->operation->setFrom(PyString_AsString(from_id));
|
|
Py_DECREF(from_id);
|
|
}
|
|
PyObject * to = PyDict_GetItemString(kwds, "to");
|
|
if (to != NULL) {
|
|
PyObject * to_id = 0;
|
|
if (PyString_Check(to)) {
|
|
to_id = to;
|
|
Py_INCREF(to_id);
|
|
} else if ((to_id = PyObject_GetAttrString(to, "id")) == NULL) {
|
|
PyErr_SetString(PyExc_TypeError, "to is not a string and has no id");
|
|
return -1;
|
|
}
|
|
if (!PyString_Check(to_id)) {
|
|
Py_DECREF(to_id);
|
|
PyErr_SetString(PyExc_TypeError, "id of to is not a string");
|
|
return -1;
|
|
}
|
|
self->operation->setTo(PyString_AsString(to_id));
|
|
Py_DECREF(to_id);
|
|
}
|
|
}
|
|
std::vector<Root> & args_list = self->operation->modifyArgs();
|
|
assert(args_list.empty());
|
|
if (arg1 != 0 && addToArgs(args_list, arg1) != 0) {
|
|
return -1;
|
|
}
|
|
if (arg2 != 0 && addToArgs(args_list, arg2) != 0) {
|
|
return -1;
|
|
}
|
|
if (arg3 != 0 && addToArgs(args_list, arg3) != 0) {
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static PyObject * Operation_new(PyTypeObject * type, PyObject *, PyObject *)
|
|
{
|
|
// This looks allot like the default implementation, except we call the
|
|
// in-place constructor.
|
|
PyOperation * self = (PyOperation *)type->tp_alloc(type, 0);
|
|
if (self != NULL) {
|
|
new (&(self->operation)) RootOperation(nullptr);
|
|
}
|
|
return (PyObject *)self;
|
|
}
|
|
|
|
PyTypeObject PyConstOperation_Type = {
|
|
PyObject_HEAD_INIT(&PyType_Type)
|
|
0, // ob_size
|
|
"atlas.Operation", // tp_name
|
|
sizeof(PyOperation), // tp_basicsize
|
|
0, // tp_itemsize
|
|
// methods
|
|
(destructor)Operation_dealloc, // tp_dealloc
|
|
0, // tp_print
|
|
0, // tp_getattr
|
|
0, // tp_setattr
|
|
0, // tp_compare
|
|
0, // tp_repr
|
|
&Operation_num, // tp_as_number
|
|
&Operation_seq, // tp_as_sequence
|
|
0, // tp_as_mapping
|
|
0, // tp_hash
|
|
0, // tp_call
|
|
0, // tp_str
|
|
(getattrofunc)Operation_getattro, // tp_getattro
|
|
0, // tp_setattro
|
|
0, // tp_as_buffer
|
|
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, // tp_flags
|
|
"Operation objects", // tp_doc
|
|
0, // tp_travers
|
|
0, // tp_clear
|
|
0, // tp_richcompare
|
|
0, // tp_weaklistoffset
|
|
0, // tp_iter
|
|
0, // tp_iternext
|
|
ConstOperation_methods, // tp_methods
|
|
0, // tp_members
|
|
0, // tp_getset
|
|
0, // tp_base
|
|
0, // tp_dict
|
|
0, // tp_descr_get
|
|
0, // tp_descr_set
|
|
0, // tp_dictoffset
|
|
(initproc)Operation_init, // tp_init
|
|
0, // tp_alloc
|
|
Operation_new, // tp_new
|
|
};
|
|
|
|
PyTypeObject PyOperation_Type = {
|
|
PyObject_HEAD_INIT(&PyType_Type)
|
|
0, // ob_size
|
|
"atlas.Operation", // tp_name
|
|
0, // tp_basicsize
|
|
0, // tp_itemsize
|
|
// methods
|
|
0, // tp_dealloc
|
|
0, // tp_print
|
|
0, // tp_getattr
|
|
0, // tp_setattr
|
|
0, // tp_compare
|
|
0, // tp_repr
|
|
&Operation_num, // tp_as_number
|
|
&Operation_seq, // tp_as_sequence
|
|
0, // tp_as_mapping
|
|
0, // tp_hash
|
|
0, // tp_call
|
|
0, // tp_str
|
|
0, // tp_getattro
|
|
(setattrofunc)Operation_setattro, // tp_setattro
|
|
0, // tp_as_buffer
|
|
Py_TPFLAGS_DEFAULT, // tp_flags
|
|
"Operation objects", // tp_doc
|
|
0, // tp_travers
|
|
0, // tp_clear
|
|
0, // tp_richcompare
|
|
0, // tp_weaklistoffset
|
|
0, // tp_iter
|
|
0, // tp_iternext
|
|
Operation_methods, // tp_methods
|
|
0, // tp_members
|
|
0, // tp_getset
|
|
&PyConstOperation_Type, // tp_base
|
|
0, // tp_dict
|
|
0, // tp_descr_get
|
|
0, // tp_descr_set
|
|
0, // tp_dictoffset
|
|
0, // tp_init
|
|
0, // tp_alloc
|
|
Operation_new, // tp_new
|
|
};
|
|
|
|
/*
|
|
* Beginning of Operation creation functions section.
|
|
*/
|
|
|
|
PyOperation * newPyOperation()
|
|
{
|
|
return (PyOperation *)PyOperation_Type.tp_new(&PyOperation_Type, 0, 0);
|
|
}
|
|
|
|
PyOperation * newPyConstOperation()
|
|
{
|
|
return (PyOperation *)PyConstOperation_Type.tp_new(&PyConstOperation_Type, 0, 0);
|
|
}
|