diff options
Diffstat (limited to 'numpy/lib')
-rw-r--r-- | numpy/lib/arraysetops.py | 10 | ||||
-rw-r--r-- | numpy/lib/format.py | 45 | ||||
-rw-r--r-- | numpy/lib/function_base.py | 120 | ||||
-rw-r--r-- | numpy/lib/npyio.py | 8 | ||||
-rw-r--r-- | numpy/lib/tests/data/python3.npy | bin | 0 -> 96 bytes | |||
-rw-r--r-- | numpy/lib/tests/data/win64python2.npy | bin | 0 -> 96 bytes | |||
-rw-r--r-- | numpy/lib/tests/test_format.py | 10 | ||||
-rw-r--r-- | numpy/lib/tests/test_function_base.py | 38 | ||||
-rw-r--r-- | numpy/lib/tests/test_io.py | 11 | ||||
-rw-r--r-- | numpy/lib/tests/test_nanfunctions.py | 16 | ||||
-rw-r--r-- | numpy/lib/utils.py | 158 |
11 files changed, 270 insertions, 146 deletions
diff --git a/numpy/lib/arraysetops.py b/numpy/lib/arraysetops.py index 5c3b504de..d3b6119f4 100644 --- a/numpy/lib/arraysetops.py +++ b/numpy/lib/arraysetops.py @@ -241,6 +241,11 @@ def intersect1d(ar1, ar2, assume_unique=False): >>> np.intersect1d([1, 3, 4, 3], [3, 1, 2, 1]) array([1, 3]) + To intersect more than two arrays, use functools.reduce: + + >>> from functools import reduce + >>> reduce(np.intersect1d, ([1, 3, 4, 3], [3, 1, 2, 1], [6, 3, 4, 2])) + array([3]) """ if not assume_unique: # Might be faster than unique( intersect1d( ar1, ar2 ) )? @@ -421,6 +426,11 @@ def union1d(ar1, ar2): >>> np.union1d([-1, 0, 1], [-2, 0, 2]) array([-2, -1, 0, 1, 2]) + To find the union of more than two arrays, use functools.reduce: + + >>> from functools import reduce + >>> reduce(np.union1d, ([1, 3, 4, 3], [3, 1, 2, 1], [6, 3, 4, 2])) + array([1, 2, 3, 4, 6]) """ return unique(np.concatenate((ar1, ar2))) diff --git a/numpy/lib/format.py b/numpy/lib/format.py index 98743b6ad..b93f86ca3 100644 --- a/numpy/lib/format.py +++ b/numpy/lib/format.py @@ -141,7 +141,7 @@ import sys import io import warnings from numpy.lib.utils import safe_eval -from numpy.compat import asbytes, isfileobj, long, basestring +from numpy.compat import asbytes, asstr, isfileobj, long, basestring if sys.version_info[0] >= 3: import pickle @@ -298,7 +298,8 @@ def _write_array_header(fp, d, version=None): # can take advantage of our premature optimization. current_header_len = MAGIC_LEN + 2 + len(header) + 1 # 1 for the newline topad = 16 - (current_header_len % 16) - header = asbytes(header + ' '*topad + '\n') + header = header + ' '*topad + '\n' + header = asbytes(_filter_header(header)) if len(header) >= (256*256) and version == (1, 0): raise ValueError("header does not fit inside %s bytes required by the" @@ -410,6 +411,45 @@ def read_array_header_2_0(fp): """ _read_array_header(fp, version=(2, 0)) + +def _filter_header(s): + """Clean up 'L' in npz header ints. + + Cleans up the 'L' in strings representing integers. Needed to allow npz + headers produced in Python2 to be read in Python3. + + Parameters + ---------- + s : byte string + Npy file header. + + Returns + ------- + header : str + Cleaned up header. + + """ + import tokenize + if sys.version_info[0] >= 3: + from io import StringIO + else: + from StringIO import StringIO + + tokens = [] + last_token_was_number = False + for token in tokenize.generate_tokens(StringIO(asstr(s)).read): + token_type = token[0] + token_string = token[1] + if (last_token_was_number and + token_type == tokenize.NAME and + token_string == "L"): + continue + else: + tokens.append(token) + last_token_was_number = (token_type == tokenize.NUMBER) + return tokenize.untokenize(tokens) + + def _read_array_header(fp, version): """ see read_array_header_1_0 @@ -434,6 +474,7 @@ def _read_array_header(fp, version): # "shape" : tuple of int # "fortran_order" : bool # "descr" : dtype.descr + header = _filter_header(header) try: d = safe_eval(header) except SyntaxError as e: diff --git a/numpy/lib/function_base.py b/numpy/lib/function_base.py index 8b384bfaa..36ce94bad 100644 --- a/numpy/lib/function_base.py +++ b/numpy/lib/function_base.py @@ -515,8 +515,7 @@ def average(a, axis=None, weights=None, returned=False): scl = avg.dtype.type(a.size/avg.size) else: a = a + 0.0 - wgt = np.array(weights, dtype=a.dtype, copy=0) - + wgt = np.asarray(weights) # Sanity checks if a.shape != wgt.shape: if axis is None: @@ -533,7 +532,7 @@ def average(a, axis=None, weights=None, returned=False): # setup wgt to broadcast along axis wgt = np.array(wgt, copy=0, ndmin=a.ndim).swapaxes(-1, axis) - scl = wgt.sum(axis=axis) + scl = wgt.sum(axis=axis, dtype=np.result_type(a.dtype, wgt.dtype)) if (scl == 0.0).any(): raise ZeroDivisionError( "Weights sum to zero, can't be normalized") @@ -883,28 +882,33 @@ def copy(a, order='K'): # Basic operations -def gradient(f, *varargs): +def gradient(f, *varargs, **kwargs): """ Return the gradient of an N-dimensional array. - + The gradient is computed using second order accurate central differences - in the interior and second order accurate one-sides (forward or backwards) - differences at the boundaries. The returned gradient hence has the same - shape as the input array. + in the interior and either first differences or second order accurate + one-sides (forward or backwards) differences at the boundaries. The + returned gradient hence has the same shape as the input array. Parameters ---------- f : array_like - An N-dimensional array containing samples of a scalar function. - `*varargs` : scalars - 0, 1, or N scalars specifying the sample distances in each direction, - that is: `dx`, `dy`, `dz`, ... The default distance is 1. + An N-dimensional array containing samples of a scalar function. + varargs : list of scalar, optional + N scalars specifying the sample distances for each dimension, + i.e. `dx`, `dy`, `dz`, ... Default distance: 1. + edge_order : {1, 2}, optional + Gradient is calculated using N\ :sup:`th` order accurate differences + at the boundaries. Default: 1. + + .. versionadded:: 1.9.1 Returns ------- gradient : ndarray - N arrays of the same shape as `f` giving the derivative of `f` with - respect to each dimension. + N arrays of the same shape as `f` giving the derivative of `f` with + respect to each dimension. Examples -------- @@ -916,15 +920,14 @@ def gradient(f, *varargs): >>> np.gradient(np.array([[1, 2, 6], [3, 4, 5]], dtype=np.float)) [array([[ 2., 2., -1.], - [ 2., 2., -1.]]), - array([[ 1. , 2.5, 4. ], - [ 1. , 1. , 1. ]])] + [ 2., 2., -1.]]), array([[ 1. , 2.5, 4. ], + [ 1. , 1. , 1. ]])] - >>> x = np.array([0,1,2,3,4]) - >>> dx = gradient(x) + >>> x = np.array([0, 1, 2, 3, 4]) + >>> dx = np.gradient(x) >>> y = x**2 - >>> gradient(y,dx) - array([0., 2., 4., 6., 8.]) + >>> np.gradient(y, dx, edge_order=2) + array([-0., 2., 4., 6., 8.]) """ f = np.asanyarray(f) N = len(f.shape) # number of dimensions @@ -939,6 +942,13 @@ def gradient(f, *varargs): raise SyntaxError( "invalid number of arguments") + edge_order = kwargs.pop('edge_order', 1) + if kwargs: + raise TypeError('"{}" are not valid keyword arguments.'.format( + '", "'.join(kwargs.keys()))) + if edge_order > 2: + raise ValueError("'edge_order' greater than 2 not supported") + # use central differences on interior and one-sided differences on the # endpoints. This preserves second order-accuracy over the full domain. @@ -978,7 +988,7 @@ def gradient(f, *varargs): "at least two elements are required.") # Numerical differentiation: 1st order edges, 2nd order interior - if y.shape[axis] == 2: + if y.shape[axis] == 2 or edge_order == 1: # Use first order differences for time data out = np.empty_like(y, dtype=otype) @@ -1026,7 +1036,8 @@ def gradient(f, *varargs): out[slice1] = (3.0*y[slice2] - 4.0*y[slice3] + y[slice4])/2.0 # divide by step size - outvals.append(out / dx[axis]) + out /= dx[axis] + outvals.append(out) # reset the slice object in this dimension to ":" slice1[axis] = slice(None) @@ -1102,7 +1113,7 @@ def diff(a, n=1, axis=-1): return a[slice1]-a[slice2] -def interp(x, xp, fp, left=None, right=None): +def interp(x, xp, fp, left=None, right=None, period=None): """ One-dimensional linear interpolation. @@ -1115,7 +1126,9 @@ def interp(x, xp, fp, left=None, right=None): The x-coordinates of the interpolated values. xp : 1-D sequence of floats - The x-coordinates of the data points, must be increasing. + The x-coordinates of the data points, must be increasing if argument + `period` is not specified. Otherwise, `xp` is internally sorted after + normalizing the periodic boundaries with ``xp = xp % period``. fp : 1-D sequence of floats The y-coordinates of the data points, same length as `xp`. @@ -1126,6 +1139,12 @@ def interp(x, xp, fp, left=None, right=None): right : float, optional Value to return for `x > xp[-1]`, default is `fp[-1]`. + period : None or float, optional + .. versionadded:: 1.10.0 + A period for the x-coordinates. This parameter allows the proper + interpolation of angular x-coordinates. Parameters `left` and `right` + are ignored if `period` is specified. + Returns ------- y : {float, ndarray} @@ -1135,6 +1154,8 @@ def interp(x, xp, fp, left=None, right=None): ------ ValueError If `xp` and `fp` have different length + If `xp` or `fp` are not 1-D sequences + If `period == 0` Notes ----- @@ -1144,7 +1165,6 @@ def interp(x, xp, fp, left=None, right=None): np.all(np.diff(xp) > 0) - Examples -------- >>> xp = [1, 2, 3] @@ -1170,13 +1190,51 @@ def interp(x, xp, fp, left=None, right=None): [<matplotlib.lines.Line2D object at 0x...>] >>> plt.show() + Interpolation with periodic x-coordinates: + + >>> x = [-180, -170, -185, 185, -10, -5, 0, 365] + >>> xp = [190, -190, 350, -350] + >>> fp = [5, 10, 3, 4] + >>> np.interp(x, xp, fp, period=360) + array([7.5, 5., 8.75, 6.25, 3., 3.25, 3.5, 3.75]) + """ - if isinstance(x, (float, int, number)): - return compiled_interp([x], xp, fp, left, right).item() - elif isinstance(x, np.ndarray) and x.ndim == 0: - return compiled_interp([x], xp, fp, left, right).item() + if period is None: + if isinstance(x, (float, int, number)): + return compiled_interp([x], xp, fp, left, right).item() + elif isinstance(x, np.ndarray) and x.ndim == 0: + return compiled_interp([x], xp, fp, left, right).item() + else: + return compiled_interp(x, xp, fp, left, right) else: - return compiled_interp(x, xp, fp, left, right) + if period == 0: + raise ValueError("period must be a non-zero value") + period = abs(period) + left = None + right = None + return_array = True + if isinstance(x, (float, int, number)): + return_array = False + x = [x] + x = np.asarray(x, dtype=np.float64) + xp = np.asarray(xp, dtype=np.float64) + fp = np.asarray(fp, dtype=np.float64) + if xp.ndim != 1 or fp.ndim != 1: + raise ValueError("Data points must be 1-D sequences") + if xp.shape[0] != fp.shape[0]: + raise ValueError("fp and xp are not of the same length") + # normalizing periodic boundaries + x = x % period + xp = xp % period + asort_xp = np.argsort(xp) + xp = xp[asort_xp] + fp = fp[asort_xp] + xp = np.concatenate((xp[-1:]-period, xp, xp[0:1]+period)) + fp = np.concatenate((fp[-1:], fp, fp[0:1])) + if return_array: + return compiled_interp(x, xp, fp, left, right) + else: + return compiled_interp(x, xp, fp, left, right).item() def angle(z, deg=0): diff --git a/numpy/lib/npyio.py b/numpy/lib/npyio.py index 641203f34..cbef1a6e2 100644 --- a/numpy/lib/npyio.py +++ b/numpy/lib/npyio.py @@ -122,6 +122,14 @@ class BagObj(object): return object.__getattribute__(self, '_obj')[key] except KeyError: raise AttributeError(key) + + def __dir__(self): + """ + Enables dir(bagobj) to list the files in an NpzFile. + + This also enables tab-completion in an interpreter or IPython. + """ + return object.__getattribute__(self, '_obj').keys() def zipfile_factory(*args, **kwargs): diff --git a/numpy/lib/tests/data/python3.npy b/numpy/lib/tests/data/python3.npy Binary files differnew file mode 100644 index 000000000..7c6997dd6 --- /dev/null +++ b/numpy/lib/tests/data/python3.npy diff --git a/numpy/lib/tests/data/win64python2.npy b/numpy/lib/tests/data/win64python2.npy Binary files differnew file mode 100644 index 000000000..d9bc36af7 --- /dev/null +++ b/numpy/lib/tests/data/win64python2.npy diff --git a/numpy/lib/tests/test_format.py b/numpy/lib/tests/test_format.py index c09386789..ee77386bc 100644 --- a/numpy/lib/tests/test_format.py +++ b/numpy/lib/tests/test_format.py @@ -524,6 +524,16 @@ def test_compressed_roundtrip(): assert_array_equal(arr, arr1) +def test_python2_python3_interoperability(): + if sys.version_info[0] >= 3: + fname = 'win64python2.npy' + else: + fname = 'python3.npy' + path = os.path.join(os.path.dirname(__file__), 'data', fname) + data = np.load(path) + assert_array_equal(data, np.ones(2)) + + def test_version_2_0(): f = BytesIO() # requires more than 2 byte for header diff --git a/numpy/lib/tests/test_function_base.py b/numpy/lib/tests/test_function_base.py index c800f8347..80faf85a6 100644 --- a/numpy/lib/tests/test_function_base.py +++ b/numpy/lib/tests/test_function_base.py @@ -124,6 +124,11 @@ class TestAverage(TestCase): assert_array_equal(average(y1, weights=w2, axis=1), desired) assert_equal(average(y1, weights=w2), 5.) + y3 = rand(5).astype(np.float32) + w3 = rand(5).astype(np.float64) + + assert_(np.average(y3, weights=w3).dtype == np.result_type(y3, w3)) + def test_returned(self): y = np.array([[1, 2, 3], [4, 5, 6]]) @@ -526,8 +531,18 @@ class TestGradient(TestCase): def test_masked(self): # Make sure that gradient supports subclasses like masked arrays - x = np.ma.array([[1, 1], [3, 4]]) - assert_equal(type(gradient(x)[0]), type(x)) + x = np.ma.array([[1, 1], [3, 4]], + mask=[[False, False], [False, False]]) + out = gradient(x)[0] + assert_equal(type(out), type(x)) + # And make sure that the output and input don't have aliased mask + # arrays + assert_(x.mask is not out.mask) + # Also check that edge_order=2 doesn't alter the original mask + x2 = np.ma.arange(5) + x2[2] = np.ma.masked + np.gradient(x2, edge_order=2) + assert_array_equal(x2.mask, [False, False, True, False, False]) def test_datetime64(self): # Make sure gradient() can handle special types like datetime64 @@ -536,7 +551,7 @@ class TestGradient(TestCase): '1910-10-12', '1910-12-12', '1912-12-12'], dtype='datetime64[D]') dx = np.array( - [-7, -3, 0, 31, 61, 396, 1066], + [-5, -3, 0, 31, 61, 396, 731], dtype='timedelta64[D]') assert_array_equal(gradient(x), dx) assert_(dx.dtype == np.dtype('timedelta64[D]')) @@ -547,7 +562,7 @@ class TestGradient(TestCase): [-5, -3, 10, 12, 61, 321, 300], dtype='timedelta64[D]') dx = np.array( - [-3, 7, 7, 25, 154, 119, -161], + [2, 7, 7, 25, 154, 119, -21], dtype='timedelta64[D]') assert_array_equal(gradient(x), dx) assert_(dx.dtype == np.dtype('timedelta64[D]')) @@ -561,7 +576,7 @@ class TestGradient(TestCase): dx = x[1] - x[0] y = 2 * x ** 3 + 4 * x ** 2 + 2 * x analytical = 6 * x ** 2 + 8 * x + 2 - num_error = np.abs((np.gradient(y, dx) / analytical) - 1) + num_error = np.abs((np.gradient(y, dx, edge_order=2) / analytical) - 1) assert_(np.all(num_error < 0.03) == True) @@ -1604,6 +1619,9 @@ class TestInterp(TestCase): def test_exceptions(self): assert_raises(ValueError, interp, 0, [], []) assert_raises(ValueError, interp, 0, [0], [1, 2]) + assert_raises(ValueError, interp, 0, [0, 1], [1, 2], period=0) + assert_raises(ValueError, interp, 0, [], [], period=360) + assert_raises(ValueError, interp, 0, [0], [1, 2], period=360) def test_basic(self): x = np.linspace(0, 1, 5) @@ -1644,6 +1662,16 @@ class TestInterp(TestCase): fp = np.sin(xp) assert_almost_equal(np.interp(np.pi, xp, fp), 0.0) + def test_period(self): + x = [-180, -170, -185, 185, -10, -5, 0, 365] + xp = [190, -190, 350, -350] + fp = [5, 10, 3, 4] + y = [7.5, 5., 8.75, 6.25, 3., 3.25, 3.5, 3.75] + assert_almost_equal(np.interp(x, xp, fp, period=360), y) + x = np.array(x, order='F').reshape(2, -1) + y = np.array(y, order='C').reshape(2, -1) + assert_almost_equal(np.interp(x, xp, fp, period=360), y) + def compare_results(res, desired): for i in range(len(desired)): diff --git a/numpy/lib/tests/test_io.py b/numpy/lib/tests/test_io.py index 4038d6a7f..68b2018cd 100644 --- a/numpy/lib/tests/test_io.py +++ b/numpy/lib/tests/test_io.py @@ -216,6 +216,17 @@ class TestSavezLoad(RoundtripTest, TestCase): l = np.load(c) assert_equal(a, l['file_a']) assert_equal(b, l['file_b']) + + def test_BagObj(self): + a = np.array([[1, 2], [3, 4]], float) + b = np.array([[1 + 2j, 2 + 7j], [3 - 6j, 4 + 12j]], complex) + c = BytesIO() + np.savez(c, file_a=a, file_b=b) + c.seek(0) + l = np.load(c) + assert_equal(sorted(dir(l.f)), ['file_a','file_b']) + assert_equal(a, l.f.file_a) + assert_equal(b, l.f.file_b) def test_savez_filename_clashes(self): # Test that issue #852 is fixed diff --git a/numpy/lib/tests/test_nanfunctions.py b/numpy/lib/tests/test_nanfunctions.py index 3da6b5149..35ae86c20 100644 --- a/numpy/lib/tests/test_nanfunctions.py +++ b/numpy/lib/tests/test_nanfunctions.py @@ -645,6 +645,22 @@ class TestNanFunctions_Median(TestCase): assert_raises(IndexError, np.nanmedian, d, axis=(0, 4)) assert_raises(ValueError, np.nanmedian, d, axis=(1, 1)) + def test_float_special(self): + with warnings.catch_warnings(record=True): + warnings.simplefilter('ignore', RuntimeWarning) + a = np.array([[np.inf, np.nan], [np.nan, np.nan]]) + assert_equal(np.nanmedian(a, axis=0), [np.inf, np.nan]) + assert_equal(np.nanmedian(a, axis=1), [np.inf, np.nan]) + assert_equal(np.nanmedian(a), np.inf) + + # minimum fill value check + a = np.array([[np.nan, np.nan, np.inf], [np.nan, np.nan, np.inf]]) + assert_equal(np.nanmedian(a, axis=1), np.inf) + + # no mask path + a = np.array([[np.inf, np.inf], [np.inf, np.inf]]) + assert_equal(np.nanmedian(a, axis=1), np.inf) + class TestNanFunctions_Percentile(TestCase): diff --git a/numpy/lib/utils.py b/numpy/lib/utils.py index df0052493..519d0e9b9 100644 --- a/numpy/lib/utils.py +++ b/numpy/lib/utils.py @@ -4,6 +4,7 @@ import os import sys import types import re +import warnings from numpy.core.numerictypes import issubclass_, issubsctype, issubdtype from numpy.core import ndarray, ufunc, asarray @@ -1002,111 +1003,70 @@ class SafeEval(object): This includes strings with lists, dicts and tuples using the abstract syntax tree created by ``compiler.parse``. - For an example of usage, see `safe_eval`. + .. deprecated:: 1.10.0 See Also -------- safe_eval """ + def __init__(self): + warnings.warn("SafeEval is deprecated in 1.10 and will be removed.", + DeprecationWarning) - if sys.version_info[0] < 3: - def visit(self, node, **kw): - cls = node.__class__ - meth = getattr(self, 'visit'+cls.__name__, self.default) - return meth(node, **kw) + def visit(self, node): + cls = node.__class__ + meth = getattr(self, 'visit' + cls.__name__, self.default) + return meth(node) - def default(self, node, **kw): - raise SyntaxError("Unsupported source construct: %s" - % node.__class__) + def default(self, node): + raise SyntaxError("Unsupported source construct: %s" + % node.__class__) - def visitExpression(self, node, **kw): - for child in node.getChildNodes(): - return self.visit(child, **kw) + def visitExpression(self, node): + return self.visit(node.body) - def visitConst(self, node, **kw): - return node.value + def visitNum(self, node): + return node.n - def visitDict(self, node,**kw): - return dict( - [(self.visit(k), self.visit(v)) for k, v in node.items] - ) - - def visitTuple(self, node, **kw): - return tuple([self.visit(i) for i in node.nodes]) - - def visitList(self, node, **kw): - return [self.visit(i) for i in node.nodes] - - def visitUnaryAdd(self, node, **kw): - return +self.visit(node.getChildNodes()[0]) - - def visitUnarySub(self, node, **kw): - return -self.visit(node.getChildNodes()[0]) - - def visitName(self, node, **kw): - if node.name == 'False': - return False - elif node.name == 'True': - return True - elif node.name == 'None': - return None - else: - raise SyntaxError("Unknown name: %s" % node.name) - else: - - def visit(self, node): - cls = node.__class__ - meth = getattr(self, 'visit' + cls.__name__, self.default) - return meth(node) - - def default(self, node): - raise SyntaxError("Unsupported source construct: %s" - % node.__class__) - - def visitExpression(self, node): - return self.visit(node.body) - - def visitNum(self, node): - return node.n + def visitStr(self, node): + return node.s - def visitStr(self, node): - return node.s + def visitBytes(self, node): + return node.s - def visitBytes(self, node): - return node.s + def visitDict(self, node,**kw): + return dict([(self.visit(k), self.visit(v)) + for k, v in zip(node.keys, node.values)]) - def visitDict(self, node,**kw): - return dict([(self.visit(k), self.visit(v)) - for k, v in zip(node.keys, node.values)]) + def visitTuple(self, node): + return tuple([self.visit(i) for i in node.elts]) - def visitTuple(self, node): - return tuple([self.visit(i) for i in node.elts]) + def visitList(self, node): + return [self.visit(i) for i in node.elts] - def visitList(self, node): - return [self.visit(i) for i in node.elts] + def visitUnaryOp(self, node): + import ast + if isinstance(node.op, ast.UAdd): + return +self.visit(node.operand) + elif isinstance(node.op, ast.USub): + return -self.visit(node.operand) + else: + raise SyntaxError("Unknown unary op: %r" % node.op) + + def visitName(self, node): + if node.id == 'False': + return False + elif node.id == 'True': + return True + elif node.id == 'None': + return None + else: + raise SyntaxError("Unknown name: %s" % node.id) - def visitUnaryOp(self, node): - import ast - if isinstance(node.op, ast.UAdd): - return +self.visit(node.operand) - elif isinstance(node.op, ast.USub): - return -self.visit(node.operand) - else: - raise SyntaxError("Unknown unary op: %r" % node.op) - - def visitName(self, node): - if node.id == 'False': - return False - elif node.id == 'True': - return True - elif node.id == 'None': - return None - else: - raise SyntaxError("Unknown name: %s" % node.id) + def visitNameConstant(self, node): + return node.value - def visitNameConstant(self, node): - return node.value def safe_eval(source): """ @@ -1151,26 +1111,8 @@ def safe_eval(source): SyntaxError: Unsupported source construct: compiler.ast.CallFunc """ - # Local imports to speed up numpy's import time. - import warnings - - with warnings.catch_warnings(): - # compiler package is deprecated for 3.x, which is already solved - # here - warnings.simplefilter('ignore', DeprecationWarning) - try: - import compiler - except ImportError: - import ast as compiler - - walker = SafeEval() - try: - ast = compiler.parse(source, mode="eval") - except SyntaxError: - raise - try: - return walker.visit(ast) - except SyntaxError: - raise + # Local import to speed up numpy's import time. + import ast + return ast.literal_eval(source) #----------------------------------------------------------------------------- |