This is an automated email from the ASF dual-hosted git repository.

wesm pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/arrow.git


The following commit(s) were added to refs/heads/master by this push:
     new b926574  ARROW-2722: [Python] Sanitize dtype number to handle edge 
cases
b926574 is described below

commit b9265743c422b6df325948c1ae6f7f86a8b5d092
Author: Antoine Pitrou <[email protected]>
AuthorDate: Mon Jul 9 16:06:20 2018 -0400

    ARROW-2722: [Python] Sanitize dtype number to handle edge cases
    
    Author: Antoine Pitrou <[email protected]>
    
    Closes #2234 from pitrou/ARROW-2722-sanitize-numpy-type-num and squashes 
the following commits:
    
    75faf9ae <Antoine Pitrou> ARROW-2722:  Sanitize dtype number to handle edge 
cases
---
 cpp/src/arrow/python/numpy_convert.cc       | 32 ++---------------------------
 cpp/src/arrow/python/numpy_interop.h        | 13 ++++++++++++
 cpp/src/arrow/python/type_traits.h          | 12 ++---------
 python/pyarrow/tests/test_convert_pandas.py |  6 ++++++
 4 files changed, 23 insertions(+), 40 deletions(-)

diff --git a/cpp/src/arrow/python/numpy_convert.cc 
b/cpp/src/arrow/python/numpy_convert.cc
index e91aae1..97220a5 100644
--- a/cpp/src/arrow/python/numpy_convert.cc
+++ b/cpp/src/arrow/python/numpy_convert.cc
@@ -45,22 +45,6 @@ bool is_contiguous(PyObject* array) {
   }
 }
 
