diff -r 1186d68715cc Doc/library/ast.rst --- a/Doc/library/ast.rst Wed Jul 04 19:33:45 2012 -0700 +++ b/Doc/library/ast.rst Thu Jul 05 21:45:37 2012 -0300 @@ -113,19 +113,27 @@ filename, mode, ast.PyCF_ONLY_AST)``. -.. function:: literal_eval(node_or_string) +.. function:: literal_eval(node_or_string, safe_names=None) Safely evaluate an expression node or a string containing a Python expression. The string or node provided may only consist of the following Python literal structures: strings, bytes, numbers, tuples, lists, dicts, - sets, booleans, and ``None``. - + sets, booleans, ``None`` and ``Ellipsis``. + A mapping may be provided as the second argument to allow identifiers to + be loaded. + This can be used for safely evaluating strings containing Python expressions from untrusted sources without the need to parse the values oneself. .. versionchanged:: 3.2 Now allows bytes and set literals. + .. versionchanged:: 3.3 + Allows Ellipsis literals. + + .. versionchanged:: 3.3 + Added the safe_names argument. + .. function:: get_docstring(node, clean=True) diff -r 1186d68715cc Lib/ast.py --- a/Lib/ast.py Wed Jul 04 19:33:45 2012 -0700 +++ b/Lib/ast.py Thu Jul 05 21:45:37 2012 -0300 @@ -35,14 +35,18 @@ return compile(source, filename, mode, PyCF_ONLY_AST) -def literal_eval(node_or_string): +def literal_eval(node_or_string, safe_names=None): """ Safely evaluate an expression node or a string containing a Python expression. The string or node provided may only consist of the following Python literal structures: strings, bytes, numbers, tuples, lists, dicts, - sets, booleans, and None. + sets, booleans, None and Ellipsis. + A mapping may be provided as the second argument to allow identifiers to + be loaded. """ - _safe_names = {'None': None, 'True': True, 'False': False} + _safe_names = {'None': None, 'True': True, 'False': False, 'Ellipsis': ...} + if safe_names: + _safe_names.update(safe_names) if isinstance(node_or_string, str): node_or_string = parse(node_or_string, mode='eval') if isinstance(node_or_string, Expression): @@ -52,6 +56,8 @@ return node.s elif isinstance(node, Num): return node.n + elif isinstance(node, Ellipsis): + return ... elif isinstance(node, Tuple): return tuple(map(_convert, node.elts)) elif isinstance(node, List): diff -r 1186d68715cc Lib/test/test_ast.py --- a/Lib/test/test_ast.py Wed Jul 04 19:33:45 2012 -0700 +++ b/Lib/test/test_ast.py Thu Jul 05 21:45:37 2012 -0300 @@ -488,6 +488,12 @@ self.assertEqual(ast.literal_eval('-6'), -6) self.assertEqual(ast.literal_eval('-6j+3'), 3-6j) self.assertEqual(ast.literal_eval('3.25'), 3.25) + self.assertEqual(ast.literal_eval('...'), Ellipsis) + self.assertEqual(ast.literal_eval('Ellipsis'), Ellipsis) + inf = float('inf') + self.assertEqual(ast.literal_eval('inf', {'inf': inf}), inf) + self.assertEqual(ast.literal_eval('[some, names]', + {'some': 1, 'names': 2}), [1, 2]) def test_literal_eval_issue4907(self): self.assertEqual(ast.literal_eval('2j'), 2j)