Repository: matplotlib/matplotlib
Pull request: FIX: allow reshape 2-D to return a bare 1-d list
## PR Summary

reverts a bit of the logic in https://github.com/matplotlib/matplotlib/pull/8116  Attn @anntzer.  

This case allows 

```python
import matplotlib.cbook as cbook

x = [datetime(2018,1,1),  datetime(2018, 2, 1),  datetime(2018,3, 1)]
xnew = cbook._reshape_2D(x, 'x')
```
to return 
```
[array([datetime.datetime(2018, 1, 1, 0, 0),
       datetime.datetime(2018, 2, 1, 0, 0),
       datetime.datetime(2018, 3, 1, 0, 0)], dtype=object)]
```
rather than 

```
[array([datetime.datetime(2018, 1, 1, 0, 0)], dtype=object), 
 array([datetime.datetime(2018, 2, 1, 0, 0)], dtype=object), 
 array([datetime.datetime(2018, 3, 1, 0, 0)], dtype=object)]
```

Closes #11899  Attn @anntzer  and @dstansby 


## PR Checklist

- [ ] Has Pytest style unit tests
- [ ] Code is [Flake 8](http://flake8.pycqa.org/en/latest/) compliant
- [ ] New features are documented, with examples if plot related
- [ ] Documentation is sphinx and numpydoc compliant
- [ ] Added an entry to doc/users/next_whats_new/ if major new feature (follow instructions in README.rst there)
- [ ] Documented in doc/api/api_changes.rst if API changed in a backward-incompatible way

<!--
Thank you so much for your PR!  To help us review your contribution, please
consider the following points:

- A development guide is available at https://matplotlib.org/devdocs/devel/index.html.

- Help with git and github is available at
  https://matplotlib.org/devel/gitwash/development_workflow.html.

- Do not create the PR out of master, but out of a separate branch.

- The PR title should summarize the changes, for example "Raise ValueError on
  non-numeric input to set_xlim".  Avoid non-descriptive titles such as
  "Addresses issue #8576".

- The summary should provide at least 1-2 sentences describing the pull request
  in detail (Why is this change required?  What problem does it solve?) and
  link to any relevant issues.

- If you are contributing fixes to docstrings, please pay attention to
  http://matplotlib.org/devel/documenting_mpl.html#formatting.  In particular,
  note the difference between using single backquotes, double backquotes, and
  asterisks in the markup.

We understand that PRs can sometimes be overwhelming, especially as the
reviews start coming in.  Please let us know if the reviews are unclear or
the recommended next step seems overly demanding, if you would like help in
addressing a reviewer's comments, or if you have been waiting too long to hear
back on your PR.
-->

Problem statement:
Histogram of list of datetimes
### Bug report

**Bug summary**
When creating a histogram of a list of datetimes, the input seems to be interpreted as a sequency of arrays.

**Code for reproduction**

```python
from datetime import datetime
from matplotlib import pyplot as plt
plt.hist([datetime(2018,1,1),  datetime(2018, 2, 1),  datetime(2018,3, 1)])

# We get the expected result,  when we cast the list to a numpy array (but only if we specify the dtype?!)
# import numpy
# plt.hist(numpy.array([datetime(2018,1,1),  datetime(2018, 2, 1),  datetime(2018,3, 1)], dtype='datetime64[h]'))

```

**Actual outcome**

Output of **n** is a list of arrays, indicating that the input dates are interpreted as a sequence of arrays.
```
# If applicable, paste the console output here
([array([1., 0., 0., 0., 0., 0., 0., 0., 0., 0.]),
  array([0., 0., 0., 0., 0., 1., 0., 0., 0., 0.]),   #  <---  expected array instead of list of arrays
  array([0., 0., 0., 0., 0., 0., 0., 0., 0., 1.])],
 array([736695. , 736700.9, 736706.8, 736712.7, 736718.6, 736724.5,
        736730.4, 736736.3, 736742.2, 736748.1, 736754. ]),
 <a list of 3 Lists of Patches objects>)
```
Output of matplotlib version 2.2.0, 2.2.2 and 2.2.3 

**Expected outcome**

```
# If applicable, paste the console output here
(array([1., 0., 0., 0., 0., 1., 0., 0., 0., 1.]),
 array([736695. , 736700.9, 736706.8, 736712.7, 736718.6, 736724.5,
        736730.4, 736736.3, 736742.2, 736748.1, 736754. ]),
 <a list of 10 Patch objects>)
```
This worked in matplotlib version 2.1.2

**Matplotlib version**
<!--Please specify your platform and versions of the relevant libraries you are using:-->
  * Operating system: Fedora 27
  * Matplotlib version:  2.2.3
  * Matplotlib backend (`print(matplotlib.get_backend())`): agg
  * Python version:  3.6.5
  * Jupyter version (if applicable):
  * Other libraries:

Hints from issue discussion:
Your example is nt quite complete, so maybe I'm doing something wrong, but for 

```python

from matplotlib import pyplot as plt
import datetime

n, x = plt.hist([datetime.datetime(2018,1,1),  datetime.datetime(2018, 2, 1),
                 datetime.datetime(2018,3, 1)])
```

on 2.1.2 I get 
```
Traceback (most recent call last):
  File "testHist.py", line 5, in <module>
    datetime.datetime(2018,3, 1)])
ValueError: too many values to unpack (expected 2)
```

So I don't think it worked on 2.1.2 either.  
Thanks for the fast feedback!
Arghs, forgot to import the datetime in the example (updated issue now).  
The value error ist the result of plt.hist() returning 3 instead of 2 variables, namely **n**, **bins** and **patches**.

Code variant with assigning output to variables:
``` python
from matplotlib import pyplot as plt
from datetime import datetime
n, x, p = plt.hist([datetime(2018,1,1),  datetime(2018, 2, 1),  datetime(2018,3, 1)])
print(n)  
```

Output in 2.12 is:
`[1. 0. 0. 0. 0. 1. 0. 0. 0. 1.]`

Output in 2.2.3 is:
`[array([1., 0., 0., 0., 0., 0., 0., 0., 0., 0.]), array([0., 0., 0., 0., 0., 1., 0., 0., 0., 0.]), array([0., 0., 0., 0., 0., 0., 0., 0., 0., 1.])]`

 

@jklymak  have i been able to clarify your questions?  Greetings!
This bisects to c02a84d95c2497215b73ae14967969d422bec229 "Correctly convert units for a stacked histogram" @dstansby #9654

Obviously this works for floats, so the issue is that your data is not floats.  I guess this used to work before, but whether or not it really should have is debatable.  What should 
```
plt.hist(['a', 'b', 'c'])
```
return? It looks like the reason datetime worked at all is that it has a `toordinal` method.

Commit message: FIX: allow reshape 2-D to return a bare 1-d list

Patch to review:
diff --git a/lib/matplotlib/cbook/__init__.py b/lib/matplotlib/cbook/__init__.py
index 2c5661253873..1d73f8445dc8 100644
--- a/lib/matplotlib/cbook/__init__.py
+++ b/lib/matplotlib/cbook/__init__.py
@@ -1397,8 +1397,11 @@ def _reshape_2D(X, name):
         # 1D array of scalars: directly return it.
         return [X]
     elif X.ndim in [1, 2]:
-        # 2D array, or 1D array of iterables: flatten them first.
-        return [np.reshape(x, -1) for x in X]
+        if hasattr(X[0], '__len__'):
+            # 2D array, or 1D array of iterables: flatten them first.
+            return [np.reshape(x, -1) for x in X]
+        else:
+            return [X]
     else:
         raise ValueError("{} must have 2 or fewer dimensions".format(name))
 


Code review comments:
diff_hunk: @@ -1397,8 +1397,11 @@ def _reshape_2D(X, name):
         # 1D array of scalars: directly return it.
         return [X]
     elif X.ndim in [1, 2]:
-        # 2D array, or 1D array of iterables: flatten them first.
-        return [np.reshape(x, -1) for x in X]
+        if hasattr(X[0], '__len__'):
path: lib/matplotlib/cbook/__init__.py
text: @user1:
Or just replace the `X.dtype.type != np.object_` check above by `not hasattr(X[0], "__iter__")`/`not isinstance(X[0], collections.abc.Iterable)`?  That seems to match what the comments intended too.  (`__iter__` or `__len__`, I don't really care.)