-int cast_npy_type_compat(int type_num) {
-  // Both LONGLONG and INT64 can be observed in the wild, which is buggy. We 
set
-  // U/LONGLONG to U/INT64 so things work properly.
-
-#if (NPY_INT64 == NPY_LONGLONG) && (NPY_SIZEOF_LONGLONG == 8)
-  if (type_num == NPY_LONGLONG) {
-    type_num = NPY_INT64;
-  }
-  if (type_num == NPY_ULONGLONG) {
-    type_num = NPY_UINT64;
-  }
-#endif
-
-  return type_num;
-}
-
 NumPyBuffer::NumPyBuffer(PyObject* ao) : Buffer(nullptr, 0) {
   arr_ = ao;
   Py_INCREF(ao);
@@ -92,7 +76,7 @@ Status GetTensorType(PyObject* dtype, 
std::shared_ptr<DataType>* out) {
     return Status::TypeError("Did not pass numpy.dtype object");
   }
   PyArray_Descr* descr = reinterpret_cast<PyArray_Descr*>(dtype);
-  int type_num = cast_npy_type_compat(descr->type_num);
+  int type_num = fix_numpy_type_num(descr->type_num);
 
   switch (type_num) {
     TO_ARROW_TYPE_CASE(BOOL, uint8);
@@ -100,16 +84,10 @@ Status GetTensorType(PyObject* dtype, 
std::shared_ptr<DataType>* out) {
     TO_ARROW_TYPE_CASE(INT16, int16);
     TO_ARROW_TYPE_CASE(INT32, int32);
     TO_ARROW_TYPE_CASE(INT64, int64);
-#if (NPY_INT64 != NPY_LONGLONG)
-    TO_ARROW_TYPE_CASE(LONGLONG, int64);
-#endif
     TO_ARROW_TYPE_CASE(UINT8, uint8);
     TO_ARROW_TYPE_CASE(UINT16, uint16);
     TO_ARROW_TYPE_CASE(UINT32, uint32);
     TO_ARROW_TYPE_CASE(UINT64, uint64);
-#if (NPY_UINT64 != NPY_ULONGLONG)
-    TO_ARROW_CASE(ULONGLONG);
-#endif
     TO_ARROW_TYPE_CASE(FLOAT16, float16);
     TO_ARROW_TYPE_CASE(FLOAT32, float32);
     TO_ARROW_TYPE_CASE(FLOAT64, float64);
@@ -160,7 +138,7 @@ Status NumPyDtypeToArrow(PyObject* dtype, 
std::shared_ptr<DataType>* out) {
 }
 
 Status NumPyDtypeToArrow(PyArray_Descr* descr, std::shared_ptr<DataType>* out) 
{
-  int type_num = cast_npy_type_compat(descr->type_num);
+  int type_num = fix_numpy_type_num(descr->type_num);
 
   switch (type_num) {
     TO_ARROW_TYPE_CASE(BOOL, boolean);
@@ -168,16 +146,10 @@ Status NumPyDtypeToArrow(PyArray_Descr* descr, 
std::shared_ptr<DataType>* out) {
     TO_ARROW_TYPE_CASE(INT16, int16);
     TO_ARROW_TYPE_CASE(INT32, int32);
     TO_ARROW_TYPE_CASE(INT64, int64);
-#if (NPY_INT64 != NPY_LONGLONG)
-    TO_ARROW_TYPE_CASE(LONGLONG, int64);
-#endif
     TO_ARROW_TYPE_CASE(UINT8, uint8);
     TO_ARROW_TYPE_CASE(UINT16, uint16);
     TO_ARROW_TYPE_CASE(UINT32, uint32);
     TO_ARROW_TYPE_CASE(UINT64, uint64);
-#if (NPY_UINT64 != NPY_ULONGLONG)
-    TO_ARROW_CASE(ULONGLONG);
-#endif
     TO_ARROW_TYPE_CASE(FLOAT16, float16);
     TO_ARROW_TYPE_CASE(FLOAT32, float32);
     TO_ARROW_TYPE_CASE(FLOAT64, float64);
diff --git a/cpp/src/arrow/python/numpy_interop.h 
b/cpp/src/arrow/python/numpy_interop.h
index 0715c66..b62c4e6 100644
--- a/cpp/src/arrow/python/numpy_interop.h
+++ b/cpp/src/arrow/python/numpy_interop.h
@@ -80,6 +80,19 @@ inline int import_numpy() {
   return 0;
 }
 
+// See above about the missing Numpy integer type numbers
+inline int fix_numpy_type_num(int type_num) {
+#if !NPY_INT32_IS_INT && NPY_BITSOF_INT == 32
+  if (type_num == NPY_INT) return NPY_INT32;
+  if (type_num == NPY_UINT) return NPY_UINT32;
+#endif
+#if !NPY_INT64_IS_LONG_LONG && NPY_BITSOF_LONGLONG == 64
+  if (type_num == NPY_LONGLONG) return NPY_INT64;
+  if (type_num == NPY_ULONGLONG) return NPY_UINT64;
+#endif
+  return type_num;
+}
+
 }  // namespace py
 }  // namespace arrow
 
diff --git a/cpp/src/arrow/python/type_traits.h 
b/cpp/src/arrow/python/type_traits.h
index ff39aad..d90517a 100644
--- a/cpp/src/arrow/python/type_traits.h
+++ b/cpp/src/arrow/python/type_traits.h
@@ -263,6 +263,8 @@ struct arrow_traits<Type::BINARY> {
 };
 
 static inline int NumPyTypeSize(int npy_type) {
+  npy_type = fix_numpy_type_num(npy_type);
+
   switch (npy_type) {
     case NPY_BOOL:
     case NPY_INT8:
@@ -277,16 +279,6 @@ static inline int NumPyTypeSize(int npy_type) {
     case NPY_INT64:
     case NPY_UINT64:
       return 8;
-#if !NPY_INT32_IS_INT
-    case NPY_INT:
-    case NPY_UINT:
-      return NPY_BITSOF_INT / 8;
-#endif
-#if !NPY_INT64_IS_LONG_LONG
-    case NPY_LONGLONG:
-    case NPY_ULONGLONG:
-      return NPY_BITSOF_LONGLONG / 8;
-#endif
     case NPY_FLOAT16:
       return 2;
     case NPY_FLOAT32:
diff --git a/python/pyarrow/tests/test_convert_pandas.py 
b/python/pyarrow/tests/test_convert_pandas.py
index 19ffb25..ceedf1a 100644
--- a/python/pyarrow/tests/test_convert_pandas.py
+++ b/python/pyarrow/tests/test_convert_pandas.py
@@ -569,6 +569,12 @@ class TestConvertPrimitiveTypes(object):
         df = pd.DataFrame(data)
         _check_pandas_roundtrip(df)
 
+        # Do the same with pa.array()
+        # (for some reason, it doesn't use the same code paths at all)
+        for np_arr in data.values():
+            arr = pa.array(np_arr)
+            assert arr.to_pylist() == np_arr.tolist()
+
     def test_integer_with_nulls(self):
         # pandas requires upcast to float dtype
 

Reply via email to