finish removing boost python dependency, looking promising!

This commit is contained in:
Thomas Fussell 2017-07-03 07:42:35 -07:00
parent 588809d74d
commit dbe60a5227
2 changed files with 42 additions and 35 deletions

View File

@ -6,6 +6,7 @@
#include <cassert> #include <cassert>
#include <stdexcept> #include <stdexcept>
#include <iostream> #include <iostream>
#include <Python.h>
namespace xlnt { namespace xlnt {
namespace arrow { namespace arrow {
@ -116,10 +117,10 @@ class streambuf : public std::basic_streambuf<char>
PyObject *python_file_obj, PyObject *python_file_obj,
std::size_t buffer_size_ = 0) std::size_t buffer_size_ = 0)
: :
py_read (PyObject_GetAttr(python_file_obj, "read")), py_read (PyObject_GetAttrString(python_file_obj, "read")),
py_write(PyObject_GetAttr(python_file_obj, "write")), py_write(PyObject_GetAttrString(python_file_obj, "write")),
py_seek (PyObject_GetAttr(python_file_obj, "seek")), py_seek (PyObject_GetAttrString(python_file_obj, "seek")),
py_tell (PyObject_GetAttr(python_file_obj, "tell")), py_tell (PyObject_GetAttrString(python_file_obj, "tell")),
buffer_size(buffer_size_ != 0 ? buffer_size_ : default_buffer_size), buffer_size(buffer_size_ != 0 ? buffer_size_ : default_buffer_size),
write_buffer(0), write_buffer(0),
pos_of_read_buffer_end_in_py_file(0), pos_of_read_buffer_end_in_py_file(0),
@ -132,17 +133,13 @@ class streambuf : public std::basic_streambuf<char>
py_tell and py_seek. py_tell and py_seek.
*/ */
if (py_tell != nullptr) { if (py_tell != nullptr) {
try {
PyObject_CallFunction(py_tell, nullptr); PyObject_CallFunction(py_tell, nullptr);
} if (PyErr_Occurred() != nullptr)
catch (bp::error_already_set&) { {
py_tell = nullptr; py_tell = nullptr;
py_seek = nullptr; py_seek = nullptr;
/* Boost.Python does not do any Python exception handling whatsoever PyErr_Clear();
So we need to catch it by hand like so. }
*/
PyErr_Clear();
}
} }
if (py_write != nullptr) { if (py_write != nullptr) {
@ -157,8 +154,8 @@ class streambuf : public std::basic_streambuf<char>
setp(0, 0); setp(0, 0);
} }
if (py_tell != nulllptr) { if (py_tell != nullptr) {
auto py_pos = static_cast<off_type>(PyLong_AsLong(PyObject_CallFunction(py_tell, nullptr))); auto py_pos = extract_int<off_type>(PyObject_CallFunction(py_tell, nullptr));
pos_of_read_buffer_end_in_py_file = py_pos; pos_of_read_buffer_end_in_py_file = py_pos;
pos_of_write_buffer_end_in_py_file = py_pos; pos_of_write_buffer_end_in_py_file = py_pos;
} }
@ -188,16 +185,15 @@ class streambuf : public std::basic_streambuf<char>
"That Python file object has no 'read' attribute"); "That Python file object has no 'read' attribute");
} }
read_buffer = PyObject_CallFunction(py_read, "i", buffer_size); read_buffer = PyObject_CallFunction(py_read, "i", buffer_size);
char *read_buffer_data; char *read_buffer_data = nullptr;
bp::ssize_t py_n_read; Py_ssize_t py_n_read = 0;
if (PyBytes_AsStringAndSize(read_buffer.ptr(), if (PyBytes_AsStringAndSize(read_buffer, &read_buffer_data, &py_n_read) == -1) {
&read_buffer_data, &py_n_read) == -1) {
setg(0, 0, 0); setg(0, 0, 0);
throw std::invalid_argument( throw std::invalid_argument(
"The method 'read' of the Python file object " "The method 'read' of the Python file object "
"did not return a string."); "did not return a string.");
} }
off_type n_read = (off_type)py_n_read; auto n_read = (off_type)py_n_read;
pos_of_read_buffer_end_in_py_file += n_read; pos_of_read_buffer_end_in_py_file += n_read;
setg(read_buffer_data, read_buffer_data, read_buffer_data + n_read); setg(read_buffer_data, read_buffer_data, read_buffer_data + n_read);
// ^^^27.5.2.3.1 (4) // ^^^27.5.2.3.1 (4)
@ -212,11 +208,12 @@ class streambuf : public std::basic_streambuf<char>
"That Python file object has no 'write' attribute"); "That Python file object has no 'write' attribute");
} }
farthest_pptr = std::max(farthest_pptr, pptr()); farthest_pptr = std::max(farthest_pptr, pptr());
off_type n_written = (off_type)(farthest_pptr - pbase()); auto n_written = (off_type)(farthest_pptr - pbase());
bp::str chunk(pbase(), farthest_pptr); auto chunk = PyBytes_FromStringAndSize(pbase(), farthest_pptr - pbase());
py_write(chunk); PyObject_CallFunction(py_write, "O", chunk);
if (!traits_type::eq_int_type(c, traits_type::eof())) { if (!traits_type::eq_int_type(c, traits_type::eof())) {
py_write(traits_type::to_char_type(c)); auto ch = traits_type::to_char_type(c);
PyObject_CallFunction(py_write, "y#", reinterpret_cast<char *>(&ch), 1);
n_written++; n_written++;
} }
if (n_written) { if (n_written) {
@ -314,8 +311,8 @@ class streambuf : public std::basic_streambuf<char>
if (which == std::ios_base::in) off -= egptr() - gptr(); if (which == std::ios_base::in) off -= egptr() - gptr();
else if (which == std::ios_base::out) off += pptr() - pbase(); else if (which == std::ios_base::out) off += pptr() - pbase();
} }
py_seek(off, whence); PyObject_CallFunction(py_seek, "ii", off, whence);
result = off_type(bp::extract<off_type>(py_tell())); result = extract_int<off_type>(PyObject_CallFunction(py_tell, nullptr));
if (which == std::ios_base::in) underflow(); if (which == std::ios_base::in) underflow();
} }
return *result; return *result;
@ -410,6 +407,15 @@ class streambuf : public std::basic_streambuf<char>
return pos_of_buffer_end_in_py_file + (buf_sought - buf_end); return pos_of_buffer_end_in_py_file + (buf_sought - buf_end);
} }
template<typename T>
T extract_int(PyObject *o)
{
auto value = PyLong_AsLong(o);
Py_DECREF(o);
return static_cast<T>(value);
}
public: public:
class istream : public std::istream class istream : public std::istream
@ -442,7 +448,7 @@ struct streambuf_capsule
streambuf python_streambuf; streambuf python_streambuf;
streambuf_capsule( streambuf_capsule(
bp::object& python_file_obj, PyObject *python_file_obj,
std::size_t buffer_size=0) std::size_t buffer_size=0)
: :
python_streambuf(python_file_obj, buffer_size) python_streambuf(python_file_obj, buffer_size)
@ -452,7 +458,7 @@ struct streambuf_capsule
struct ostream : private streambuf_capsule, streambuf::ostream struct ostream : private streambuf_capsule, streambuf::ostream
{ {
ostream( ostream(
bp::object& python_file_obj, PyObject *python_file_obj,
std::size_t buffer_size=0) std::size_t buffer_size=0)
: :
streambuf_capsule(python_file_obj, buffer_size), streambuf_capsule(python_file_obj, buffer_size),
@ -461,10 +467,13 @@ struct ostream : private streambuf_capsule, streambuf::ostream
~ostream() ~ostream()
{ {
try { if (this->good())
if (this->good()) this->flush(); {
this->flush();
} }
catch (bp::error_already_set&) {
if (PyErr_Occurred() != nullptr)
{
PyErr_Clear(); PyErr_Clear();
throw std::runtime_error( throw std::runtime_error(
"Problem closing python ostream.\n" "Problem closing python ostream.\n"

View File

@ -7,9 +7,7 @@
PyObject *xlsx2arrow(PyObject *file) PyObject *xlsx2arrow(PyObject *file)
{ {
boost::python::handle<> boost_file_handle(file); xlnt::arrow::streambuf buffer(file);
boost::python::object boost_file(boost_file_handle);
boost_adaptbx::python::streambuf buffer(boost_file);
std::istream stream(&buffer); std::istream stream(&buffer);
std::shared_ptr<arrow::Schema> schema; std::shared_ptr<arrow::Schema> schema;
std::vector<std::shared_ptr<arrow::Column>> columns; std::vector<std::shared_ptr<arrow::Column>> columns;