Python 3: make ansible.template.safe_eval() work

Two things changed in Python 3.4:

- 'basestring' is no longer defined, so use six.string_types

- True/False are now special AST node types (NamedConstant) rather than
  just names

(Good thing we had tests, or I wouldn't have noticed the 2nd thing!)

I found only one place where safe_eval() is called inside the ansible
codebase: in lib/template/__init__.py.  The call to safe_eval(result,
...) is protected by result.startswith('...'), which means result cannot
possibly be a byte string on Python 3 (or startswith() would raise, so
six.string_types (which excludes byte strings on Python 3) is fine here.
pull/12318/head
Marius Gedminas 9 years ago
parent 0c5bbe3c32
commit 2b73002044

@ -20,6 +20,7 @@ __metaclass__ = type
import ast import ast
import sys import sys
from six import string_types
from six.moves import builtins from six.moves import builtins
from ansible import constants as C from ansible import constants as C
@ -73,6 +74,14 @@ def safe_eval(expr, locals={}, include_exceptions=False):
) )
) )
# And in Python 3.4 too
if sys.version_info[:2] >= (3, 4):
SAFE_NODES.update(
set(
(ast.NameConstant,)
)
)
filter_list = [] filter_list = []
for filter in filter_loader.all(): for filter in filter_loader.all():
filter_list.extend(filter.filters().keys()) filter_list.extend(filter.filters().keys())
@ -96,7 +105,7 @@ def safe_eval(expr, locals={}, include_exceptions=False):
for child_node in ast.iter_child_nodes(node): for child_node in ast.iter_child_nodes(node):
self.generic_visit(child_node, inside_call) self.generic_visit(child_node, inside_call)
if not isinstance(expr, basestring): if not isinstance(expr, string_types):
# already templated to a datastructure, perhaps? # already templated to a datastructure, perhaps?
if include_exceptions: if include_exceptions:
return (expr, None) return (expr, None)

Loading…
Cancel
Save