We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
locale_gen fails when using Python 3
##### ISSUE TYPE
<!--- Pick one below and delete the rest: -->
 - Bug Report

##### COMPONENT NAME
`locale_gen`

##### ANSIBLE VERSION
```
ansible 2.2.0.0
```

##### CONFIGURATION
```ansible_python_interpreter: "python3"```

##### OS / ENVIRONMENT
Ubuntu Xenial 16.04

##### SUMMARY
When using Python 3, running a task with `locale_gen` fails.

##### STEPS TO REPRODUCE
1. Set a task using `locale_gen`; in my case it was:
    ```
    - name: ensure the required locale exists
      locale_gen:
        name: "{{ db_locale }}"
        state: present
    ```
2. Set `--ansible_python_interpreter=python3` when running the task. (Or `/usr/bin/python3` or whatever works on your system.)

##### EXPECTED RESULTS
```
TASK [postgresql : ensure the required locale exists] **************************
changed: [default] => {"changed": true, "msg": "OK", "name": "en_GB.UTF-8"}
```

##### ACTUAL RESULTS
```
TASK [postgresql : ensure the required locale exists] **************************
fatal: [default]: FAILED! => {"changed": false, "failed": true, "module_stderr": "Shared connection to 127.0.0.1 closed.\r\n", "module_stdout": "Traceback (most recent call last):\r\n  File \"/tmp/ansible_23qigrzr/ansible_module_locale_gen.py\", line 239, in <module>\r\n    main()\r\n  File \"/tmp/ansible_23qigrzr/ansible_module_locale_gen.py\", line 217, in main\r\n    if is_present(name):\r\n  File \"/tmp/ansible_23qigrzr/ansible_module_locale_gen.py\", line 96, in is_present\r\n    return any(fix_case(name) == fix_case(line) for line in output.splitlines())\r\n  File \"/tmp/ansible_23qigrzr/ansible_module_locale_gen.py\", line 96, in <genexpr>\r\n    return any(fix_case(name) == fix_case(line) for line in output.splitlines())\r\n  File \"/tmp/ansible_23qigrzr/ansible_module_locale_gen.py\", line 101, in fix_case\r\n    for s, r in LOCALE_NORMALIZATION.iteritems():\r\nAttributeError: 'dict' object has no attribute 'iteritems'\r\n", "msg": "MODULE FAILURE"}```



