diff --git a/cpp/src/arrow/types/string.h b/cpp/src/arrow/types/string.h index a4d1522210f84..8ccc0a9698a54 100644 --- a/cpp/src/arrow/types/string.h +++ b/cpp/src/arrow/types/string.h @@ -136,12 +136,13 @@ class StringBuilder : public ListBuilder { } Status Append(const std::string& value) { - RETURN_NOT_OK(ListBuilder::Append()); - return byte_builder_->Append(reinterpret_cast(value.c_str()), - value.size()); + return Append(value.c_str(), value.size()); } - Status Append(const uint8_t* value, int32_t length); + Status Append(const char* value, int32_t length) { + RETURN_NOT_OK(ListBuilder::Append()); + return byte_builder_->Append(reinterpret_cast(value), length); + } Status Append(const std::vector& values, uint8_t* null_bytes); diff --git a/python/arrow/array.pyx b/python/arrow/array.pyx index 15639f7b4ebd4..3a3210d6cc100 100644 --- a/python/arrow/array.pyx +++ b/python/arrow/array.pyx @@ -129,6 +129,14 @@ cdef class UInt64Array(NumericArray): pass +cdef class FloatArray(NumericArray): + pass + + +cdef class DoubleArray(NumericArray): + pass + + cdef class ListArray(Array): pass @@ -141,6 +149,7 @@ cdef dict _array_classes = { LogicalType_NA: NullArray, LogicalType_BOOL: BooleanArray, LogicalType_INT64: Int64Array, + LogicalType_DOUBLE: DoubleArray, LogicalType_LIST: ListArray, LogicalType_STRING: StringArray, } diff --git a/python/arrow/tests/test_convert_builtin.py b/python/arrow/tests/test_convert_builtin.py index bc30191d90f52..d651fbe357aa8 100644 --- a/python/arrow/tests/test_convert_builtin.py +++ b/python/arrow/tests/test_convert_builtin.py @@ -50,10 +50,18 @@ def test_garbage_collection(self): assert arrow.total_allocated_bytes() == bytes_before def test_double(self): - pass + data = [1.5, 1, None, 2.5, None, None] + arr = arrow.from_pylist(data) + assert len(arr) == 6 + assert arr.null_count == 3 + assert arr.type == arrow.double() def test_string(self): - pass + data = ['foo', b'bar', None, 'arrow'] + arr = arrow.from_pylist(data) + assert len(arr) == 4 + assert arr.null_count == 1 + assert arr.type == arrow.string() def test_list_of_int(self): data = [[1, 2, 3], [], None, [1, 2]] diff --git a/python/src/pyarrow/adapters/builtin.cc b/python/src/pyarrow/adapters/builtin.cc index 234f126a8759e..0b689113ad49a 100644 --- a/python/src/pyarrow/adapters/builtin.cc +++ b/python/src/pyarrow/adapters/builtin.cc @@ -256,10 +256,10 @@ class BoolConverter : public TypedConverter { class Int64Converter : public TypedConverter { public: - Status AppendData(PyObject* obj, int64_t size) override { + Status AppendData(PyObject* seq, int64_t size) override { int64_t val; for (int64_t i = 0; i < size; ++i) { - OwnedRef item(PySequence_GetItem(obj, i)); + OwnedRef item(PySequence_GetItem(seq, i)); if (item.obj() == Py_None) { RETURN_ARROW_NOT_OK(typed_builder_->AppendNull()); } else { @@ -275,6 +275,17 @@ class Int64Converter : public TypedConverter { class DoubleConverter : public TypedConverter { public: Status AppendData(PyObject* seq, int64_t size) override { + int64_t val; + for (int64_t i = 0; i < size; ++i) { + OwnedRef item(PySequence_GetItem(seq, i)); + if (item.obj() == Py_None) { + RETURN_ARROW_NOT_OK(typed_builder_->AppendNull()); + } else { + val = PyFloat_AsDouble(item.obj()); + RETURN_IF_PYERROR(); + RETURN_ARROW_NOT_OK(typed_builder_->Append(val)); + } + } return Status::OK(); } }; @@ -282,6 +293,32 @@ class DoubleConverter : public TypedConverter { class StringConverter : public TypedConverter { public: Status AppendData(PyObject* seq, int64_t size) override { + PyObject* item; + PyObject* bytes_obj; + OwnedRef tmp; + const char* bytes; + int32_t length; + for (int64_t i = 0; i < size; ++i) { + item = PySequence_GetItem(seq, i); + OwnedRef holder(item); + + if (item == Py_None) { + RETURN_ARROW_NOT_OK(typed_builder_->AppendNull()); + continue; + } else if (PyUnicode_Check(item)) { + tmp.reset(PyUnicode_AsUTF8String(item)); + RETURN_IF_PYERROR(); + bytes_obj = tmp.obj(); + } else if (PyBytes_Check(item)) { + bytes_obj = item; + } else { + return Status::TypeError("Non-string value encountered"); + } + // No error checking + length = PyBytes_GET_SIZE(bytes_obj); + bytes = PyBytes_AS_STRING(bytes_obj); + RETURN_ARROW_NOT_OK(typed_builder_->Append(bytes, length)); + } return Status::OK(); } };