prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  safe_eval() warning for variables containing curly braces and Jinja2 expressions
  ##### ISSUE TYPE
  - Bug Report
  ##### COMPONENT NAME
  
  `template/safe_eval`
  ##### ANSIBLE VERSION
  
  ```
  ansible 2.2.0.0
    config file = 
    configured module search path = Default w/o overrides
  ```
  ##### SUMMARY
  
  There is a strange `safe_eval()` warning if one wants to template a string containing Jinja2 expressions and curly braces. Even escaping the curly braces like `{{ '{}' }}` does not help.
  ##### STEPS TO REPRODUCE
  
  ```
  - hosts: localhost
    vars:
      foo: "bar"
    tasks:
      - debug: msg="{}/{{ foo }}"
  ```
  ##### EXPECTED RESULTS
  
  Apart from the warning the expected results coincide with the actual ones.
  ##### ACTUAL RESULTS
  
  ```
  PLAY [localhost] ***************************************************************
  
  TASK [setup] *******************************************************************
  ok: [localhost]
  
  TASK [debug] *******************************************************************
   [WARNING]: Exception in safe_eval() on expr: {}/bar (name 'bar' is not defined)
  
  ok: [localhost] => {
      "msg": "{}/bar"
  }
  
  PLAY RECAP *********************************************************************
  localhost                  : ok=2    changed=0    unreachable=0    failed=0   
  ```
  
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `lib/ansible/template/safe_eval.py`
  Content:
  ```
  1 # (c) 2012, Michael DeHaan <michael.dehaan@gmail.com>
  2 #
  3 # This file is part of Ansible
  4 #
  5 # Ansible is free software: you can redistribute it and/or modify
  6 # it under the terms of the GNU General Public License as published by
  7 # the Free Software Foundation, either version 3 of the License, or
  8 # (at your option) any later version.
  9 #
  10 # Ansible is distributed in the hope that it will be useful,
  11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
  12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13 # GNU General Public License for more details.
  14 #
  15 # You should have received a copy of the GNU General Public License
  16 # along with Ansible.  If not, see <http://www.gnu.org/licenses/>.
  17 from __future__ import (absolute_import, division, print_function)
  18 __metaclass__ = type
  19 
  20 import ast
  21 import sys
  22 
  23 from ansible.compat.six import string_types
  24 from ansible.compat.six.moves import builtins
  25 
  26 from ansible import constants as C
  27 from ansible.plugins import filter_loader, test_loader
  28 
  29 try:
  30     from __main__ import display
  31 except ImportError:
  32     from ansible.utils.display import Display
  33     display = Display()
  34 
  35 def safe_eval(expr, locals={}, include_exceptions=False):
  36     '''
  37     This is intended for allowing things like:
  38     with_items: a_list_variable
  39 
  40     Where Jinja2 would return a string but we do not want to allow it to
  41     call functions (outside of Jinja2, where the env is constrained). If
  42     the input data to this function came from an untrusted (remote) source,
  43     it should first be run through _clean_data_struct() to ensure the data
  44     is further sanitized prior to evaluation.
  45 
  46     Based on:
  47     http://stackoverflow.com/questions/12523516/using-ast-and-whitelists-to-make-pythons-eval-safe
  48     '''
  49 
  50     # define certain JSON types
  51     # eg. JSON booleans are unknown to python eval()
  52     JSON_TYPES = {
  53         'false': False,
  54         'null': None,
  55         'true': True,
  56     }
  57 
  58     # this is the whitelist of AST nodes we are going to
  59     # allow in the evaluation. Any node type other than
  60     # those listed here will raise an exception in our custom
  61     # visitor class defined below.
  62     SAFE_NODES = set(
  63         (
  64             ast.Add,
  65             ast.BinOp,
  66             ast.Call,
  67             ast.Compare,
  68             ast.Dict,
  69             ast.Div,
  70             ast.Expression,
  71             ast.List,
  72             ast.Load,
  73             ast.Mult,
  74             ast.Num,
  75             ast.Name,
  76             ast.Str,
  77             ast.Sub,
  78             ast.Tuple,
  79             ast.UnaryOp,
  80         )
  81     )
  82 
  83     # AST node types were expanded after 2.6
  84     if sys.version_info[:2] >= (2, 7):
  85         SAFE_NODES.update(
  86             set(
  87                 (ast.Set,)
  88             )
  89         )
  90 
  91     # And in Python 3.4 too
  92     if sys.version_info[:2] >= (3, 4):
  93         SAFE_NODES.update(
  94             set(
  95                 (ast.NameConstant,)
  96             )
  97         )
  98 
  99     filter_list = []
  100     for filter in filter_loader.all():
  101         filter_list.extend(filter.filters().keys())
  102 
  103     test_list = []
  104     for test in test_loader.all():
  105         test_list.extend(test.tests().keys())
  106 
  107     CALL_WHITELIST = C.DEFAULT_CALLABLE_WHITELIST + filter_list + test_list
  108 
  109     class CleansingNodeVisitor(ast.NodeVisitor):
  110         def generic_visit(self, node, inside_call=False):
  111             if type(node) not in SAFE_NODES:
  112                 raise Exception("invalid expression (%s)" % expr)
  113             elif isinstance(node, ast.Call):
  114                 inside_call = True
  115             elif isinstance(node, ast.Name) and inside_call:
  116                 if hasattr(builtins, node.id) and node.id not in CALL_WHITELIST:
  117                     raise Exception("invalid function: %s" % node.id)
  118             # iterate over all child nodes
  119             for child_node in ast.iter_child_nodes(node):
  120                 self.generic_visit(child_node, inside_call)
  121 
  122     if not isinstance(expr, string_types):
  123         # already templated to a datastructure, perhaps?
  124         if include_exceptions:
  125             return (expr, None)
  126         return expr
  127 
  128     cnv = CleansingNodeVisitor()
  129     try:
  130         parsed_tree = ast.parse(expr, mode='eval')
  131         cnv.visit(parsed_tree)
  132         compiled = compile(parsed_tree, expr, 'eval')
  133         result = eval(compiled, JSON_TYPES, dict(locals))
  134 
  135         if include_exceptions:
  136             return (result, None)
  137         else:
  138             return result
  139     except SyntaxError as e:
  140         # special handling for syntax errors, we just return
  141         # the expression string back as-is to support late evaluation
  142         if include_exceptions:
  143             return (expr, None)
  144         return expr
  145     except Exception as e:
  146         display.warning('Exception in safe_eval() on expr: %s (%s)' % (expr, e))
  147         if include_exceptions:
  148             return (expr, e)
  149         return expr
  150
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/lib/ansible/template/safe_eval.py b/lib/ansible/template/safe_eval.py
  --- a/lib/ansible/template/safe_eval.py
  +++ b/lib/ansible/template/safe_eval.py
  @@ -26,12 +26,6 @@
   from ansible import constants as C
   from ansible.plugins import filter_loader, test_loader
   
  -try:
  -    from __main__ import display
  -except ImportError:
  -    from ansible.utils.display import Display
  -    display = Display()
  -
   def safe_eval(expr, locals={}, include_exceptions=False):
       '''
       This is intended for allowing things like:
  @@ -143,7 +137,6 @@
               return (expr, None)
           return expr
       except Exception as e:
  -        display.warning('Exception in safe_eval() on expr: %s (%s)' % (expr, e))
           if include_exceptions:
               return (expr, e)
           return expr
  
verification_info: {"golden_diff": "diff --git a/lib/ansible/template/safe_eval.py b/lib/ansible/template/safe_eval.py\n--- a/lib/ansible/template/safe_eval.py\n+++ b/lib/ansible/template/safe_eval.py\n@@ -26,12 +26,6 @@\n from ansible import constants as C\n from ansible.plugins import filter_loader, test_loader\n \n-try:\n-    from __main__ import display\n-except ImportError:\n-    from ansible.utils.display import Display\n-    display = Display()\n-\n def safe_eval(expr, locals={}, include_exceptions=False):\n     '''\n     This is intended for allowing things like:\n@@ -143,7 +137,6 @@\n             return (expr, None)\n         return expr\n     except Exception as e:\n-        display.warning('Exception in safe_eval() on expr: %s (%s)' % (expr, e))\n         if include_exceptions:\n             return (expr, e)\n         return expr\n", "issue": "safe_eval() warning for variables containing curly braces and Jinja2 expressions\n##### ISSUE TYPE\n- Bug Report\n##### COMPONENT NAME\n\n`template/safe_eval`\n##### ANSIBLE VERSION\n\n```\nansible 2.2.0.0\n  config file = \n  configured module search path = Default w/o overrides\n```\n##### SUMMARY\n\nThere is a strange `safe_eval()` warning if one wants to template a string containing Jinja2 expressions and curly braces. Even escaping the curly braces like `{{ '{}' }}` does not help.\n##### STEPS TO REPRODUCE\n\n```\n- hosts: localhost\n  vars:\n    foo: \"bar\"\n  tasks:\n    - debug: msg=\"{}/{{ foo }}\"\n```\n##### EXPECTED RESULTS\n\nApart from the warning the expected results coincide with the actual ones.\n##### ACTUAL RESULTS\n\n```\nPLAY [localhost] ***************************************************************\n\nTASK [setup] *******************************************************************\nok: [localhost]\n\nTASK [debug] *******************************************************************\n [WARNING]: Exception in safe_eval() on expr: {}/bar (name 'bar' is not defined)\n\nok: [localhost] => {\n    \"msg\": \"{}/bar\"\n}\n\nPLAY RECAP *********************************************************************\nlocalhost                  : ok=2    changed=0    unreachable=0    failed=0   \n```\n\n", "before_files": [{"content": "# (c) 2012, Michael DeHaan <michael.dehaan@gmail.com>\n#\n# This file is part of Ansible\n#\n# Ansible is free software: you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation, either version 3 of the License, or\n# (at your option) any later version.\n#\n# Ansible is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with Ansible.  If not, see <http://www.gnu.org/licenses/>.\nfrom __future__ import (absolute_import, division, print_function)\n__metaclass__ = type\n\nimport ast\nimport sys\n\nfrom ansible.compat.six import string_types\nfrom ansible.compat.six.moves import builtins\n\nfrom ansible import constants as C\nfrom ansible.plugins import filter_loader, test_loader\n\ntry:\n    from __main__ import display\nexcept ImportError:\n    from ansible.utils.display import Display\n    display = Display()\n\ndef safe_eval(expr, locals={}, include_exceptions=False):\n    '''\n    This is intended for allowing things like:\n    with_items: a_list_variable\n\n    Where Jinja2 would return a string but we do not want to allow it to\n    call functions (outside of Jinja2, where the env is constrained). If\n    the input data to this function came from an untrusted (remote) source,\n    it should first be run through _clean_data_struct() to ensure the data\n    is further sanitized prior to evaluation.\n\n    Based on:\n    http://stackoverflow.com/questions/12523516/using-ast-and-whitelists-to-make-pythons-eval-safe\n    '''\n\n    # define certain JSON types\n    # eg. JSON booleans are unknown to python eval()\n    JSON_TYPES = {\n        'false': False,\n        'null': None,\n        'true': True,\n    }\n\n    # this is the whitelist of AST nodes we are going to\n    # allow in the evaluation. Any node type other than\n    # those listed here will raise an exception in our custom\n    # visitor class defined below.\n    SAFE_NODES = set(\n        (\n            ast.Add,\n            ast.BinOp,\n            ast.Call,\n            ast.Compare,\n            ast.Dict,\n            ast.Div,\n            ast.Expression,\n            ast.List,\n            ast.Load,\n            ast.Mult,\n            ast.Num,\n            ast.Name,\n            ast.Str,\n            ast.Sub,\n            ast.Tuple,\n            ast.UnaryOp,\n        )\n    )\n\n    # AST node types were expanded after 2.6\n    if sys.version_info[:2] >= (2, 7):\n        SAFE_NODES.update(\n            set(\n                (ast.Set,)\n            )\n        )\n\n    # And in Python 3.4 too\n    if sys.version_info[:2] >= (3, 4):\n        SAFE_NODES.update(\n            set(\n                (ast.NameConstant,)\n            )\n        )\n\n    filter_list = []\n    for filter in filter_loader.all():\n        filter_list.extend(filter.filters().keys())\n\n    test_list = []\n    for test in test_loader.all():\n        test_list.extend(test.tests().keys())\n\n    CALL_WHITELIST = C.DEFAULT_CALLABLE_WHITELIST + filter_list + test_list\n\n    class CleansingNodeVisitor(ast.NodeVisitor):\n        def generic_visit(self, node, inside_call=False):\n            if type(node) not in SAFE_NODES:\n                raise Exception(\"invalid expression (%s)\" % expr)\n            elif isinstance(node, ast.Call):\n                inside_call = True\n            elif isinstance(node, ast.Name) and inside_call:\n                if hasattr(builtins, node.id) and node.id not in CALL_WHITELIST:\n                    raise Exception(\"invalid function: %s\" % node.id)\n            # iterate over all child nodes\n            for child_node in ast.iter_child_nodes(node):\n                self.generic_visit(child_node, inside_call)\n\n    if not isinstance(expr, string_types):\n        # already templated to a datastructure, perhaps?\n        if include_exceptions:\n            return (expr, None)\n        return expr\n\n    cnv = CleansingNodeVisitor()\n    try:\n        parsed_tree = ast.parse(expr, mode='eval')\n        cnv.visit(parsed_tree)\n        compiled = compile(parsed_tree, expr, 'eval')\n        result = eval(compiled, JSON_TYPES, dict(locals))\n\n        if include_exceptions:\n            return (result, None)\n        else:\n            return result\n    except SyntaxError as e:\n        # special handling for syntax errors, we just return\n        # the expression string back as-is to support late evaluation\n        if include_exceptions:\n            return (expr, None)\n        return expr\n    except Exception as e:\n        display.warning('Exception in safe_eval() on expr: %s (%s)' % (expr, e))\n        if include_exceptions:\n            return (expr, e)\n        return expr\n", "path": "lib/ansible/template/safe_eval.py"}], "after_files": [{"content": "# (c) 2012, Michael DeHaan <michael.dehaan@gmail.com>\n#\n# This file is part of Ansible\n#\n# Ansible is free software: you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation, either version 3 of the License, or\n# (at your option) any later version.\n#\n# Ansible is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with Ansible.  If not, see <http://www.gnu.org/licenses/>.\nfrom __future__ import (absolute_import, division, print_function)\n__metaclass__ = type\n\nimport ast\nimport sys\n\nfrom ansible.compat.six import string_types\nfrom ansible.compat.six.moves import builtins\n\nfrom ansible import constants as C\nfrom ansible.plugins import filter_loader, test_loader\n\ndef safe_eval(expr, locals={}, include_exceptions=False):\n    '''\n    This is intended for allowing things like:\n    with_items: a_list_variable\n\n    Where Jinja2 would return a string but we do not want to allow it to\n    call functions (outside of Jinja2, where the env is constrained). If\n    the input data to this function came from an untrusted (remote) source,\n    it should first be run through _clean_data_struct() to ensure the data\n    is further sanitized prior to evaluation.\n\n    Based on:\n    http://stackoverflow.com/questions/12523516/using-ast-and-whitelists-to-make-pythons-eval-safe\n    '''\n\n    # define certain JSON types\n    # eg. JSON booleans are unknown to python eval()\n    JSON_TYPES = {\n        'false': False,\n        'null': None,\n        'true': True,\n    }\n\n    # this is the whitelist of AST nodes we are going to\n    # allow in the evaluation. Any node type other than\n    # those listed here will raise an exception in our custom\n    # visitor class defined below.\n    SAFE_NODES = set(\n        (\n            ast.Add,\n            ast.BinOp,\n            ast.Call,\n            ast.Compare,\n            ast.Dict,\n            ast.Div,\n            ast.Expression,\n            ast.List,\n            ast.Load,\n            ast.Mult,\n            ast.Num,\n            ast.Name,\n            ast.Str,\n            ast.Sub,\n            ast.Tuple,\n            ast.UnaryOp,\n        )\n    )\n\n    # AST node types were expanded after 2.6\n    if sys.version_info[:2] >= (2, 7):\n        SAFE_NODES.update(\n            set(\n                (ast.Set,)\n            )\n        )\n\n    # And in Python 3.4 too\n    if sys.version_info[:2] >= (3, 4):\n        SAFE_NODES.update(\n            set(\n                (ast.NameConstant,)\n            )\n        )\n\n    filter_list = []\n    for filter in filter_loader.all():\n        filter_list.extend(filter.filters().keys())\n\n    test_list = []\n    for test in test_loader.all():\n        test_list.extend(test.tests().keys())\n\n    CALL_WHITELIST = C.DEFAULT_CALLABLE_WHITELIST + filter_list + test_list\n\n    class CleansingNodeVisitor(ast.NodeVisitor):\n        def generic_visit(self, node, inside_call=False):\n            if type(node) not in SAFE_NODES:\n                raise Exception(\"invalid expression (%s)\" % expr)\n            elif isinstance(node, ast.Call):\n                inside_call = True\n            elif isinstance(node, ast.Name) and inside_call:\n                if hasattr(builtins, node.id) and node.id not in CALL_WHITELIST:\n                    raise Exception(\"invalid function: %s\" % node.id)\n            # iterate over all child nodes\n            for child_node in ast.iter_child_nodes(node):\n                self.generic_visit(child_node, inside_call)\n\n    if not isinstance(expr, string_types):\n        # already templated to a datastructure, perhaps?\n        if include_exceptions:\n            return (expr, None)\n        return expr\n\n    cnv = CleansingNodeVisitor()\n    try:\n        parsed_tree = ast.parse(expr, mode='eval')\n        cnv.visit(parsed_tree)\n        compiled = compile(parsed_tree, expr, 'eval')\n        result = eval(compiled, JSON_TYPES, dict(locals))\n\n        if include_exceptions:\n            return (result, None)\n        else:\n            return result\n    except SyntaxError as e:\n        # special handling for syntax errors, we just return\n        # the expression string back as-is to support late evaluation\n        if include_exceptions:\n            return (expr, None)\n        return expr\n    except Exception as e:\n        if include_exceptions:\n            return (expr, e)\n        return expr\n", "path": "lib/ansible/template/safe_eval.py"}]}