--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `system/locale_gen.py`
Content:
```
1 #!/usr/bin/python
2 # -*- coding: utf-8 -*-
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 DOCUMENTATION = '''
20 ---
21 module: locale_gen
22 short_description: Creates or removes locales.
23 description:
24      - Manages locales by editing /etc/locale.gen and invoking locale-gen.
25 version_added: "1.6"
26 author: "Augustus Kling (@AugustusKling)"
27 options:
28     name:
29         description:
30              - Name and encoding of the locale, such as "en_GB.UTF-8".
31         required: true
32         default: null
33         aliases: []
34     state:
35       description:
36            - Whether the locale shall be present.
37       required: false
38       choices: ["present", "absent"]
39       default: "present"
40 '''
41 
42 EXAMPLES = '''
43 # Ensure a locale exists.
44 - locale_gen: name=de_CH.UTF-8 state=present
45 '''
46 
47 import os
48 import os.path
49 from subprocess import Popen, PIPE, call
50 import re
51 
52 from ansible.module_utils.basic import *
53 from ansible.module_utils.pycompat24 import get_exception
54 
55 LOCALE_NORMALIZATION = {
56     ".utf8": ".UTF-8",
57     ".eucjp": ".EUC-JP",
58     ".iso885915": ".ISO-8859-15",
59     ".cp1251": ".CP1251",
60     ".koi8r": ".KOI8-R",
61     ".armscii8": ".ARMSCII-8",
62     ".euckr": ".EUC-KR",
63     ".gbk": ".GBK",
64     ".gb18030": ".GB18030",
65     ".euctw": ".EUC-TW",
66 }
67 
68 # ===========================================
69 # location module specific support methods.
70 #
71 
72 def is_available(name, ubuntuMode):
73     """Check if the given locale is available on the system. This is done by
74     checking either :
75     * if the locale is present in /etc/locales.gen
76     * or if the locale is present in /usr/share/i18n/SUPPORTED"""
77     if ubuntuMode:
78         __regexp = '^(?P<locale>\S+_\S+) (?P<charset>\S+)\s*$'
79         __locales_available = '/usr/share/i18n/SUPPORTED'
80     else:
81         __regexp = '^#{0,1}\s*(?P<locale>\S+_\S+) (?P<charset>\S+)\s*$'
82         __locales_available = '/etc/locale.gen'
83 
84     re_compiled = re.compile(__regexp)
85     fd = open(__locales_available, 'r')
86     for line in fd:
87         result = re_compiled.match(line)
88         if result and result.group('locale') == name:
89             return True
90     fd.close()
91     return False
92 
93 def is_present(name):
94     """Checks if the given locale is currently installed."""
95     output = Popen(["locale", "-a"], stdout=PIPE).communicate()[0]
96     return any(fix_case(name) == fix_case(line) for line in output.splitlines())
97 
98 def fix_case(name):
99     """locale -a might return the encoding in either lower or upper case.
100     Passing through this function makes them uniform for comparisons."""
101     for s, r in LOCALE_NORMALIZATION.iteritems():
102         name = name.replace(s, r)
103     return name
104 
105 def replace_line(existing_line, new_line):
106     """Replaces lines in /etc/locale.gen"""
107     try:
108         f = open("/etc/locale.gen", "r")
109         lines = [line.replace(existing_line, new_line) for line in f]
110     finally:
111         f.close()
112     try:
113         f = open("/etc/locale.gen", "w")
114         f.write("".join(lines))
115     finally:
116         f.close()
117 
118 def set_locale(name, enabled=True):
119     """ Sets the state of the locale. Defaults to enabled. """
120     search_string = '#{0,1}\s*%s (?P<charset>.+)' % name
121     if enabled:
122         new_string = '%s \g<charset>' % (name)
123     else:
124         new_string = '# %s \g<charset>' % (name)
125     try:
126         f = open("/etc/locale.gen", "r")
127         lines = [re.sub(search_string, new_string, line) for line in f]
128     finally:
129         f.close()
130     try:
131         f = open("/etc/locale.gen", "w")
132         f.write("".join(lines))
133     finally:
134         f.close()
135 
136 def apply_change(targetState, name):
137     """Create or remove locale.
138 
139     Keyword arguments:
140     targetState -- Desired state, either present or absent.
141     name -- Name including encoding such as de_CH.UTF-8.
142     """
143     if targetState=="present":
144         # Create locale.
145         set_locale(name, enabled=True)
146     else:
147         # Delete locale.
148         set_locale(name, enabled=False)
149     
150     localeGenExitValue = call("locale-gen")
151     if localeGenExitValue!=0:
152         raise EnvironmentError(localeGenExitValue, "locale.gen failed to execute, it returned "+str(localeGenExitValue))
153 
154 def apply_change_ubuntu(targetState, name):
155     """Create or remove locale.
156     
157     Keyword arguments:
158     targetState -- Desired state, either present or absent.
159     name -- Name including encoding such as de_CH.UTF-8.
160     """
161     if targetState=="present":
162         # Create locale.
163         # Ubuntu's patched locale-gen automatically adds the new locale to /var/lib/locales/supported.d/local
164         localeGenExitValue = call(["locale-gen", name])
165     else:
166         # Delete locale involves discarding the locale from /var/lib/locales/supported.d/local and regenerating all locales.
167         try:
168             f = open("/var/lib/locales/supported.d/local", "r")
169             content = f.readlines()
170         finally:
171             f.close()
172         try:
173             f = open("/var/lib/locales/supported.d/local", "w")
174             for line in content:
175                 locale, charset = line.split(' ')
176                 if locale != name:
177                     f.write(line)
178         finally:
179             f.close()
180         # Purge locales and regenerate.
181         # Please provide a patch if you know how to avoid regenerating the locales to keep!
182         localeGenExitValue = call(["locale-gen", "--purge"])
183     
184     if localeGenExitValue!=0:
185         raise EnvironmentError(localeGenExitValue, "locale.gen failed to execute, it returned "+str(localeGenExitValue))
186 
187 # ==============================================================
188 # main
189 
190 def main():
191 
192     module = AnsibleModule(
193         argument_spec = dict(
194             name = dict(required=True),
195             state = dict(choices=['present','absent'], default='present'),
196         ),
197         supports_check_mode=True
198     )
199 
200     name = module.params['name']
201     state = module.params['state']
202 
203     if not os.path.exists("/etc/locale.gen"):
204         if os.path.exists("/var/lib/locales/supported.d/"):
205             # Ubuntu created its own system to manage locales.
206             ubuntuMode = True
207         else:
208             module.fail_json(msg="/etc/locale.gen and /var/lib/locales/supported.d/local are missing. Is the package \"locales\" installed?")
209     else:
210         # We found the common way to manage locales.
211         ubuntuMode = False
212 
213     if not is_available(name, ubuntuMode):
214         module.fail_json(msg="The locales you've entered is not available "
215                              "on your system.")
216 
217     if is_present(name):
218         prev_state = "present"
219     else:
220         prev_state = "absent"
221     changed = (prev_state!=state)
222     
223     if module.check_mode:
224         module.exit_json(changed=changed)
225     else:
226         if changed:
227             try:
228                 if ubuntuMode==False:
229                     apply_change(state, name)
230                 else:
231                     apply_change_ubuntu(state, name)
232             except EnvironmentError:
233                 e = get_exception()
234                 module.fail_json(msg=e.strerror, exitValue=e.errno)
235 
236         module.exit_json(name=name, changed=changed, msg="OK")
237 
238 
239 main()
240
```
--- 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/system/locale_gen.py b/system/locale_gen.py
--- a/system/locale_gen.py
+++ b/system/locale_gen.py
@@ -98,7 +98,7 @@
 def fix_case(name):
     """locale -a might return the encoding in either lower or upper case.
     Passing through this function makes them uniform for comparisons."""
