Repository: hgrecco/pint

Issue:
`Quantity.tolist()` method fails for zero-dimenional arrays
# Description
As I understand, `Quantity.tolist()` is meant to mirror numpy's `ndarray.tolist()` method; it does this successfully with arrays of at least dimensionality 1, but throws an exception for 0-dimensional arrays (i.e., scalar ndarrays).

*Pint version: 0.16.1*

# Example
Some setup code:
```pycon
>>> import pint
>>> ureg = pint.UnitRegistry()
>>> import numpy as np
```

When I run `tolist()` on a 1-dimensional ndarray, it works as expected:
```pycon
>>> a = np.arange(5)
>>> a.ndim
1
>>> a.tolist()
[0, 1, 2, 3, 4]
>>> (a * ureg.meter).tolist()
[<Quantity(0, 'meter')>, <Quantity(1, 'meter')>, <Quantity(2, 'meter')>, <Quantity(3, 'meter')>, <Quantity(4, 'meter')>]
```

But when I run `tolist()` on a 0-dimensional ndarray, it raises an exception:
```pycon
>>> a = np.array(5)
>>> a.ndim
0
>>> a.tolist()
5
>>> (a * ureg.meter).tolist()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\___\venv\lib\site-packages\pint\quantity.py", line 1886, in tolist
    for value in self._magnitude.tolist()
TypeError: 'int' object is not iterable
```

Discussion:

Patch:
diff --git a/CHANGES b/CHANGES
index b444cb3..e7b85d2 100644
--- a/CHANGES
+++ b/CHANGES
@@ -4,7 +4,7 @@ Pint Changelog
 0.17 (unreleased)
 -----------------
 
-- Nothing changed yet.
+- Fix tolist function with scalar ndarray. (Issue #1195)
 
 
 0.16.1 (2020-09-22)
diff --git a/pint/quantity.py b/pint/quantity.py
index 0395a65..6c59f7c 100644
--- a/pint/quantity.py
+++ b/pint/quantity.py
@@ -1879,12 +1879,22 @@ class Quantity(PrettyIPython, SharedRegistryObject):
 
     def tolist(self):
         units = self._units
-        return [
-            self.__class__(value, units).tolist()
-            if isinstance(value, list)
-            else self.__class__(value, units)
-            for value in self._magnitude.tolist()
-        ]
+
+        try:
+            values = self._magnitude.tolist()
+            if not isinstance(values, list):
+                return self.__class__(values, units)
+
+            return [
+                self.__class__(value, units).tolist()
+                if isinstance(value, list)
+                else self.__class__(value, units)
+                for value in self._magnitude.tolist()
+            ]
+        except AttributeError:
+            raise AttributeError(
+                f"Magnitude '{type(self._magnitude).__name__}' does not support tolist."
+            )
 
     # Measurement support
     def plus_minus(self, error, relative=False):


Test patch:
diff --git a/pint/testsuite/test_numpy.py b/pint/testsuite/test_numpy.py
index d9cee57..3be74f8 100644
--- a/pint/testsuite/test_numpy.py
+++ b/pint/testsuite/test_numpy.py
@@ -26,6 +26,10 @@ class TestNumpyMethods(QuantityTestCase):
     def q(self):
         return [[1, 2], [3, 4]] * self.ureg.m
 
+    @property
+    def q_scalar(self):
+        return np.array(5) * self.ureg.m
+
     @property
     def q_nan(self):
         return [[1, 2], [3, np.nan]] * self.ureg.m
@@ -497,6 +501,10 @@ class TestNumpyUnclassified(TestNumpyMethods):
             self.q.tolist(),
             [[1 * self.ureg.m, 2 * self.ureg.m], [3 * self.ureg.m, 4 * self.ureg.m]],
         )
+        self.assertEqual(self.q_scalar.tolist(), 5 * self.ureg.m)
+
+        with self.assertRaises(AttributeError):
+            (5 * self.ureg.m).tolist()
 
     def test_fill(self):
         tmp = self.q