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

View File

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