-    for s, r in LOCALE_NORMALIZATION.iteritems():
+    for s, r in LOCALE_NORMALIZATION.items():
         name = name.replace(s, r)
     return name

{"golden_diff": "diff --git a/system/locale_gen.py b/system/locale_gen.py\n--- a/system/locale_gen.py\n+++ b/system/locale_gen.py\n@@ -98,7 +98,7 @@\n def fix_case(name):\n     \"\"\"locale -a might return the encoding in either lower or upper case.\n     Passing through this function makes them uniform for comparisons.\"\"\"\n-    for s, r in LOCALE_NORMALIZATION.iteritems():\n+    for s, r in LOCALE_NORMALIZATION.items():\n         name = name.replace(s, r)\n     return name\n", "issue": "locale_gen fails when using Python 3\n##### ISSUE TYPE\r\n<!--- Pick one below and delete the rest: -->\r\n - Bug Report\r\n\r\n##### COMPONENT NAME\r\n`locale_gen`\r\n\r\n##### ANSIBLE VERSION\r\n```\r\nansible 2.2.0.0\r\n```\r\n\r\n##### CONFIGURATION\r\n```ansible_python_interpreter: \"python3\"```\r\n\r\n##### OS / ENVIRONMENT\r\nUbuntu Xenial 16.04\r\n\r\n##### SUMMARY\r\nWhen using Python 3, running a task with `locale_gen` fails.\r\n\r\n##### STEPS TO REPRODUCE\r\n1. Set a task using `locale_gen`; in my case it was:\r\n    ```\r\n    - name: ensure the required locale exists\r\n      locale_gen:\r\n        name: \"{{ db_locale }}\"\r\n        state: present\r\n    ```\r\n2. Set `--ansible_python_interpreter=python3` when running the task. (Or `/usr/bin/python3` or whatever works on your system.)\r\n\r\n##### EXPECTED RESULTS\r\n```\r\nTASK [postgresql : ensure the required locale exists] **************************\r\nchanged: [default] => {\"changed\": true, \"msg\": \"OK\", \"name\": \"en_GB.UTF-8\"}\r\n```\r\n\r\n##### ACTUAL RESULTS\r\n```\r\nTASK [postgresql : ensure the required locale exists] **************************\r\nfatal: [default]: FAILED! => {\"changed\": false, \"failed\": true, \"module_stderr\": \"Shared connection to 127.0.0.1 closed.\\r\\n\", \"module_stdout\": \"Traceback (most recent call last):\\r\\n  File \\\"/tmp/ansible_23qigrzr/ansible_module_locale_gen.py\\\", line 239, in <module>\\r\\n    main()\\r\\n  File \\\"/tmp/ansible_23qigrzr/ansible_module_locale_gen.py\\\", line 217, in main\\r\\n    if is_present(name):\\r\\n  File \\\"/tmp/ansible_23qigrzr/ansible_module_locale_gen.py\\\", line 96, in is_present\\r\\n    return any(fix_case(name) == fix_case(line) for line in output.splitlines())\\r\\n  File \\\"/tmp/ansible_23qigrzr/ansible_module_locale_gen.py\\\", line 96, in <genexpr>\\r\\n    return any(fix_case(name) == fix_case(line) for line in output.splitlines())\\r\\n  File \\\"/tmp/ansible_23qigrzr/ansible_module_locale_gen.py\\\", line 101, in fix_case\\r\\n    for s, r in LOCALE_NORMALIZATION.iteritems():\\r\\nAttributeError: 'dict' object has no attribute 'iteritems'\\r\\n\", \"msg\": \"MODULE FAILURE\"}```\r\n\r\n\n", "before_files": [{"content": "#!/usr/bin/python\n# -*- coding: utf-8 -*-\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\nDOCUMENTATION = '''\n---\nmodule: locale_gen\nshort_description: Creates or removes locales.\ndescription:\n     - Manages locales by editing /etc/locale.gen and invoking locale-gen.\nversion_added: \"1.6\"\nauthor: \"Augustus Kling (@AugustusKling)\"\noptions:\n    name:\n        description:\n             - Name and encoding of the locale, such as \"en_GB.UTF-8\".\n        required: true\n        default: null\n        aliases: []\n    state:\n      description:\n           - Whether the locale shall be present.\n      required: false\n      choices: [\"present\", \"absent\"]\n      default: \"present\"\n'''\n\nEXAMPLES = '''\n# Ensure a locale exists.\n- locale_gen: name=de_CH.UTF-8 state=present\n'''\n\nimport os\nimport os.path\nfrom subprocess import Popen, PIPE, call\nimport re\n\nfrom ansible.module_utils.basic import *\nfrom ansible.module_utils.pycompat24 import get_exception\n\nLOCALE_NORMALIZATION = {\n    \".utf8\": \".UTF-8\",\n    \".eucjp\": \".EUC-JP\",\n    \".iso885915\": \".ISO-8859-15\",\n    \".cp1251\": \".CP1251\",\n    \".koi8r\": \".KOI8-R\",\n    \".armscii8\": \".ARMSCII-8\",\n    \".euckr\": \".EUC-KR\",\n    \".gbk\": \".GBK\",\n    \".gb18030\": \".GB18030\",\n    \".euctw\": \".EUC-TW\",\n}\n\n# ===========================================\n# location module specific support methods.\n#\n\ndef is_available(name, ubuntuMode):\n    \"\"\"Check if the given locale is available on the system. This is done by\n    checking either :\n    * if the locale is present in /etc/locales.gen\n    * or if the locale is present in /usr/share/i18n/SUPPORTED\"\"\"\n    if ubuntuMode:\n        __regexp = '^(?P<locale>\\S+_\\S+) (?P<charset>\\S+)\\s*$'\n        __locales_available = '/usr/share/i18n/SUPPORTED'\n    else:\n        __regexp = '^#{0,1}\\s*(?P<locale>\\S+_\\S+) (?P<charset>\\S+)\\s*$'\n        __locales_available = '/etc/locale.gen'\n\n    re_compiled = re.compile(__regexp)\n    fd = open(__locales_available, 'r')\n    for line in fd:\n        result = re_compiled.match(line)\n        if result and result.group('locale') == name:\n            return True\n    fd.close()\n    return False\n\ndef is_present(name):\n    \"\"\"Checks if the given locale is currently installed.\"\"\"\n    output = Popen([\"locale\", \"-a\"], stdout=PIPE).communicate()[0]\n    return any(fix_case(name) == fix_case(line) for line in output.splitlines())\n\ndef fix_case(name):\n    \"\"\"locale -a might return the encoding in either lower or upper case.\n    Passing through this function makes them uniform for comparisons.\"\"\"\n    for s, r in LOCALE_NORMALIZATION.iteritems():\n        name = name.replace(s, r)\n    return name\n\ndef replace_line(existing_line, new_line):\n    \"\"\"Replaces lines in /etc/locale.gen\"\"\"\n    try:\n        f = open(\"/etc/locale.gen\", \"r\")\n        lines = [line.replace(existing_line, new_line) for line in f]\n    finally:\n        f.close()\n    try:\n        f = open(\"/etc/locale.gen\", \"w\")\n        f.write(\"\".join(lines))\n    finally:\n        f.close()\n\ndef set_locale(name, enabled=True):\n    \"\"\" Sets the state of the locale. Defaults to enabled. \"\"\"\n    search_string = '#{0,1}\\s*%s (?P<charset>.+)' % name\n    if enabled:\n        new_string = '%s \\g<charset>' % (name)\n    else:\n        new_string = '# %s \\g<charset>' % (name)\n    try:\n        f = open(\"/etc/locale.gen\", \"r\")\n        lines = [re.sub(search_string, new_string, line) for line in f]\n    finally:\n        f.close()\n    try:\n        f = open(\"/etc/locale.gen\", \"w\")\n        f.write(\"\".join(lines))\n    finally:\n        f.close()\n\ndef apply_change(targetState, name):\n    \"\"\"Create or remove locale.\n\n    Keyword arguments:\n    targetState -- Desired state, either present or absent.\n    name -- Name including encoding such as de_CH.UTF-8.\n    \"\"\"\n    if targetState==\"present\":\n        # Create locale.\n        set_locale(name, enabled=True)\n    else:\n        # Delete locale.\n        set_locale(name, enabled=False)\n    \n    localeGenExitValue = call(\"locale-gen\")\n    if localeGenExitValue!=0:\n        raise EnvironmentError(localeGenExitValue, \"locale.gen failed to execute, it returned \"+str(localeGenExitValue))\n\ndef apply_change_ubuntu(targetState, name):\n    \"\"\"Create or remove locale.\n    \n    Keyword arguments:\n    targetState -- Desired state, either present or absent.\n    name -- Name including encoding such as de_CH.UTF-8.\n    \"\"\"\n    if targetState==\"present\":\n        # Create locale.\n        # Ubuntu's patched locale-gen automatically adds the new locale to /var/lib/locales/supported.d/local\n        localeGenExitValue = call([\"locale-gen\", name])\n    else:\n        # Delete locale involves discarding the locale from /var/lib/locales/supported.d/local and regenerating all locales.\n        try:\n            f = open(\"/var/lib/locales/supported.d/local\", \"r\")\n            content = f.readlines()\n        finally:\n            f.close()\n        try:\n            f = open(\"/var/lib/locales/supported.d/local\", \"w\")\n            for line in content:\n                locale, charset = line.split(' ')\n                if locale != name:\n                    f.write(line)\n        finally:\n            f.close()\n        # Purge locales and regenerate.\n        # Please provide a patch if you know how to avoid regenerating the locales to keep!\n        localeGenExitValue = call([\"locale-gen\", \"--purge\"])\n    \n    if localeGenExitValue!=0:\n        raise EnvironmentError(localeGenExitValue, \"locale.gen failed to execute, it returned \"+str(localeGenExitValue))\n\n# ==============================================================\n# main\n\ndef main():\n\n    module = AnsibleModule(\n        argument_spec = dict(\n            name = dict(required=True),\n            state = dict(choices=['present','absent'], default='present'),\n        ),\n        supports_check_mode=True\n    )\n\n    name = module.params['name']\n    state = module.params['state']\n\n    if not os.path.exists(\"/etc/locale.gen\"):\n        if os.path.exists(\"/var/lib/locales/supported.d/\"):\n            # Ubuntu created its own system to manage locales.\n            ubuntuMode = True\n        else:\n            module.fail_json(msg=\"/etc/locale.gen and /var/lib/locales/supported.d/local are missing. Is the package \\\"locales\\\" installed?\")\n    else:\n        # We found the common way to manage locales.\n        ubuntuMode = False\n\n    if not is_available(name, ubuntuMode):\n        module.fail_json(msg=\"The locales you've entered is not available \"\n                             \"on your system.\")\n\n    if is_present(name):\n        prev_state = \"present\"\n    else:\n        prev_state = \"absent\"\n    changed = (prev_state!=state)\n    \n    if module.check_mode:\n        module.exit_json(changed=changed)\n    else:\n        if changed:\n            try:\n                if ubuntuMode==False:\n                    apply_change(state, name)\n                else:\n                    apply_change_ubuntu(state, name)\n            except EnvironmentError:\n                e = get_exception()\n                module.fail_json(msg=e.strerror, exitValue=e.errno)\n\n        module.exit_json(name=name, changed=changed, msg=\"OK\")\n\n\nmain()\n", "path": "system/locale_gen.py"}], "after_files": [{"content": "#!/usr/bin/python\n# -*- coding: utf-8 -*-\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\nDOCUMENTATION = '''\n---\nmodule: locale_gen\nshort_description: Creates or removes locales.\ndescription:\n     - Manages locales by editing /etc/locale.gen and invoking locale-gen.\nversion_added: \"1.6\"\nauthor: \"Augustus Kling (@AugustusKling)\"\noptions:\n    name:\n        description:\n             - Name and encoding of the locale, such as \"en_GB.UTF-8\".\n        required: true\n        default: null\n        aliases: []\n    state:\n      description:\n           - Whether the locale shall be present.\n      required: false\n      choices: [\"present\", \"absent\"]\n      default: \"present\"\n'''\n\nEXAMPLES = '''\n# Ensure a locale exists.\n- locale_gen: name=de_CH.UTF-8 state=present\n'''\n\nimport os\nimport os.path\nfrom subprocess import Popen, PIPE, call\nimport re\n\nfrom ansible.module_utils.basic import *\nfrom ansible.module_utils.pycompat24 import get_exception\n\nLOCALE_NORMALIZATION = {\n    \".utf8\": \".UTF-8\",\n    \".eucjp\": \".EUC-JP\",\n    \".iso885915\": \".ISO-8859-15\",\n    \".cp1251\": \".CP1251\",\n    \".koi8r\": \".KOI8-R\",\n    \".armscii8\": \".ARMSCII-8\",\n    \".euckr\": \".EUC-KR\",\n    \".gbk\": \".GBK\",\n    \".gb18030\": \".GB18030\",\n    \".euctw\": \".EUC-TW\",\n}\n\n# ===========================================\n# location module specific support methods.\n#\n\ndef is_available(name, ubuntuMode):\n    \"\"\"Check if the given locale is available on the system. This is done by\n    checking either :\n    * if the locale is present in /etc/locales.gen\n    * or if the locale is present in /usr/share/i18n/SUPPORTED\"\"\"\n    if ubuntuMode:\n        __regexp = '^(?P<locale>\\S+_\\S+) (?P<charset>\\S+)\\s*$'\n        __locales_available = '/usr/share/i18n/SUPPORTED'\n    else:\n        __regexp = '^#{0,1}\\s*(?P<locale>\\S+_\\S+) (?P<charset>\\S+)\\s*$'\n        __locales_available = '/etc/locale.gen'\n\n    re_compiled = re.compile(__regexp)\n    fd = open(__locales_available, 'r')\n    for line in fd:\n        result = re_compiled.match(line)\n        if result and result.group('locale') == name:\n            return True\n    fd.close()\n    return False\n\ndef is_present(name):\n    \"\"\"Checks if the given locale is currently installed.\"\"\"\n    output = Popen([\"locale\", \"-a\"], stdout=PIPE).communicate()[0]\n    return any(fix_case(name) == fix_case(line) for line in output.splitlines())\n\ndef fix_case(name):\n    \"\"\"locale -a might return the encoding in either lower or upper case.\n    Passing through this function makes them uniform for comparisons.\"\"\"\n    for s, r in LOCALE_NORMALIZATION.items():\n        name = name.replace(s, r)\n    return name\n\ndef replace_line(existing_line, new_line):\n    \"\"\"Replaces lines in /etc/locale.gen\"\"\"\n    try:\n        f = open(\"/etc/locale.gen\", \"r\")\n        lines = [line.replace(existing_line, new_line) for line in f]\n    finally:\n        f.close()\n    try:\n        f = open(\"/etc/locale.gen\", \"w\")\n        f.write(\"\".join(lines))\n    finally:\n        f.close()\n\ndef set_locale(name, enabled=True):\n    \"\"\" Sets the state of the locale. Defaults to enabled. \"\"\"\n    search_string = '#{0,1}\\s*%s (?P<charset>.+)' % name\n    if enabled:\n        new_string = '%s \\g<charset>' % (name)\n    else:\n        new_string = '# %s \\g<charset>' % (name)\n    try:\n        f = open(\"/etc/locale.gen\", \"r\")\n        lines = [re.sub(search_string, new_string, line) for line in f]\n    finally:\n        f.close()\n    try:\n        f = open(\"/etc/locale.gen\", \"w\")\n        f.write(\"\".join(lines))\n    finally:\n        f.close()\n\ndef apply_change(targetState, name):\n    \"\"\"Create or remove locale.\n\n    Keyword arguments:\n    targetState -- Desired state, either present or absent.\n    name -- Name including encoding such as de_CH.UTF-8.\n    \"\"\"\n    if targetState==\"present\":\n        # Create locale.\n        set_locale(name, enabled=True)\n    else:\n        # Delete locale.\n        set_locale(name, enabled=False)\n    \n    localeGenExitValue = call(\"locale-gen\")\n    if localeGenExitValue!=0:\n        raise EnvironmentError(localeGenExitValue, \"locale.gen failed to execute, it returned \"+str(localeGenExitValue))\n\ndef apply_change_ubuntu(targetState, name):\n    \"\"\"Create or remove locale.\n    \n    Keyword arguments:\n    targetState -- Desired state, either present or absent.\n    name -- Name including encoding such as de_CH.UTF-8.\n    \"\"\"\n    if targetState==\"present\":\n        # Create locale.\n        # Ubuntu's patched locale-gen automatically adds the new locale to /var/lib/locales/supported.d/local\n        localeGenExitValue = call([\"locale-gen\", name])\n    else:\n        # Delete locale involves discarding the locale from /var/lib/locales/supported.d/local and regenerating all locales.\n        try:\n            f = open(\"/var/lib/locales/supported.d/local\", \"r\")\n            content = f.readlines()\n        finally:\n            f.close()\n        try:\n            f = open(\"/var/lib/locales/supported.d/local\", \"w\")\n            for line in content:\n                locale, charset = line.split(' ')\n                if locale != name:\n                    f.write(line)\n        finally:\n            f.close()\n        # Purge locales and regenerate.\n        # Please provide a patch if you know how to avoid regenerating the locales to keep!\n        localeGenExitValue = call([\"locale-gen\", \"--purge\"])\n    \n    if localeGenExitValue!=0:\n        raise EnvironmentError(localeGenExitValue, \"locale.gen failed to execute, it returned \"+str(localeGenExitValue))\n\n# ==============================================================\n# main\n\ndef main():\n\n    module = AnsibleModule(\n        argument_spec = dict(\n            name = dict(required=True),\n            state = dict(choices=['present','absent'], default='present'),\n        ),\n        supports_check_mode=True\n    )\n\n    name = module.params['name']\n    state = module.params['state']\n\n    if not os.path.exists(\"/etc/locale.gen\"):\n        if os.path.exists(\"/var/lib/locales/supported.d/\"):\n            # Ubuntu created its own system to manage locales.\n            ubuntuMode = True\n        else:\n            module.fail_json(msg=\"/etc/locale.gen and /var/lib/locales/supported.d/local are missing. Is the package \\\"locales\\\" installed?\")\n    else:\n        # We found the common way to manage locales.\n        ubuntuMode = False\n\n    if not is_available(name, ubuntuMode):\n        module.fail_json(msg=\"The locales you've entered is not available \"\n                             \"on your system.\")\n\n    if is_present(name):\n        prev_state = \"present\"\n    else:\n        prev_state = \"absent\"\n    changed = (prev_state!=state)\n    \n    if module.check_mode:\n        module.exit_json(changed=changed)\n    else:\n        if changed:\n            try:\n                if ubuntuMode==False:\n                    apply_change(state, name)\n                else:\n                    apply_change_ubuntu(state, name)\n            except EnvironmentError:\n                e = get_exception()\n                module.fail_json(msg=e.strerror, exitValue=e.errno)\n\n        module.exit_json(name=name, changed=changed, msg=\"OK\")\n\n\nmain()\n", "path": "system/locale_gen.py"}]}