Repository: pandas-dev/pandas
Pull request: Fixed tuple to List Conversion in Dataframe class
- [X] closes #25075 
- [X] tests added / passed
- [X] passes `git diff upstream/master -u -- "*.py" | flake8 --diff`
- [X] whatsnew entry

Traceback of issue #25075 
- [pandas/core/frame.py: L#435](https://github.com/pandas-dev/pandas/blob/master/pandas/core/frame.py#L435) `to_arrays(data, columns, dtype=dtype)`
- [pandas/core/internals/construction.py: L#403](https://github.com/pandas-dev/pandas/blob/master/pandas/core/internals/construction.py#L403) `_list_to_arrays(data, columns, coerce_float=coerce_float, dtype=dtype)`
- [pandas/core/internals/construction.py: L#434](https://github.com/pandas-dev/pandas/blob/master/pandas/core/internals/construction.py#L434) `lib.to_object_array(data)`
- [pandas/_libs/lib.pyx: L#2283](https://github.com/pandas-dev/pandas/blob/master/pandas/_libs/lib.pyx#L2283) `row[j]`

### Cause of "Segmentation fault"
**row** variable as declared on [line#2266](https://github.com/pandas-dev/pandas/blob/master/pandas/_libs/lib.pyx#L2266) has to be of _list_ type.
It is tried to assign a tuple by converting to a list on [line#2280](https://github.com/pandas-dev/pandas/blob/master/pandas/_libs/lib.pyx#L2280) using `row = <list>input_rows[i]`
The conversion fails. As a result, the type of **row** is tuple (not a list) after line#2280. The `Segmentation fault` is returned when tried to access a value from it at [line#2283](https://github.com/pandas-dev/pandas/blob/master/pandas/_libs/lib.pyx#L2283)

### Fixes in #25089 
- At [line#2280](https://github.com/pandas-dev/pandas/blob/master/pandas/_libs/lib.pyx#L2280) in [_libs/lib.pyx](https://github.com/pandas-dev/pandas/blob/master/pandas/_libs/lib.pyx), changed the style of converting tuple into list.
  `<list>` --> `list()`
  This successfully converts tuples into list and further exception does not occur. As a result, function `to_object_array` correctly returns the numpy ndarray, what it's supposed to return.

As a result, not only `Segmentation fault` is removed, the need of function to raise `Type Error` is also eliminated.

Problem statement:
Segmentation fault while creating dataframe from list of mixed-type rows
```python
In [2]: pd.DataFrame([
   ...:     [1, 2],
   ...:     (3, 4)
   ...: ])
Segmentation fault: 11
```

I'd like to see a `TypeError` here, instead of a segfault.

<details>

INSTALLED VERSIONS
------------------
commit: None
python: 3.7.2.final.0
python-bits: 64
OS: Darwin
OS-release: 18.2.0
machine: x86_64
processor: i386
byteorder: little
LC_ALL: None
LANG: en_US.UTF-8
LOCALE: en_US.UTF-8

pandas: 0.24.0
pytest: None
pip: 19.0.1
setuptools: 40.7.1
Cython: None
numpy: 1.15.4
scipy: 1.2.0
pyarrow: None
xarray: None
IPython: 7.2.0
sphinx: None
patsy: None
dateutil: 2.7.5
pytz: 2018.9
blosc: None
bottleneck: None
tables: None
numexpr: None
feather: None
matplotlib: 3.0.2
openpyxl: None
xlrd: None
xlwt: None
xlsxwriter: None
lxml.etree: None
bs4: None
html5lib: None
sqlalchemy: None
pymysql: None
psycopg2: None
jinja2: 2.10
s3fs: None
fastparquet: None
pandas_gbq: None
pandas_datareader: None
gcsfs: None

</details>

Hints from issue discussion:
Thanks!  I can confirm this behavior on master:
```python
In [1]: import pandas as pd; pd.__version__                                                                                                      
Out[1]: '0.25.0.dev0+37.g5c40cf2'

In [2]: pd.DataFrame([[1, 2], (3, 4)])                                                                                                           
Segmentation fault
```
Looks like a regression, as this previously raised a `TypeError` in 0.23.4:
```python
In [1]: import pandas as pd; pd.__version__
Out[1]: '0.23.4'

In [2]: pd.DataFrame([[1, 2], (3, 4)])
---------------------------------------------------------------------------
TypeError: Expected list, got tuple
```
Seems a bit odd that the error shows no traceback of function calls because whenever there is an exception, python always show the traceback of exception.
This behavior could be because it's directly printed somewhere after catching the exception OR there's some error in API Calling to CPython Code.
I would like to work on this issue and solve it.

Commit message: Modified whatsnew and Done asv check

Patch to review:
diff --git a/doc/source/whatsnew/v0.24.2.rst b/doc/source/whatsnew/v0.24.2.rst
index a047ad46e4887..2524cc8701dfe 100644
--- a/doc/source/whatsnew/v0.24.2.rst
+++ b/doc/source/whatsnew/v0.24.2.rst
@@ -22,13 +22,14 @@ Fixed Regressions
 
 - Fixed regression in :meth:`DataFrame.all` and :meth:`DataFrame.any` where ``bool_only=True`` was ignored (:issue:`25101`)
 
+- Fixed regression in :meth:`DataFrame.__init__`  where mixed type of rows generated `Segmentation fault` (:issue:`25075`)
+
 .. _whatsnew_0242.enhancements:
 
 Enhancements
 ^^^^^^^^^^^^
 
--
--
+- The DataFrame class supports list as well as tuples in the ndarray, which previously raised `TypeError`
 
 .. _whatsnew_0242.bug_fixes:
 
@@ -37,9 +38,7 @@ Bug Fixes
 
 **Conversion**
 
--
--
--
+- Fixed bug in :meth:`lib.pyx` where `tuple` to `list` conversion failed (:issue:`25089`)
 
 **Indexing**
 
@@ -94,4 +93,4 @@ Bug Fixes
 Contributors
 ~~~~~~~~~~~~
 
-.. contributors:: v0.24.1..v0.24.2
\ No newline at end of file
+.. contributors:: v0.24.1..v0.24.2
diff --git a/pandas/_libs/lib.pyx b/pandas/_libs/lib.pyx
index f8875d60049b1..1f0f0a408aee8 100644
--- a/pandas/_libs/lib.pyx
+++ b/pandas/_libs/lib.pyx
@@ -2277,7 +2277,7 @@ def to_object_array(rows: object, int min_width=0):
     result = np.empty((n, k), dtype=object)
 
     for i in range(n):
-        row = <list>input_rows[i]
+        row = list(input_rows[i])
 
         for j in range(len(row)):
             result[i, j] = row[j]
diff --git a/pandas/tests/frame/test_constructors.py b/pandas/tests/frame/test_constructors.py
index 90ad48cac3a5f..8b663227b41ef 100644
--- a/pandas/tests/frame/test_constructors.py
+++ b/pandas/tests/frame/test_constructors.py
@@ -1183,6 +1183,13 @@ def test_constructor_mixed_dict_and_Series(self):
                              index=['a', 'b'])
         tm.assert_frame_equal(result, expected)
 
+    def test_constructor_mixed_type_rows(self):
+        data = [[1, 2], (3, 4)]
+        result = DataFrame(data)
+        data2 = [[1, 2], [3, 4]]
+        expected = DataFrame(data2)
+        tm.assert_frame_equal(result, expected)
+
     def test_constructor_tuples(self):
         result = DataFrame({'A': [(1, 2), (3, 4)]})
         expected = DataFrame({'A': Series([(1, 2), (3, 4)])})


Code review comments:
diff_hunk: @@ -22,13 +22,14 @@ Fixed Regressions
 
 - Fixed regression in :meth:`DataFrame.all` and :meth:`DataFrame.any` where ``bool_only=True`` was ignored (:issue:`25101`)
 
+- Fixed regression in :meth:`DataFrame.__init__`  where mixed type of rows generated `Segmentation fault` (:issue:`25075`)
+
 .. _whatsnew_0242.enhancements:
 
 Enhancements
 ^^^^^^^^^^^^
 
--
--
+- The DataFrame class supports list as well as tuples in the ndarray, which previously raised `TypeError`
path: doc/source/whatsnew/v0.24.2.rst
text: @user1:
this is not needed

diff_hunk: @@ -37,9 +38,7 @@ Bug Fixes
 
 **Conversion**
 
--
--
--
+- Fixed bug in :meth:`lib.pyx` where `tuple` to `list` conversion failed (:issue:`25089`)
path: doc/source/whatsnew/v0.24.2.rst
text: @user1:
this is not needed

diff_hunk: @@ -1183,6 +1183,13 @@ def test_constructor_mixed_dict_and_Series(self):
                              index=['a', 'b'])
         tm.assert_frame_equal(result, expected)
 
+    def test_constructor_mixed_type_rows(self):
+        data = [[1, 2], (3, 4)]
+        result = DataFrame(data)
+        data2 = [[1, 2], [3, 4]]
path: pandas/tests/frame/test_constructors.py
text: @user1:
you can inline data2 to the constructor