diff options
Diffstat (limited to 'src/python/python.cpp')
-rw-r--r-- | src/python/python.cpp | 186 |
1 files changed, 186 insertions, 0 deletions
diff --git a/src/python/python.cpp b/src/python/python.cpp new file mode 100644 index 0000000..53fb867 --- /dev/null +++ b/src/python/python.cpp @@ -0,0 +1,186 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "orcus/env.hpp" +#include "orcus/info.hpp" + +#include "root.hpp" +#include "xlsx.hpp" +#include "ods.hpp" +#include "csv.hpp" +#include "xls_xml.hpp" +#include "gnumeric.hpp" + +#ifdef __ORCUS_SPREADSHEET_MODEL +#include "document.hpp" +#include "sheet.hpp" +#include "sheet_rows.hpp" +#include "cell.hpp" +#include "named_expression.hpp" +#include "named_expressions.hpp" +#include "formula_token.hpp" +#include "formula_tokens.hpp" +#endif + +#include <iostream> +#include <sstream> +#include <string> + +#include <Python.h> + +#define ORCUS_DEBUG_PYTHON 0 +#define GETSTATE(m) ((struct module_state*)PyModule_GetState(m)) + +using namespace std; + +namespace orcus { namespace python { + +namespace { + +#if ORCUS_DEBUG_PYTHON +void print_args(PyObject* args) +{ + string args_str; + PyObject* repr = PyObject_Repr(args); + if (repr) + { + Py_INCREF(repr); + args_str = PyBytes_AsString(repr); + Py_DECREF(repr); + } + cout << args_str << "\n"; +} +#endif + +PyMethodDef orcus_methods[] = +{ + { "detect_format", (PyCFunction)detect_format, METH_VARARGS | METH_KEYWORDS, + "Detect the format type of a spreadsheet file." }, + + { "_csv_read", (PyCFunction)csv_read, METH_VARARGS | METH_KEYWORDS, + "Load specified csv file into a document model." }, + + { "_ods_read", (PyCFunction)ods_read, METH_VARARGS | METH_KEYWORDS, + "Load specified ods file into a document model." }, + + { "_xlsx_read", (PyCFunction)xlsx_read, METH_VARARGS | METH_KEYWORDS, + "Load specified xlsx file into a document model." }, + + { "_xls_xml_read", (PyCFunction)xls_xml_read, METH_VARARGS | METH_KEYWORDS, + "Load specified xls-xml file into a document model." }, + + { "_gnumeric_read", (PyCFunction)gnumeric_read, METH_VARARGS | METH_KEYWORDS, + "Load specified gnumeric file into a document model." }, + + { nullptr, nullptr, 0, nullptr } +}; + +struct module_state +{ + PyObject* error; +}; + +int orcus_traverse(PyObject* m, visitproc visit, void* arg) +{ + Py_VISIT(GETSTATE(m)->error); + return 0; +} + +int orcus_clear(PyObject* m) +{ + Py_CLEAR(GETSTATE(m)->error); + return 0; +} + +[[maybe_unused]] +bool add_type_to_module(PyObject* m, PyTypeObject* typeobj, const char* type_name) +{ + if (PyType_Ready(typeobj)) + return false; + + Py_INCREF(typeobj); + if (PyModule_AddObject(m, type_name, reinterpret_cast<PyObject*>(typeobj)) < 0) + { + Py_DECREF(m); + Py_DECREF(typeobj); + return false; + } + + return true; +} + +bool populate_module_attributes(PyObject* m) +{ + std::ostringstream os; + os << orcus::get_version_major() << '.' + << orcus::get_version_minor() << '.' + << orcus::get_version_micro(); + + PyObject* version = PyUnicode_FromString(os.str().data()); + if (PyModule_AddObject(m, "__version__", version) < 0) + return false; + + return true; +} + +} + +struct PyModuleDef moduledef = +{ + PyModuleDef_HEAD_INIT, + "_orcus", + nullptr, + sizeof(struct module_state), + orcus_methods, + nullptr, + orcus_traverse, + orcus_clear, + nullptr +}; + +}} + +extern "C" { + +ORCUS_DLLPUBLIC PyObject* PyInit__orcus() +{ + PyObject* m = PyModule_Create(&orcus::python::moduledef); + if (!orcus::python::populate_module_attributes(m)) + return nullptr; + +#ifdef __ORCUS_SPREADSHEET_MODEL + if (!orcus::python::add_type_to_module(m, orcus::python::get_document_type(), "Document")) + return nullptr; + + if (!orcus::python::add_type_to_module(m, orcus::python::get_sheet_type(), "Sheet")) + return nullptr; + + if (!orcus::python::add_type_to_module(m, orcus::python::get_sheet_rows_type(), "SheetRows")) + return nullptr; + + if (!orcus::python::add_type_to_module(m, orcus::python::get_cell_type(), "Cell")) + return nullptr; + + if (!orcus::python::add_type_to_module(m, orcus::python::get_named_exp_type(), "NamedExpression")) + return nullptr; + + if (!orcus::python::add_type_to_module(m, orcus::python::get_named_exps_type(), "NamedExpressions")) + return nullptr; + + if (!orcus::python::add_type_to_module(m, orcus::python::get_formula_token_type(), "FormulaToken")) + return nullptr; + + if (!orcus::python::add_type_to_module(m, orcus::python::get_formula_tokens_type(), "FormulaTokens")) + return nullptr; +#endif + + return m; +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |