We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Add "<<INCLUDE_ANSIBLE_MODULE_JSON_ARGS>>" replacer for non-Python modules.
In v2, the module-arguments file are no more passed to any modules, even if the style of the modules are `non_native_want_json` or `old`.
So, we have to embed `<<INCLUDE_ANSIBLE_MODULE_WINDOWS_ARGS>>` replacer in non-Python (nor PS1) modules to pass module-arguments.
It seems the name of the replacer is some kind of confusing, and adding the new replacer `<<INCLUDE_ANSIBLE_MODULE_JSON_ARGS>>`, the alias of `<<INCLUDE_ANSIBLE_MODULE_WINDOWS_ARGS>>`, would be helpful.


--- 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/executor/module_common.py`
Content:
```
1 # (c) 2013-2014, Michael DeHaan <michael.dehaan@gmail.com>
2 # (c) 2015 Toshio Kuratomi <tkuratomi@ansible.com>
3 #
4 # This file is part of Ansible
5 #
6 # Ansible is free software: you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation, either version 3 of the License, or
9 # (at your option) any later version.
10 #
11 # Ansible is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 # GNU General Public License for more details.
15 #
16 # You should have received a copy of the GNU General Public License
17 # along with Ansible.  If not, see <http://www.gnu.org/licenses/>.
18 
19 # Make coding more python3-ish
20 from __future__ import (absolute_import, division, print_function)
21 __metaclass__ = type
22 
23 # from python and deps
24 from six.moves import StringIO
25 import json
26 import os
27 import shlex
28 
29 # from Ansible
30 from ansible import __version__
31 from ansible import constants as C
32 from ansible.errors import AnsibleError
33 from ansible.parsing.utils.jsonify import jsonify
34 from ansible.utils.unicode import to_bytes
35 
36 REPLACER         = "#<<INCLUDE_ANSIBLE_MODULE_COMMON>>"
37 REPLACER_ARGS    = "\"<<INCLUDE_ANSIBLE_MODULE_ARGS>>\""
38 REPLACER_COMPLEX = "\"<<INCLUDE_ANSIBLE_MODULE_COMPLEX_ARGS>>\""
39 REPLACER_WINDOWS = "# POWERSHELL_COMMON"
40 REPLACER_WINARGS = "<<INCLUDE_ANSIBLE_MODULE_WINDOWS_ARGS>>"
41 REPLACER_VERSION = "\"<<ANSIBLE_VERSION>>\""
42 
43 # We could end up writing out parameters with unicode characters so we need to
44 # specify an encoding for the python source file
45 ENCODING_STRING = '# -*- coding: utf-8 -*-'
46 
47 # we've moved the module_common relative to the snippets, so fix the path
48 _SNIPPET_PATH = os.path.join(os.path.dirname(__file__), '..', 'module_utils')
49 
50 # ******************************************************************************
51 
52 def _slurp(path):
53     if not os.path.exists(path):
54         raise AnsibleError("imported module support code does not exist at %s" % path)
55     fd = open(path)
56     data = fd.read()
57     fd.close()
58     return data
59 
60 def _find_snippet_imports(module_data, module_path, strip_comments):
61     """
62     Given the source of the module, convert it to a Jinja2 template to insert
63     module code and return whether it's a new or old style module.
64     """
65 
66     module_style = 'old'
67     if REPLACER in module_data:
68         module_style = 'new'
69     elif REPLACER_WINDOWS in module_data:
70         module_style = 'new'
71     elif 'from ansible.module_utils.' in module_data:
72         module_style = 'new'
73     elif 'WANT_JSON' in module_data:
74         module_style = 'non_native_want_json'
75 
76     output = StringIO()
77     lines = module_data.split('\n')
78     snippet_names = []
79 
80     for line in lines:
81 
82         if REPLACER in line:
83             output.write(_slurp(os.path.join(_SNIPPET_PATH, "basic.py")))
84             snippet_names.append('basic')
85         if REPLACER_WINDOWS in line:
86             ps_data = _slurp(os.path.join(_SNIPPET_PATH, "powershell.ps1"))
87             output.write(ps_data)
88             snippet_names.append('powershell')
89         elif line.startswith('from ansible.module_utils.'):
90             tokens=line.split(".")
91             import_error = False
92             if len(tokens) != 3:
93                 import_error = True
94             if " import *" not in line:
95                 import_error = True
96             if import_error:
97                 raise AnsibleError("error importing module in %s, expecting format like 'from ansible.module_utils.basic import *'" % module_path)
98             snippet_name = tokens[2].split()[0]
99             snippet_names.append(snippet_name)
100             output.write(_slurp(os.path.join(_SNIPPET_PATH, snippet_name + ".py")))
101         else:
102             if strip_comments and line.startswith("#") or line == '':
103                 pass
104             output.write(line)
105             output.write("\n")
106 
107     if not module_path.endswith(".ps1"):
108         # Unixy modules
109         if len(snippet_names) > 0 and not 'basic' in snippet_names:
110             raise AnsibleError("missing required import in %s: from ansible.module_utils.basic import *" % module_path)
111     else:
112         # Windows modules
113         if len(snippet_names) > 0 and not 'powershell' in snippet_names:
114             raise AnsibleError("missing required import in %s: # POWERSHELL_COMMON" % module_path)
115 
116     return (output.getvalue(), module_style)
117 
118 # ******************************************************************************
119 
120 def modify_module(module_path, module_args, task_vars=dict(), strip_comments=False):
121     """
122     Used to insert chunks of code into modules before transfer rather than
123     doing regular python imports.  This allows for more efficient transfer in
124     a non-bootstrapping scenario by not moving extra files over the wire and
125     also takes care of embedding arguments in the transferred modules.
126 
127     This version is done in such a way that local imports can still be
128     used in the module code, so IDEs don't have to be aware of what is going on.
129 
130     Example:
131 
132     from ansible.module_utils.basic import *
133 
134        ... will result in the insertion of basic.py into the module
135        from the module_utils/ directory in the source tree.
136 
137     All modules are required to import at least basic, though there will also
138     be other snippets.
139 
140     For powershell, there's equivalent conventions like this:
141 
142     # POWERSHELL_COMMON
143 
144     which results in the inclusion of the common code from powershell.ps1
145 
146     """
147     ### TODO: Optimization ideas if this code is actually a source of slowness:
148     # * Fix comment stripping: Currently doesn't preserve shebangs and encoding info (but we unconditionally add encoding info)
149     # * Use pyminifier if installed
150     # * comment stripping/pyminifier needs to have config setting to turn it
151     #   off for debugging purposes (goes along with keep remote but should be
152     #   separate otherwise users wouldn't be able to get info on what the
153     #   minifier output)
154     # * Only split into lines and recombine into strings once
155     # * Cache the modified module?  If only the args are different and we do
156     #   that as the last step we could cache sll the work up to that point.
157 
158     with open(module_path) as f:
159 
160         # read in the module source
161         module_data = f.read()
162 
163         (module_data, module_style) = _find_snippet_imports(module_data, module_path, strip_comments)
164 
165         module_args_json = json.dumps(module_args)
166         encoded_args = repr(module_args_json.encode('utf-8'))
167 
168         # these strings should be part of the 'basic' snippet which is required to be included
169         module_data = module_data.replace(REPLACER_VERSION, repr(__version__))
170         module_data = module_data.replace(REPLACER_COMPLEX, encoded_args)
171         module_data = module_data.replace(REPLACER_WINARGS, module_args_json.encode('utf-8'))
172 
173         if module_style == 'new':
174             facility = C.DEFAULT_SYSLOG_FACILITY
175             if 'ansible_syslog_facility' in task_vars:
176                 facility = task_vars['ansible_syslog_facility']
177             module_data = module_data.replace('syslog.LOG_USER', "syslog.%s" % facility)
178 
179         lines = module_data.split(b"\n", 1)
180         shebang = None
181         if lines[0].startswith(b"#!"):
182             shebang = lines[0].strip()
183             args = shlex.split(str(shebang[2:]))
184             interpreter = args[0]
185             interpreter_config = 'ansible_%s_interpreter' % os.path.basename(interpreter)
186 
187             if interpreter_config in task_vars:
188                 interpreter = to_bytes(task_vars[interpreter_config], errors='strict')
189                 lines[0] = shebang = b"#!{0} {1}".format(interpreter, b" ".join(args[1:]))
190 
191             if interpreter.startswith('python'):
192                 lines.insert(1, ENCODING_STRING)
193         else:
194             # No shebang, assume a binary module?
195             pass
196 
197         module_data = b"\n".join(lines)
198 
199         return (module_data, module_style, shebang)
200 
201
```
--- 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()

```

diff --git a/lib/ansible/executor/module_common.py b/lib/ansible/executor/module_common.py
--- a/lib/ansible/executor/module_common.py
+++ b/lib/ansible/executor/module_common.py
@@ -33,12 +33,13 @@
 from ansible.parsing.utils.jsonify import jsonify
 from ansible.utils.unicode import to_bytes
 
-REPLACER         = "#<<INCLUDE_ANSIBLE_MODULE_COMMON>>"
-REPLACER_ARGS    = "\"<<INCLUDE_ANSIBLE_MODULE_ARGS>>\""
-REPLACER_COMPLEX = "\"<<INCLUDE_ANSIBLE_MODULE_COMPLEX_ARGS>>\""
-REPLACER_WINDOWS = "# POWERSHELL_COMMON"
-REPLACER_WINARGS = "<<INCLUDE_ANSIBLE_MODULE_WINDOWS_ARGS>>"
-REPLACER_VERSION = "\"<<ANSIBLE_VERSION>>\""
+REPLACER          = "#<<INCLUDE_ANSIBLE_MODULE_COMMON>>"
+REPLACER_ARGS     = "\"<<INCLUDE_ANSIBLE_MODULE_ARGS>>\""
+REPLACER_COMPLEX  = "\"<<INCLUDE_ANSIBLE_MODULE_COMPLEX_ARGS>>\""
+REPLACER_WINDOWS  = "# POWERSHELL_COMMON"
+REPLACER_WINARGS  = "<<INCLUDE_ANSIBLE_MODULE_WINDOWS_ARGS>>"
+REPLACER_JSONARGS = "<<INCLUDE_ANSIBLE_MODULE_JSON_ARGS>>"
+REPLACER_VERSION  = "\"<<ANSIBLE_VERSION>>\""
 
 # We could end up writing out parameters with unicode characters so we need to
 # specify an encoding for the python source file
@@ -68,6 +69,8 @@
         module_style = 'new'
     elif REPLACER_WINDOWS in module_data:
         module_style = 'new'
+    elif REPLACER_JSONARGS in module_data:
+        module_style = 'new'
     elif 'from ansible.module_utils.' in module_data:
         module_style = 'new'
     elif 'WANT_JSON' in module_data:
@@ -162,13 +165,14 @@
 
         (module_data, module_style) = _find_snippet_imports(module_data, module_path, strip_comments)
 
-        module_args_json = json.dumps(module_args)
-        encoded_args = repr(module_args_json.encode('utf-8'))
+        module_args_json = json.dumps(module_args).encode('utf-8')
+        python_repred_args = repr(module_args_json)
 
         # these strings should be part of the 'basic' snippet which is required to be included
         module_data = module_data.replace(REPLACER_VERSION, repr(__version__))
-        module_data = module_data.replace(REPLACER_COMPLEX, encoded_args)
-        module_data = module_data.replace(REPLACER_WINARGS, module_args_json.encode('utf-8'))
+        module_data = module_data.replace(REPLACER_COMPLEX, python_repred_args)
+        module_data = module_data.replace(REPLACER_WINARGS, module_args_json)
+        module_data = module_data.replace(REPLACER_JSONARGS, module_args_json)
 
         if module_style == 'new':
             facility = C.DEFAULT_SYSLOG_FACILITY

