/* Copyright (C) 2018 Erik Ogenvik 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "CyPy_Operation.h" #include "CyPy_Element.h" #include "CyPy_RootEntity.h" #include "rules/entityfilter/python/CyPy_EntityFilter.h" #include "CyPy_Oplist.h" #include #include #include 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; CyPy_Operation::CyPy_Operation(Py::PythonClassInstance* self, Py::Tuple& args, Py::Dict& kwds) : WrapperBase(self, args, kwds) { if (args.size() == 0) { throw Py::TypeError("Must submit argument for operation type."); } auto parent = verifyString(args.front()); Root r = Atlas::Objects::Factories::instance()->createObject(parent); m_value = Atlas::Objects::smart_dynamic_cast(r); if (!m_value) { m_value = Generic(); m_value->setParent(parent); } for (auto entry : kwds) { if (entry.first.isString()) { setattro(entry.first.as_string(), entry.second); } } if (args.size() > 1) { auto& args_list = m_value->modifyArgs(); for (PyCxx_ssize_t i = 1; i < args.size(); ++i) { addToArgs(args_list, args[i]); } } } CyPy_Operation::CyPy_Operation(Py::PythonClassInstance* self, Atlas::Objects::Operation::RootOperation value) : WrapperBase(self, std::move(value)) { } void CyPy_Operation::addToArgs(std::vector& args, const Py::Object& arg) { if (CyPy_Element::check(arg)) { Py::PythonClassObject obj(arg); auto& o = obj.getCxxObject()->m_value; if (o.isMap()) { args.push_back(Atlas::Objects::Factories::instance()->createObject(o.asMap())); } else { throw Py::TypeError("Operation arg is not a map"); } } else if (CyPy_Operation::check(arg)) { Py::PythonClassObject obj(arg); args.push_back(obj.getCxxObject()->m_value); } else if (CyPy_RootEntity::check(arg)) { Py::PythonClassObject obj(arg); args.push_back(obj.getCxxObject()->m_value); } else { throw Py::TypeError("Operation arg is of unknown type"); } } void CyPy_Operation::init_type() { behaviors().name("Operation"); behaviors().doc(""); behaviors().supportNumberType(Py::PythonType::support_number_add); behaviors().supportSequenceType(Py::PythonType::support_sequence_length | Py::PythonType::support_sequence_item); PYCXX_ADD_VARARGS_METHOD(set_serialno, setSerialno, ""); PYCXX_ADD_VARARGS_METHOD(set_refno, setRefno, ""); PYCXX_ADD_VARARGS_METHOD(set_from, setFrom, ""); PYCXX_ADD_VARARGS_METHOD(set_to, setTo, ""); PYCXX_ADD_VARARGS_METHOD(set_seconds, setSeconds, ""); PYCXX_ADD_VARARGS_METHOD(set_future_seconds, setFutureSeconds, ""); PYCXX_ADD_VARARGS_METHOD(set_name, setName, ""); PYCXX_ADD_VARARGS_METHOD(set_args, setArgs, ""); PYCXX_ADD_NOARGS_METHOD(get_serialno, getSerialno, ""); PYCXX_ADD_NOARGS_METHOD(is_default_serialno, isDefaultSerialno, ""); PYCXX_ADD_NOARGS_METHOD(get_refno, getRefno, ""); PYCXX_ADD_NOARGS_METHOD(get_from, getFrom, ""); PYCXX_ADD_NOARGS_METHOD(get_to, getTo, ""); PYCXX_ADD_NOARGS_METHOD(get_seconds, getSeconds, ""); PYCXX_ADD_NOARGS_METHOD(get_future_seconds, getFutureSeconds, ""); PYCXX_ADD_NOARGS_METHOD(get_args, getArgs, ""); PYCXX_ADD_NOARGS_METHOD(get_name, get_name, ""); behaviors().readyType(); } Py::Object CyPy_Operation::setSerialno(const Py::Tuple& args) { args.verify_length(1); auto arg = args.front(); if (!arg.isLong()) { throw Py::TypeError("Must submit long."); } m_value->setSerialno(Py::Long(arg)); return Py::None(); } Py::Object CyPy_Operation::setRefno(const Py::Tuple& args) { args.verify_length(1); auto arg = args.front(); if (!arg.isLong()) { throw Py::TypeError("Must submit long."); } m_value->setRefno(Py::Long(args.front())); return Py::None(); } Py::Object CyPy_Operation::setFrom(const Py::Tuple& args) { args.verify_length(1); auto arg = args.front(); if (!arg.isString()) { throw Py::TypeError("Must submit string."); } m_value->setFrom(Py::String(args.front()).as_string()); return Py::None(); } Py::Object CyPy_Operation::setTo(const Py::Tuple& args) { args.verify_length(1); auto arg = args.front(); if (!arg.isString()) { throw Py::TypeError("Must submit string."); } m_value->setTo(Py::String(args.front()).as_string()); return Py::None(); } Py::Object CyPy_Operation::setSeconds(const Py::Tuple& args) { args.verify_length(1); auto arg = args.front(); if (!arg.isNumeric()) { throw Py::TypeError("Must submit numeric."); } m_value->setSeconds(Py::Float(args.front())); return Py::None(); } Py::Object CyPy_Operation::setFutureSeconds(const Py::Tuple& args) { args.verify_length(1); auto arg = args.front(); if (!arg.isNumeric()) { throw Py::TypeError("Must submit numeric."); } m_value->setFutureSeconds(Py::Float(args.front())); return Py::None(); } Py::Object CyPy_Operation::setName(const Py::Tuple& args) { args.verify_length(1); auto arg = args.front(); if (!arg.isString()) { throw Py::TypeError("Must submit string."); } m_value->setName(Py::String(args.front()).as_string()); return Py::None(); } Py::Object CyPy_Operation::setArgs(const Py::Tuple& args) { args.verify_length(1); auto arg = args.front(); if (!arg.isSequence()) { throw Py::TypeError("Must submit list."); } Py::Sequence argsAsList(args.front()); std::vector argslist; for (auto item : argsAsList) { if (CyPy_Operation::check(item)) { argslist.push_back(CyPy_Operation::value(item)); } else if (CyPy_Element::check(item)) { auto& e = CyPy_Element::value(item); if (!e.isMap()) { throw Py::TypeError("args contains non map"); } argslist.push_back(Factories::instance()->createObject(e.Map())); } else if (CyPy_RootEntity::check(item)) { argslist.push_back(CyPy_RootEntity::value(item)); } else { throw Py::TypeError("args contains non Atlas Object"); } } m_value->setArgs(argslist); return Py::None(); } Py::Object CyPy_Operation::getSerialno() { return Py::Long(m_value->getSerialno()); } Py::Object CyPy_Operation::isDefaultSerialno() { return Py::Boolean(m_value->isDefaultSerialno()); } Py::Object CyPy_Operation::getRefno() { return Py::Long(m_value->getRefno()); } Py::Object CyPy_Operation::getFrom() { return Py::String(m_value->getFrom()); } Py::Object CyPy_Operation::getTo() { return Py::String(m_value->getTo()); } Py::Object CyPy_Operation::getSeconds() { return Py::Float(m_value->getSeconds()); } Py::Object CyPy_Operation::getFutureSeconds() { return Py::Float(m_value->getFutureSeconds()); } Py::Object CyPy_Operation::getName() { return Py::String(m_value->getName()); } Py::Object CyPy_Operation::getArgs() { auto args_list = m_value->getArgs(); Py::List list; for (auto& arg : args_list) { auto elementObj = CyPy_Element::wrap(arg->asMessage()); list.append(elementObj); } return list; } Py::Object CyPy_Operation::get_name() { return Py::String("op"); } PyCxx_ssize_t CyPy_Operation::sequence_length() { return Py::Long(m_value->getArgs().size()); } Py::Object CyPy_Operation::sequence_item(Py_ssize_t item) { auto& args = m_value->getArgs(); if (item < 0 || item >= (Py_ssize_t) args.size()) { throw Py::IndexError("Operation.[]: Not enough op arguments"); } const Root& arg = args[item]; RootOperation op = Atlas::Objects::smart_dynamic_cast(arg); if (op) { return CyPy_Operation::wrap(std::move(op)); } RootEntity ent = Atlas::Objects::smart_dynamic_cast(arg); if (ent) { return CyPy_RootEntity::wrap(std::move(ent)); } //log(WARNING, "Non operation or entity being returned as arg of operation"); return CyPy_Element::wrap(arg->asMessage()); } Py::Object CyPy_Operation::number_add(const Py::Object& other) { //It's not clear what use this is... if (other.isNone()) { return self(); } if (CyPy_Oplist::check(other)) { auto list = CyPy_Oplist::value(other); list.push_back(m_value); return CyPy_Oplist::wrap(list); } if (CyPy_Operation::check(other)) { std::vector oplist; oplist.push_back(m_value); oplist.push_back(CyPy_Operation::value(other)); return CyPy_Oplist::wrap(oplist); } throw Py::TypeError("Unknown other in Operation.num_add"); } Py::Object CyPy_Operation::getattro(const Py::String& name) { auto nameStr = name.as_string(); if (nameStr == "from_") { return Py::String(m_value->getFrom()); } if (nameStr == "to") { return Py::String(m_value->getTo()); } //Why should "id" return the parent? if (nameStr == "id") { return Py::String(m_value->getParent()); } if (nameStr == "future_seconds") { return getFutureSeconds(); } if (nameStr == "name") { return getName(); } if (nameStr == "serialno") { return getSerialno(); } if (nameStr == "refno") { return getRefno(); } if (nameStr == "args") { return getArgs(); } return PythonExtensionBase::getattro(name); } int CyPy_Operation::setattro(const Py::String& name, const Py::Object& attr) { auto nameStr = name.as_string(); if (nameStr == "from_") { if (attr.isString()) { m_value->setFrom(attr.as_string()); } else if (attr.hasAttr("id") && attr.getAttr("id").isString()) { m_value->setFrom(attr.getAttr("id").as_string()); } else { throw Py::TypeError("from_ is neither a string nor an object with an 'id' attribute"); } return 0; } if (nameStr == "to") { if (attr.isString()) { m_value->setTo(attr.as_string()); } else if (attr.hasAttr("id") && attr.getAttr("id").isString()) { m_value->setTo(attr.getAttr("id").as_string()); } else { throw Py::TypeError("to is neither a string nor an object with an 'id' attribute"); } return 0; } if (nameStr == "future_seconds") { m_value->setFutureSeconds(verifyFloat(attr)); return 0; } if (nameStr == "name") { m_value->setName(verifyString(attr)); return 0; } if (nameStr == "serialno") { m_value->setSerialno(verifyLong(attr)); return 0; } if (nameStr == "refno") { m_value->setRefno(verifyLong(attr)); return 0; } if (nameStr == "args") { setArgs(Py::Tuple(attr)); return 0; } throw Py::AttributeError("unknown attribute"); }