PyObject* Flow::create(PyTypeObject* pytype, PyObject* args, PyObject* kwds) { try { // Pick up the operation PyObject* oper = PyDict_GetItemString(kwds, "operation"); if (!oper) throw DataException("missing operation on Flow"); if (!PyObject_TypeCheck(oper, Operation::metadata->pythonClass)) throw DataException("flow operation must be of type operation"); else if (!static_cast<Operation*>(oper)->getLocation()) throw DataException("operation location is unspecified"); // Pick up the item PyObject* item = PyDict_GetItemString(kwds, "item"); if (!item) throw DataException("missing item on Flow"); if (!PyObject_TypeCheck(item, Item::metadata->pythonClass)) throw DataException("flow item must be of type item"); // Pick up the quantity PyObject* q1 = PyDict_GetItemString(kwds, "quantity"); double q2 = q1 ? PythonData(q1).getDouble() : 1.0; // Pick up the effectivity dates DateRange eff; PyObject* eff_start = PyDict_GetItemString(kwds, "effective_start"); if (eff_start) { PythonData d(eff_start); eff.setStart(d.getDate()); } PyObject* eff_end = PyDict_GetItemString(kwds, "effective_end"); if (eff_end) { PythonData d(eff_end); eff.setEnd(d.getDate()); } // Find or create a buffer for the item at the operation location Buffer* buf = Buffer::findOrCreate( static_cast<Item*>(item), static_cast<Operation*>(oper)->getLocation() ); // Pick up the type and create the flow Flow *l; PyObject* t = PyDict_GetItemString(kwds, "type"); if (t) { PythonData d(t); if (d.getString() == "flow_end") l = new FlowEnd( static_cast<Operation*>(oper), static_cast<Buffer*>(buf), q2 ); else if (d.getString() == "flow_transfer_batch") l = new FlowTransferBatch( static_cast<Operation*>(oper), static_cast<Buffer*>(buf), q2 ); else l = new FlowStart( static_cast<Operation*>(oper), static_cast<Buffer*>(buf), q2 ); } else l = new FlowStart( static_cast<Operation*>(oper), static_cast<Buffer*>(buf), q2 ); // Iterate over extra keywords, and set attributes. @todo move this responsibility to the readers... if (l) { l->setEffective(eff); PyObject *key, *value; Py_ssize_t pos = 0; while (PyDict_Next(kwds, &pos, &key, &value)) { PythonData field(value); PyObject* key_utf8 = PyUnicode_AsUTF8String(key); DataKeyword attr(PyBytes_AsString(key_utf8)); Py_DECREF(key_utf8); if (!attr.isA(Tags::effective_end) && !attr.isA(Tags::effective_start) && !attr.isA(Tags::operation) && !attr.isA(Tags::buffer) && !attr.isA(Tags::quantity) && !attr.isA(Tags::type) && !attr.isA(Tags::action)) { const MetaFieldBase* fmeta = l->getType().findField(attr.getHash()); if (!fmeta && l->getType().category) fmeta = l->getType().category->findField(attr.getHash()); if (fmeta) // Update the attribute fmeta->setField(l, field); else l->setProperty(attr.getName(), value); } }; } // Return the object Py_INCREF(l); return static_cast<PyObject*>(l); } catch (...) { PythonType::evalException(); return nullptr; } }
PyObject* Flow::create(PyTypeObject* pytype, PyObject* args, PyObject* kwds) { try { // Pick up the operation PyObject* oper = PyDict_GetItemString(kwds, "operation"); if (!oper) throw DataException("missing operation on Flow"); if (!PyObject_TypeCheck(oper, Operation::metadata->pythonClass)) throw DataException("flow operation must be of type operation"); // Pick up the buffer PyObject* buf = PyDict_GetItemString(kwds, "buffer"); if (!buf) throw DataException("missing buffer on Flow"); if (!PyObject_TypeCheck(buf, Buffer::metadata->pythonClass)) throw DataException("flow buffer must be of type buffer"); // Pick up the quantity PyObject* q1 = PyDict_GetItemString(kwds, "quantity"); double q2 = q1 ? PythonData(q1).getDouble() : 1.0; // Pick up the effectivity dates DateRange eff; PyObject* eff_start = PyDict_GetItemString(kwds, "effective_start"); if (eff_start) { PythonData d(eff_start); eff.setStart(d.getDate()); } PyObject* eff_end = PyDict_GetItemString(kwds, "effective_end"); if (eff_end) { PythonData d(eff_end); eff.setEnd(d.getDate()); } // Pick up the type and create the flow Flow *l; PyObject* t = PyDict_GetItemString(kwds, "type"); if (t) { PythonData d(t); if (d.getString() == "flow_end") l = new FlowEnd( static_cast<Operation*>(oper), static_cast<Buffer*>(buf), q2 ); else if (d.getString() == "flow_fixed_end") l = new FlowFixedEnd( static_cast<Operation*>(oper), static_cast<Buffer*>(buf), q2 ); else if (d.getString() == "flow_fixed_start") l = new FlowFixedStart( static_cast<Operation*>(oper), static_cast<Buffer*>(buf), q2 ); else l = new FlowStart( static_cast<Operation*>(oper), static_cast<Buffer*>(buf), q2 ); } else l = new FlowStart( static_cast<Operation*>(oper), static_cast<Buffer*>(buf), q2 ); // Iterate over extra keywords, and set attributes. @todo move this responsibility to the readers... if (l) { l->setEffective(eff); PyObject *key, *value; Py_ssize_t pos = 0; while (PyDict_Next(kwds, &pos, &key, &value)) { PythonData field(value); PyObject* key_utf8 = PyUnicode_AsUTF8String(key); DataKeyword attr(PyBytes_AsString(key_utf8)); Py_DECREF(key_utf8); if (!attr.isA(Tags::effective_end) && !attr.isA(Tags::effective_start) && !attr.isA(Tags::operation) && !attr.isA(Tags::buffer) && !attr.isA(Tags::quantity) && !attr.isA(Tags::type) && !attr.isA(Tags::action)) { const MetaFieldBase* fmeta = l->getType().findField(attr.getHash()); if (!fmeta && l->getType().category) fmeta = l->getType().category->findField(attr.getHash()); if (fmeta) // Update the attribute fmeta->setField(l, field); else PyErr_Format(PyExc_AttributeError, "attribute '%S' on '%s' can't be updated", key, Py_TYPE(l)->tp_name); } }; } // Return the object Py_INCREF(l); return static_cast<PyObject*>(l); } catch (...) { PythonType::evalException(); return NULL; } }