{"golden_diff": "diff --git a/lib/ansible/executor/module_common.py b/lib/ansible/executor/module_common.py\n--- a/lib/ansible/executor/module_common.py\n+++ b/lib/ansible/executor/module_common.py\n@@ -33,12 +33,13 @@\n from ansible.parsing.utils.jsonify import jsonify\n from ansible.utils.unicode import to_bytes\n \n-REPLACER         = \"#<<INCLUDE_ANSIBLE_MODULE_COMMON>>\"\n-REPLACER_ARGS    = \"\\\"<<INCLUDE_ANSIBLE_MODULE_ARGS>>\\\"\"\n-REPLACER_COMPLEX = \"\\\"<<INCLUDE_ANSIBLE_MODULE_COMPLEX_ARGS>>\\\"\"\n-REPLACER_WINDOWS = \"# POWERSHELL_COMMON\"\n-REPLACER_WINARGS = \"<<INCLUDE_ANSIBLE_MODULE_WINDOWS_ARGS>>\"\n-REPLACER_VERSION = \"\\\"<<ANSIBLE_VERSION>>\\\"\"\n+REPLACER          = \"#<<INCLUDE_ANSIBLE_MODULE_COMMON>>\"\n+REPLACER_ARGS     = \"\\\"<<INCLUDE_ANSIBLE_MODULE_ARGS>>\\\"\"\n+REPLACER_COMPLEX  = \"\\\"<<INCLUDE_ANSIBLE_MODULE_COMPLEX_ARGS>>\\\"\"\n+REPLACER_WINDOWS  = \"# POWERSHELL_COMMON\"\n+REPLACER_WINARGS  = \"<<INCLUDE_ANSIBLE_MODULE_WINDOWS_ARGS>>\"\n+REPLACER_JSONARGS = \"<<INCLUDE_ANSIBLE_MODULE_JSON_ARGS>>\"\n+REPLACER_VERSION  = \"\\\"<<ANSIBLE_VERSION>>\\\"\"\n \n # We could end up writing out parameters with unicode characters so we need to\n # specify an encoding for the python source file\n@@ -68,6 +69,8 @@\n         module_style = 'new'\n     elif REPLACER_WINDOWS in module_data:\n         module_style = 'new'\n+    elif REPLACER_JSONARGS in module_data:\n+        module_style = 'new'\n     elif 'from ansible.module_utils.' in module_data:\n         module_style = 'new'\n     elif 'WANT_JSON' in module_data:\n@@ -162,13 +165,14 @@\n \n         (module_data, module_style) = _find_snippet_imports(module_data, module_path, strip_comments)\n \n-        module_args_json = json.dumps(module_args)\n-        encoded_args = repr(module_args_json.encode('utf-8'))\n+        module_args_json = json.dumps(module_args).encode('utf-8')\n+        python_repred_args = repr(module_args_json)\n \n         # these strings should be part of the 'basic' snippet which is required to be included\n         module_data = module_data.replace(REPLACER_VERSION, repr(__version__))\n-        module_data = module_data.replace(REPLACER_COMPLEX, encoded_args)\n-        module_data = module_data.replace(REPLACER_WINARGS, module_args_json.encode('utf-8'))\n+        module_data = module_data.replace(REPLACER_COMPLEX, python_repred_args)\n+        module_data = module_data.replace(REPLACER_WINARGS, module_args_json)\n+        module_data = module_data.replace(REPLACER_JSONARGS, module_args_json)\n \n         if module_style == 'new':\n             facility = C.DEFAULT_SYSLOG_FACILITY\n", "issue": "Add \"<<INCLUDE_ANSIBLE_MODULE_JSON_ARGS>>\" replacer for non-Python modules.\nIn v2, the module-arguments file are no more passed to any modules, even if the style of the modules are `non_native_want_json` or `old`.\nSo, we have to embed `<<INCLUDE_ANSIBLE_MODULE_WINDOWS_ARGS>>` replacer in non-Python (nor PS1) modules to pass module-arguments.\nIt seems the name of the replacer is some kind of confusing, and adding the new replacer `<<INCLUDE_ANSIBLE_MODULE_JSON_ARGS>>`, the alias of `<<INCLUDE_ANSIBLE_MODULE_WINDOWS_ARGS>>`, would be helpful.\n\n", "before_files": [{"content": "# (c) 2013-2014, Michael DeHaan <michael.dehaan@gmail.com>\n# (c) 2015 Toshio Kuratomi <tkuratomi@ansible.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/>.\n\n# Make coding more python3-ish\nfrom __future__ import (absolute_import, division, print_function)\n__metaclass__ = type\n\n# from python and deps\nfrom six.moves import StringIO\nimport json\nimport os\nimport shlex\n\n# from Ansible\nfrom ansible import __version__\nfrom ansible import constants as C\nfrom ansible.errors import AnsibleError\nfrom ansible.parsing.utils.jsonify import jsonify\nfrom ansible.utils.unicode import to_bytes\n\nREPLACER         = \"#<<INCLUDE_ANSIBLE_MODULE_COMMON>>\"\nREPLACER_ARGS    = \"\\\"<<INCLUDE_ANSIBLE_MODULE_ARGS>>\\\"\"\nREPLACER_COMPLEX = \"\\\"<<INCLUDE_ANSIBLE_MODULE_COMPLEX_ARGS>>\\\"\"\nREPLACER_WINDOWS = \"# POWERSHELL_COMMON\"\nREPLACER_WINARGS = \"<<INCLUDE_ANSIBLE_MODULE_WINDOWS_ARGS>>\"\nREPLACER_VERSION = \"\\\"<<ANSIBLE_VERSION>>\\\"\"\n\n# We could end up writing out parameters with unicode characters so we need to\n# specify an encoding for the python source file\nENCODING_STRING = '# -*- coding: utf-8 -*-'\n\n# we've moved the module_common relative to the snippets, so fix the path\n_SNIPPET_PATH = os.path.join(os.path.dirname(__file__), '..', 'module_utils')\n\n# ******************************************************************************\n\ndef _slurp(path):\n    if not os.path.exists(path):\n        raise AnsibleError(\"imported module support code does not exist at %s\" % path)\n    fd = open(path)\n    data = fd.read()\n    fd.close()\n    return data\n\ndef _find_snippet_imports(module_data, module_path, strip_comments):\n    \"\"\"\n    Given the source of the module, convert it to a Jinja2 template to insert\n    module code and return whether it's a new or old style module.\n    \"\"\"\n\n    module_style = 'old'\n    if REPLACER in module_data:\n        module_style = 'new'\n    elif REPLACER_WINDOWS in module_data:\n        module_style = 'new'\n    elif 'from ansible.module_utils.' in module_data:\n        module_style = 'new'\n    elif 'WANT_JSON' in module_data:\n        module_style = 'non_native_want_json'\n\n    output = StringIO()\n    lines = module_data.split('\\n')\n    snippet_names = []\n\n    for line in lines:\n\n        if REPLACER in line:\n            output.write(_slurp(os.path.join(_SNIPPET_PATH, \"basic.py\")))\n            snippet_names.append('basic')\n        if REPLACER_WINDOWS in line:\n            ps_data = _slurp(os.path.join(_SNIPPET_PATH, \"powershell.ps1\"))\n            output.write(ps_data)\n            snippet_names.append('powershell')\n        elif line.startswith('from ansible.module_utils.'):\n            tokens=line.split(\".\")\n            import_error = False\n            if len(tokens) != 3:\n                import_error = True\n            if \" import *\" not in line:\n                import_error = True\n            if import_error:\n                raise AnsibleError(\"error importing module in %s, expecting format like 'from ansible.module_utils.basic import *'\" % module_path)\n            snippet_name = tokens[2].split()[0]\n            snippet_names.append(snippet_name)\n            output.write(_slurp(os.path.join(_SNIPPET_PATH, snippet_name + \".py\")))\n        else:\n            if strip_comments and line.startswith(\"#\") or line == '':\n                pass\n            output.write(line)\n            output.write(\"\\n\")\n\n    if not module_path.endswith(\".ps1\"):\n        # Unixy modules\n        if len(snippet_names) > 0 and not 'basic' in snippet_names:\n            raise AnsibleError(\"missing required import in %s: from ansible.module_utils.basic import *\" % module_path)\n    else:\n        # Windows modules\n        if len(snippet_names) > 0 and not 'powershell' in snippet_names:\n            raise AnsibleError(\"missing required import in %s: # POWERSHELL_COMMON\" % module_path)\n\n    return (output.getvalue(), module_style)\n\n# ******************************************************************************\n\ndef modify_module(module_path, module_args, task_vars=dict(), strip_comments=False):\n    \"\"\"\n    Used to insert chunks of code into modules before transfer rather than\n    doing regular python imports.  This allows for more efficient transfer in\n    a non-bootstrapping scenario by not moving extra files over the wire and\n    also takes care of embedding arguments in the transferred modules.\n\n    This version is done in such a way that local imports can still be\n    used in the module code, so IDEs don't have to be aware of what is going on.\n\n    Example:\n\n    from ansible.module_utils.basic import *\n\n       ... will result in the insertion of basic.py into the module\n       from the module_utils/ directory in the source tree.\n\n    All modules are required to import at least basic, though there will also\n    be other snippets.\n\n    For powershell, there's equivalent conventions like this:\n\n    # POWERSHELL_COMMON\n\n    which results in the inclusion of the common code from powershell.ps1\n\n    \"\"\"\n    ### TODO: Optimization ideas if this code is actually a source of slowness:\n    # * Fix comment stripping: Currently doesn't preserve shebangs and encoding info (but we unconditionally add encoding info)\n    # * Use pyminifier if installed\n    # * comment stripping/pyminifier needs to have config setting to turn it\n    #   off for debugging purposes (goes along with keep remote but should be\n    #   separate otherwise users wouldn't be able to get info on what the\n    #   minifier output)\n    # * Only split into lines and recombine into strings once\n    # * Cache the modified module?  If only the args are different and we do\n    #   that as the last step we could cache sll the work up to that point.\n\n    with open(module_path) as f:\n\n        # read in the module source\n        module_data = f.read()\n\n        (module_data, module_style) = _find_snippet_imports(module_data, module_path, strip_comments)\n\n        module_args_json = json.dumps(module_args)\n        encoded_args = repr(module_args_json.encode('utf-8'))\n\n        # these strings should be part of the 'basic' snippet which is required to be included\n        module_data = module_data.replace(REPLACER_VERSION, repr(__version__))\n        module_data = module_data.replace(REPLACER_COMPLEX, encoded_args)\n        module_data = module_data.replace(REPLACER_WINARGS, module_args_json.encode('utf-8'))\n\n        if module_style == 'new':\n            facility = C.DEFAULT_SYSLOG_FACILITY\n            if 'ansible_syslog_facility' in task_vars:\n                facility = task_vars['ansible_syslog_facility']\n            module_data = module_data.replace('syslog.LOG_USER', \"syslog.%s\" % facility)\n\n        lines = module_data.split(b\"\\n\", 1)\n        shebang = None\n        if lines[0].startswith(b\"#!\"):\n            shebang = lines[0].strip()\n            args = shlex.split(str(shebang[2:]))\n            interpreter = args[0]\n            interpreter_config = 'ansible_%s_interpreter' % os.path.basename(interpreter)\n\n            if interpreter_config in task_vars:\n                interpreter = to_bytes(task_vars[interpreter_config], errors='strict')\n                lines[0] = shebang = b\"#!{0} {1}\".format(interpreter, b\" \".join(args[1:]))\n\n            if interpreter.startswith('python'):\n                lines.insert(1, ENCODING_STRING)\n        else:\n            # No shebang, assume a binary module?\n            pass\n\n        module_data = b\"\\n\".join(lines)\n\n        return (module_data, module_style, shebang)\n\n", "path": "lib/ansible/executor/module_common.py"}], "after_files": [{"content": "# (c) 2013-2014, Michael DeHaan <michael.dehaan@gmail.com>\n# (c) 2015 Toshio Kuratomi <tkuratomi@ansible.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/>.\n\n# Make coding more python3-ish\nfrom __future__ import (absolute_import, division, print_function)\n__metaclass__ = type\n\n# from python and deps\nfrom six.moves import StringIO\nimport json\nimport os\nimport shlex\n\n# from Ansible\nfrom ansible import __version__\nfrom ansible import constants as C\nfrom ansible.errors import AnsibleError\nfrom ansible.parsing.utils.jsonify import jsonify\nfrom ansible.utils.unicode import to_bytes\n\nREPLACER          = \"#<<INCLUDE_ANSIBLE_MODULE_COMMON>>\"\nREPLACER_ARGS     = \"\\\"<<INCLUDE_ANSIBLE_MODULE_ARGS>>\\\"\"\nREPLACER_COMPLEX  = \"\\\"<<INCLUDE_ANSIBLE_MODULE_COMPLEX_ARGS>>\\\"\"\nREPLACER_WINDOWS  = \"# POWERSHELL_COMMON\"\nREPLACER_WINARGS  = \"<<INCLUDE_ANSIBLE_MODULE_WINDOWS_ARGS>>\"\nREPLACER_JSONARGS = \"<<INCLUDE_ANSIBLE_MODULE_JSON_ARGS>>\"\nREPLACER_VERSION  = \"\\\"<<ANSIBLE_VERSION>>\\\"\"\n\n# We could end up writing out parameters with unicode characters so we need to\n# specify an encoding for the python source file\nENCODING_STRING = '# -*- coding: utf-8 -*-'\n\n# we've moved the module_common relative to the snippets, so fix the path\n_SNIPPET_PATH = os.path.join(os.path.dirname(__file__), '..', 'module_utils')\n\n# ******************************************************************************\n\ndef _slurp(path):\n    if not os.path.exists(path):\n        raise AnsibleError(\"imported module support code does not exist at %s\" % path)\n    fd = open(path)\n    data = fd.read()\n    fd.close()\n    return data\n\ndef _find_snippet_imports(module_data, module_path, strip_comments):\n    \"\"\"\n    Given the source of the module, convert it to a Jinja2 template to insert\n    module code and return whether it's a new or old style module.\n    \"\"\"\n\n    module_style = 'old'\n    if REPLACER in module_data:\n        module_style = 'new'\n    elif REPLACER_WINDOWS in module_data:\n        module_style = 'new'\n    elif REPLACER_JSONARGS in module_data:\n        module_style = 'new'\n    elif 'from ansible.module_utils.' in module_data:\n        module_style = 'new'\n    elif 'WANT_JSON' in module_data:\n        module_style = 'non_native_want_json'\n\n    output = StringIO()\n    lines = module_data.split('\\n')\n    snippet_names = []\n\n    for line in lines:\n\n        if REPLACER in line:\n            output.write(_slurp(os.path.join(_SNIPPET_PATH, \"basic.py\")))\n            snippet_names.append('basic')\n        if REPLACER_WINDOWS in line:\n            ps_data = _slurp(os.path.join(_SNIPPET_PATH, \"powershell.ps1\"))\n            output.write(ps_data)\n            snippet_names.append('powershell')\n        elif line.startswith('from ansible.module_utils.'):\n            tokens=line.split(\".\")\n            import_error = False\n            if len(tokens) != 3:\n                import_error = True\n            if \" import *\" not in line:\n                import_error = True\n            if import_error:\n                raise AnsibleError(\"error importing module in %s, expecting format like 'from ansible.module_utils.basic import *'\" % module_path)\n            snippet_name = tokens[2].split()[0]\n            snippet_names.append(snippet_name)\n            output.write(_slurp(os.path.join(_SNIPPET_PATH, snippet_name + \".py\")))\n        else:\n            if strip_comments and line.startswith(\"#\") or line == '':\n                pass\n            output.write(line)\n            output.write(\"\\n\")\n\n    if not module_path.endswith(\".ps1\"):\n        # Unixy modules\n        if len(snippet_names) > 0 and not 'basic' in snippet_names:\n            raise AnsibleError(\"missing required import in %s: from ansible.module_utils.basic import *\" % module_path)\n    else:\n        # Windows modules\n        if len(snippet_names) > 0 and not 'powershell' in snippet_names:\n            raise AnsibleError(\"missing required import in %s: # POWERSHELL_COMMON\" % module_path)\n\n    return (output.getvalue(), module_style)\n\n# ******************************************************************************\n\ndef modify_module(module_path, module_args, task_vars=dict(), strip_comments=False):\n    \"\"\"\n    Used to insert chunks of code into modules before transfer rather than\n    doing regular python imports.  This allows for more efficient transfer in\n    a non-bootstrapping scenario by not moving extra files over the wire and\n    also takes care of embedding arguments in the transferred modules.\n\n    This version is done in such a way that local imports can still be\n    used in the module code, so IDEs don't have to be aware of what is going on.\n\n    Example:\n\n    from ansible.module_utils.basic import *\n\n       ... will result in the insertion of basic.py into the module\n       from the module_utils/ directory in the source tree.\n\n    All modules are required to import at least basic, though there will also\n    be other snippets.\n\n    For powershell, there's equivalent conventions like this:\n\n    # POWERSHELL_COMMON\n\n    which results in the inclusion of the common code from powershell.ps1\n\n    \"\"\"\n    ### TODO: Optimization ideas if this code is actually a source of slowness:\n    # * Fix comment stripping: Currently doesn't preserve shebangs and encoding info (but we unconditionally add encoding info)\n    # * Use pyminifier if installed\n    # * comment stripping/pyminifier needs to have config setting to turn it\n    #   off for debugging purposes (goes along with keep remote but should be\n    #   separate otherwise users wouldn't be able to get info on what the\n    #   minifier output)\n    # * Only split into lines and recombine into strings once\n    # * Cache the modified module?  If only the args are different and we do\n    #   that as the last step we could cache sll the work up to that point.\n\n    with open(module_path) as f:\n\n        # read in the module source\n        module_data = f.read()\n\n        (module_data, module_style) = _find_snippet_imports(module_data, module_path, strip_comments)\n\n        module_args_json = json.dumps(module_args).encode('utf-8')\n        python_repred_args = repr(module_args_json)\n\n        # these strings should be part of the 'basic' snippet which is required to be included\n        module_data = module_data.replace(REPLACER_VERSION, repr(__version__))\n        module_data = module_data.replace(REPLACER_COMPLEX, python_repred_args)\n        module_data = module_data.replace(REPLACER_WINARGS, module_args_json)\n        module_data = module_data.replace(REPLACER_JSONARGS, module_args_json)\n\n        if module_style == 'new':\n            facility = C.DEFAULT_SYSLOG_FACILITY\n            if 'ansible_syslog_facility' in task_vars:\n                facility = task_vars['ansible_syslog_facility']\n            module_data = module_data.replace('syslog.LOG_USER', \"syslog.%s\" % facility)\n\n        lines = module_data.split(b\"\\n\", 1)\n        shebang = None\n        if lines[0].startswith(b\"#!\"):\n            shebang = lines[0].strip()\n            args = shlex.split(str(shebang[2:]))\n            interpreter = args[0]\n            interpreter_config = 'ansible_%s_interpreter' % os.path.basename(interpreter)\n\n            if interpreter_config in task_vars:\n                interpreter = to_bytes(task_vars[interpreter_config], errors='strict')\n                lines[0] = shebang = b\"#!{0} {1}\".format(interpreter, b\" \".join(args[1:]))\n\n            if interpreter.startswith('python'):\n                lines.insert(1, ENCODING_STRING)\n        else:\n            # No shebang, assume a binary module?\n            pass\n\n        module_data = b\"\\n\".join(lines)\n\n        return (module_data, module_style, shebang)\n\n", "path": "lib/ansible/executor/module_common.py"}]}