Repository: numpy/numpy

Issue:
np.matrix('True False True') throws error
When trying to create a numpy matrix using the string syntax

`a = np.matrix('1 2; 3 4')`

but with booleans instead of integers

`np.matrix('True True False')`

I see this error 

```
>>> np.matrix('True True False')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/numpy/matrixlib/defmatrix.py", line 267, in __new__
    data = _convert_from_string(data)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/numpy/matrixlib/defmatrix.py", line 57, in _convert_from_string
    newrow.extend(map(_eval, temp))
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/numpy/matrixlib/defmatrix.py", line 26, in _eval
    return eval(str_)
  File "<string>", line 1, in <module>
NameError: name 'e' is not defined
```

I'm not sure but is this desired behavior?  

Thanks!


Discussion:

Resolving patch:
diff --git a/numpy/matrixlib/defmatrix.py b/numpy/matrixlib/defmatrix.py
--- a/numpy/matrixlib/defmatrix.py
+++ b/numpy/matrixlib/defmatrix.py
@@ -3,49 +3,15 @@
 __all__ = ['matrix', 'bmat', 'mat', 'asmatrix']
 
 import sys
+import ast
 import numpy.core.numeric as N
 from numpy.core.numeric import concatenate, isscalar, binary_repr, identity, asanyarray
 from numpy.core.numerictypes import issubdtype
 
-# make translation table
-_numchars = '0123456789.-+jeEL'
-
-if sys.version_info[0] >= 3:
-    class _NumCharTable:
-        def __getitem__(self, i):
-            if chr(i) in _numchars:
-                return chr(i)
-            else:
-                return None
-    _table = _NumCharTable()
-    def _eval(astr):
-        str_ = astr.translate(_table)
-        if not str_:
-            raise TypeError("Invalid data string supplied: " + astr)
-        else:
-            return eval(str_)
-
-else:
-    _table = [None]*256
-    for k in range(256):
-        _table[k] = chr(k)
-    _table = ''.join(_table)
-
-    _todelete = []
-    for k in _table:
-        if k not in _numchars:
-            _todelete.append(k)
-    _todelete = ''.join(_todelete)
-    del k
-
-    def _eval(astr):
-        str_ = astr.translate(_table, _todelete)
-        if not str_:
-            raise TypeError("Invalid data string supplied: " + astr)
-        else:
-            return eval(str_)
-
 def _convert_from_string(data):
+    for char in '[]':
+        data = data.replace(char, '')
+
     rows = data.split(';')
     newdata = []
     count = 0
@@ -54,7 +20,7 @@ def _convert_from_string(data):
         newrow = []
         for col in trow:
             temp = col.split()
-            newrow.extend(map(_eval, temp))
+            newrow.extend(map(ast.literal_eval, temp))
         if count == 0:
             Ncols = len(newrow)
         elif len(newrow) != Ncols:


Test patch:
diff --git a/numpy/matrixlib/tests/test_defmatrix.py b/numpy/matrixlib/tests/test_defmatrix.py
--- a/numpy/matrixlib/tests/test_defmatrix.py
+++ b/numpy/matrixlib/tests/test_defmatrix.py
@@ -35,8 +35,8 @@ def test_basic(self):
         assert_(mvec.shape == (1, 5))
 
     def test_exceptions(self):
-        # Check for TypeError when called with invalid string data.
-        assert_raises(TypeError, matrix, "invalid")
+        # Check for ValueError when called with invalid string data.
+        assert_raises(ValueError, matrix, "invalid")
 
     def test_bmat_nondefault_str(self):
         A = np.array([[1, 2], [3, 4]])
@@ -186,6 +186,11 @@ def test_repr(self):
         A = matrix([[1, 0], [0, 1]])
         assert_(repr(A) == "matrix([[1, 0],\n        [0, 1]])")
 
+    def test_make_bool_matrix_from_str(self):
+        A = matrix('True; True; False')
+        B = matrix([[True], [True], [False]])
+        assert_array_equal(A, B)
+
 class TestCasting(TestCase):
     def test_basic(self):
         A = np.arange(100).reshape(10, 10)