We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
pam_limits - documentation is not updated 
`limit_type` choices are `hard`, `soft` in the [documentation](http://docs.ansible.com/ansible/pam_limits_module.html) but in the [code](https://github.com/ansible/ansible-modules-extras/blob/devel/system/pam_limits.py#L95) `-` is supported.

pam_limits - documentation is not updated 
`limit_type` choices are `hard`, `soft` in the [documentation](http://docs.ansible.com/ansible/pam_limits_module.html) but in the [code](https://github.com/ansible/ansible-modules-extras/blob/devel/system/pam_limits.py#L95) `-` is supported.


--- 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/pam_limits.py`
Content:
```
1 #!/usr/bin/python
2 # -*- coding: utf-8 -*-
3 
4 # (c) 2014, Sebastien Rohaut <sebastien.rohaut@gmail.com>
5 #
6 # This file is part of Ansible
7 #
8 # Ansible is free software: you can redistribute it and/or modify
9 # it under the terms of the GNU General Public License as published by
10 # the Free Software Foundation, either version 3 of the License, or
11 # (at your option) any later version.
12 #
13 # Ansible is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 # GNU General Public License for more details.
17 #
18 # You should have received a copy of the GNU General Public License
19 # along with Ansible.  If not, see <http://www.gnu.org/licenses/>.
20 
21 import os
22 import os.path
23 import shutil
24 import re
25 
26 DOCUMENTATION = '''
27 ---
28 module: pam_limits
29 version_added: "2.0"
30 short_description: Modify Linux PAM limits
31 description:
32      - The M(pam_limits) module modify PAM limits, default in /etc/security/limits.conf.
33        For the full documentation, see man limits.conf(5).
34 options:
35   domain:
36     description:
37       - A username, @groupname, wildcard, uid/gid range.
38     required: true
39   limit_type:
40     description:
41       - Limit type, see C(man limits) for an explanation
42     required: true
43     choices: [ "hard", "soft" ]
44   limit_item:
45     description:
46       - The limit to be set
47     required: true
48     choices: [ "core", "data", "fsize", "memlock", "nofile", "rss", "stack", "cpu", "nproc", "as", "maxlogins", "maxsyslogins", "priority", "locks", "sigpending", "msgqueue", "nice", "rtprio", "chroot" ]
49   value:
50     description:
51       - The value of the limit.
52     required: true
53   backup:
54     description:
55       - Create a backup file including the timestamp information so you can get
56         the original file back if you somehow clobbered it incorrectly.
57     required: false
58     choices: [ "yes", "no" ]
59     default: "no"
60   use_min:
61     description:
62       - If set to C(yes), the minimal value will be used or conserved.
63         If the specified value is inferior to the value in the file, file content is replaced with the new value,
64         else content is not modified.
65     required: false
66     choices: [ "yes", "no" ]
67     default: "no"
68   use_max:
69     description:
70       - If set to C(yes), the maximal value will be used or conserved.
71         If the specified value is superior to the value in the file, file content is replaced with the new value,
72         else content is not modified.
73     required: false
74     choices: [ "yes", "no" ]
75     default: "no"
76   dest:
77     description:
78       - Modify the limits.conf path.
79     required: false
80     default: "/etc/security/limits.conf"
81 '''
82 
83 EXAMPLES = '''
84 # Add or modify limits for the user joe
85 - pam_limits: domain=joe limit_type=soft limit_item=nofile value=64000
86 
87 # Add or modify limits for the user joe. Keep or set the maximal value
88 - pam_limits: domain=joe limit_type=soft limit_item=nofile value=1000000
89 '''
90 
91 def main():
92 
93     pam_items = [ 'core', 'data', 'fsize', 'memlock', 'nofile', 'rss', 'stack', 'cpu', 'nproc', 'as', 'maxlogins', 'maxsyslogins', 'priority', 'locks', 'sigpending', 'msgqueue', 'nice', 'rtprio', 'chroot' ]
94 
95     pam_types = [ 'soft', 'hard', '-' ]
96 
97     limits_conf = '/etc/security/limits.conf'
98 
99     module = AnsibleModule(
100         # not checking because of daisy chain to file module
101         argument_spec = dict(
102             domain            = dict(required=True, type='str'),
103             limit_type        = dict(required=True, type='str', choices=pam_types),
104             limit_item        = dict(required=True, type='str', choices=pam_items),
105             value             = dict(required=True, type='str'),
106             use_max           = dict(default=False, type='bool'),
107             use_min           = dict(default=False, type='bool'),
108             backup            = dict(default=False, type='bool'),
109             dest              = dict(default=limits_conf, type='str'),
110             comment           = dict(required=False, default='', type='str')
111         )
112     )
113 
114     domain      =       module.params['domain']
115     limit_type  =       module.params['limit_type']
116     limit_item  =       module.params['limit_item']
117     value       =       module.params['value']
118     use_max     =       module.params['use_max']
119     use_min     =       module.params['use_min']
120     backup      =       module.params['backup']
121     limits_conf =       module.params['dest']
122     new_comment =       module.params['comment']
123 
124     changed = False
125 
126     if os.path.isfile(limits_conf):
127         if not os.access(limits_conf, os.W_OK):
128             module.fail_json(msg="%s is not writable. Use sudo" % (limits_conf) )
129     else:
130         module.fail_json(msg="%s is not visible (check presence, access rights, use sudo)" % (limits_conf) )
131 
132     if use_max and use_min:
133         module.fail_json(msg="Cannot use use_min and use_max at the same time." )
134 
135     if not (value in ['unlimited', 'infinity', '-1'] or value.isdigit()):
136         module.fail_json(msg="Argument 'value' can be one of 'unlimited', 'infinity', '-1' or positive number. Refer to manual pages for more details.")
137 
138     # Backup
139     if backup:
140         backup_file = module.backup_local(limits_conf)
141 
142     space_pattern = re.compile(r'\s+')
143 
144     message = ''
145     f = open (limits_conf, 'r')
146     # Tempfile
147     nf = tempfile.NamedTemporaryFile(delete = False)
148 
149     found = False
150     new_value = value
151 
152     for line in f:
153 
154         if line.startswith('#'):
155             nf.write(line)
156             continue
157 
158         newline = re.sub(space_pattern, ' ', line).strip()
159         if not newline:
160             nf.write(line)
161             continue
162 
163         # Remove comment in line
164         newline = newline.split('#',1)[0]
165         try:
166             old_comment = line.split('#',1)[1]
167         except:
168             old_comment = ''
169 
170         newline = newline.rstrip()
171 
172         if not new_comment:
173             new_comment = old_comment
174 
175         if new_comment:
176             new_comment = "\t#"+new_comment
177 
178         line_fields = newline.split(' ')
179 
180         if len(line_fields) != 4:
181             nf.write(line)
182             continue
183 
184         line_domain     = line_fields[0]
185         line_type       = line_fields[1]
186         line_item       = line_fields[2]
187         actual_value    = line_fields[3]
188 
189         if not (actual_value in ['unlimited', 'infinity', '-1'] or actual_value.isdigit()):
190             module.fail_json(msg="Invalid configuration of '%s'. Current value of %s is unsupported." % (limits_conf, line_item))
191 
192         # Found the line
193         if line_domain == domain and line_type == limit_type and line_item == limit_item:
194             found = True
195             if value == actual_value:
196                 message = line
197                 nf.write(line)
198                 continue
199 
200             actual_value_unlimited = actual_value in ['unlimited', 'infinity', '-1']
201             value_unlimited = value in ['unlimited', 'infinity', '-1']
202 
203             if use_max:
204                 if value.isdigit() and actual_value.isdigit():
205                     new_value = max(int(value), int(actual_value))
206                 elif actual_value_unlimited:
207                     new_value = actual_value
208                 else:
209                     new_value = value
210 
211             if use_min:
212                 if value.isdigit() and actual_value.isdigit():
213                     new_value = min(int(value), int(actual_value))
214                 elif value_unlimited:
215                     new_value = actual_value
216                 else:
217                     new_value = value
218 
219             # Change line only if value has changed
220             if new_value != actual_value:
221                 changed = True
222                 new_limit = domain + "\t" + limit_type + "\t" + limit_item + "\t" + str(new_value) + new_comment + "\n"
223                 message = new_limit
224                 nf.write(new_limit)
225             else:
226                 message = line
227                 nf.write(line)
228         else:
229             nf.write(line)
230 
231     if not found:
232         changed = True
233         new_limit = domain + "\t" + limit_type + "\t" + limit_item + "\t" + str(new_value) + new_comment + "\n"
234         message = new_limit
235         nf.write(new_limit)
236 
237     f.close()
238     nf.close()
239 
240     # Copy tempfile to newfile
241     module.atomic_move(nf.name, f.name)
242 
243     res_args = dict(
244         changed = changed, msg = message
245     )
246 
247     if backup:
248         res_args['backup_file'] = backup_file
249 
250     module.exit_json(**res_args)
251 
252 
253 # import module snippets
254 from ansible.module_utils.basic import *
255 main()
256
```
--- 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/pam_limits.py b/system/pam_limits.py
--- a/system/pam_limits.py
+++ b/system/pam_limits.py
@@ -40,7 +40,7 @@
     description:
       - Limit type, see C(man limits) for an explanation
     required: true
-    choices: [ "hard", "soft" ]
+    choices: [ "hard", "soft", "-" ]
   limit_item:
     description:
       - The limit to be set

{"golden_diff": "diff --git a/system/pam_limits.py b/system/pam_limits.py\n--- a/system/pam_limits.py\n+++ b/system/pam_limits.py\n@@ -40,7 +40,7 @@\n     description:\n       - Limit type, see C(man limits) for an explanation\n     required: true\n-    choices: [ \"hard\", \"soft\" ]\n+    choices: [ \"hard\", \"soft\", \"-\" ]\n   limit_item:\n     description:\n       - The limit to be set\n", "issue": "pam_limits - documentation is not updated \n`limit_type` choices are `hard`, `soft` in the [documentation](http://docs.ansible.com/ansible/pam_limits_module.html) but in the [code](https://github.com/ansible/ansible-modules-extras/blob/devel/system/pam_limits.py#L95) `-` is supported.\n\npam_limits - documentation is not updated \n`limit_type` choices are `hard`, `soft` in the [documentation](http://docs.ansible.com/ansible/pam_limits_module.html) but in the [code](https://github.com/ansible/ansible-modules-extras/blob/devel/system/pam_limits.py#L95) `-` is supported.\n\n", "before_files": [{"content": "#!/usr/bin/python\n# -*- coding: utf-8 -*-\n\n# (c) 2014, Sebastien Rohaut <sebastien.rohaut@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/>.\n\nimport os\nimport os.path\nimport shutil\nimport re\n\nDOCUMENTATION = '''\n---\nmodule: pam_limits\nversion_added: \"2.0\"\nshort_description: Modify Linux PAM limits\ndescription:\n     - The M(pam_limits) module modify PAM limits, default in /etc/security/limits.conf.\n       For the full documentation, see man limits.conf(5).\noptions:\n  domain:\n    description:\n      - A username, @groupname, wildcard, uid/gid range.\n    required: true\n  limit_type:\n    description:\n      - Limit type, see C(man limits) for an explanation\n    required: true\n    choices: [ \"hard\", \"soft\" ]\n  limit_item:\n    description:\n      - The limit to be set\n    required: true\n    choices: [ \"core\", \"data\", \"fsize\", \"memlock\", \"nofile\", \"rss\", \"stack\", \"cpu\", \"nproc\", \"as\", \"maxlogins\", \"maxsyslogins\", \"priority\", \"locks\", \"sigpending\", \"msgqueue\", \"nice\", \"rtprio\", \"chroot\" ]\n  value:\n    description:\n      - The value of the limit.\n    required: true\n  backup:\n    description:\n      - Create a backup file including the timestamp information so you can get\n        the original file back if you somehow clobbered it incorrectly.\n    required: false\n    choices: [ \"yes\", \"no\" ]\n    default: \"no\"\n  use_min:\n    description:\n      - If set to C(yes), the minimal value will be used or conserved.\n        If the specified value is inferior to the value in the file, file content is replaced with the new value,\n        else content is not modified.\n    required: false\n    choices: [ \"yes\", \"no\" ]\n    default: \"no\"\n  use_max:\n    description:\n      - If set to C(yes), the maximal value will be used or conserved.\n        If the specified value is superior to the value in the file, file content is replaced with the new value,\n        else content is not modified.\n    required: false\n    choices: [ \"yes\", \"no\" ]\n    default: \"no\"\n  dest:\n    description:\n      - Modify the limits.conf path.\n    required: false\n    default: \"/etc/security/limits.conf\"\n'''\n\nEXAMPLES = '''\n# Add or modify limits for the user joe\n- pam_limits: domain=joe limit_type=soft limit_item=nofile value=64000\n\n# Add or modify limits for the user joe. Keep or set the maximal value\n- pam_limits: domain=joe limit_type=soft limit_item=nofile value=1000000\n'''\n\ndef main():\n\n    pam_items = [ 'core', 'data', 'fsize', 'memlock', 'nofile', 'rss', 'stack', 'cpu', 'nproc', 'as', 'maxlogins', 'maxsyslogins', 'priority', 'locks', 'sigpending', 'msgqueue', 'nice', 'rtprio', 'chroot' ]\n\n    pam_types = [ 'soft', 'hard', '-' ]\n\n    limits_conf = '/etc/security/limits.conf'\n\n    module = AnsibleModule(\n        # not checking because of daisy chain to file module\n        argument_spec = dict(\n            domain            = dict(required=True, type='str'),\n            limit_type        = dict(required=True, type='str', choices=pam_types),\n            limit_item        = dict(required=True, type='str', choices=pam_items),\n            value             = dict(required=True, type='str'),\n            use_max           = dict(default=False, type='bool'),\n            use_min           = dict(default=False, type='bool'),\n            backup            = dict(default=False, type='bool'),\n            dest              = dict(default=limits_conf, type='str'),\n            comment           = dict(required=False, default='', type='str')\n        )\n    )\n\n    domain      =       module.params['domain']\n    limit_type  =       module.params['limit_type']\n    limit_item  =       module.params['limit_item']\n    value       =       module.params['value']\n    use_max     =       module.params['use_max']\n    use_min     =       module.params['use_min']\n    backup      =       module.params['backup']\n    limits_conf =       module.params['dest']\n    new_comment =       module.params['comment']\n\n    changed = False\n\n    if os.path.isfile(limits_conf):\n        if not os.access(limits_conf, os.W_OK):\n            module.fail_json(msg=\"%s is not writable. Use sudo\" % (limits_conf) )\n    else:\n        module.fail_json(msg=\"%s is not visible (check presence, access rights, use sudo)\" % (limits_conf) )\n\n    if use_max and use_min:\n        module.fail_json(msg=\"Cannot use use_min and use_max at the same time.\" )\n\n    if not (value in ['unlimited', 'infinity', '-1'] or value.isdigit()):\n        module.fail_json(msg=\"Argument 'value' can be one of 'unlimited', 'infinity', '-1' or positive number. Refer to manual pages for more details.\")\n\n    # Backup\n    if backup:\n        backup_file = module.backup_local(limits_conf)\n\n    space_pattern = re.compile(r'\\s+')\n\n    message = ''\n    f = open (limits_conf, 'r')\n    # Tempfile\n    nf = tempfile.NamedTemporaryFile(delete = False)\n\n    found = False\n    new_value = value\n\n    for line in f:\n\n        if line.startswith('#'):\n            nf.write(line)\n            continue\n\n        newline = re.sub(space_pattern, ' ', line).strip()\n        if not newline:\n            nf.write(line)\n            continue\n\n        # Remove comment in line\n        newline = newline.split('#',1)[0]\n        try:\n            old_comment = line.split('#',1)[1]\n        except:\n            old_comment = ''\n\n        newline = newline.rstrip()\n\n        if not new_comment:\n            new_comment = old_comment\n\n        if new_comment:\n            new_comment = \"\\t#\"+new_comment\n\n        line_fields = newline.split(' ')\n\n        if len(line_fields) != 4:\n            nf.write(line)\n            continue\n\n        line_domain     = line_fields[0]\n        line_type       = line_fields[1]\n        line_item       = line_fields[2]\n        actual_value    = line_fields[3]\n\n        if not (actual_value in ['unlimited', 'infinity', '-1'] or actual_value.isdigit()):\n            module.fail_json(msg=\"Invalid configuration of '%s'. Current value of %s is unsupported.\" % (limits_conf, line_item))\n\n        # Found the line\n        if line_domain == domain and line_type == limit_type and line_item == limit_item:\n            found = True\n            if value == actual_value:\n                message = line\n                nf.write(line)\n                continue\n\n            actual_value_unlimited = actual_value in ['unlimited', 'infinity', '-1']\n            value_unlimited = value in ['unlimited', 'infinity', '-1']\n\n            if use_max:\n                if value.isdigit() and actual_value.isdigit():\n                    new_value = max(int(value), int(actual_value))\n                elif actual_value_unlimited:\n                    new_value = actual_value\n                else:\n                    new_value = value\n\n            if use_min:\n                if value.isdigit() and actual_value.isdigit():\n                    new_value = min(int(value), int(actual_value))\n                elif value_unlimited:\n                    new_value = actual_value\n                else:\n                    new_value = value\n\n            # Change line only if value has changed\n            if new_value != actual_value:\n                changed = True\n                new_limit = domain + \"\\t\" + limit_type + \"\\t\" + limit_item + \"\\t\" + str(new_value) + new_comment + \"\\n\"\n                message = new_limit\n                nf.write(new_limit)\n            else:\n                message = line\n                nf.write(line)\n        else:\n            nf.write(line)\n\n    if not found:\n        changed = True\n        new_limit = domain + \"\\t\" + limit_type + \"\\t\" + limit_item + \"\\t\" + str(new_value) + new_comment + \"\\n\"\n        message = new_limit\n        nf.write(new_limit)\n\n    f.close()\n    nf.close()\n\n    # Copy tempfile to newfile\n    module.atomic_move(nf.name, f.name)\n\n    res_args = dict(\n        changed = changed, msg = message\n    )\n\n    if backup:\n        res_args['backup_file'] = backup_file\n\n    module.exit_json(**res_args)\n\n\n# import module snippets\nfrom ansible.module_utils.basic import *\nmain()\n", "path": "system/pam_limits.py"}], "after_files": [{"content": "#!/usr/bin/python\n# -*- coding: utf-8 -*-\n\n# (c) 2014, Sebastien Rohaut <sebastien.rohaut@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/>.\n\nimport os\nimport os.path\nimport shutil\nimport re\n\nDOCUMENTATION = '''\n---\nmodule: pam_limits\nversion_added: \"2.0\"\nshort_description: Modify Linux PAM limits\ndescription:\n     - The M(pam_limits) module modify PAM limits, default in /etc/security/limits.conf.\n       For the full documentation, see man limits.conf(5).\noptions:\n  domain:\n    description:\n      - A username, @groupname, wildcard, uid/gid range.\n    required: true\n  limit_type:\n    description:\n      - Limit type, see C(man limits) for an explanation\n    required: true\n    choices: [ \"hard\", \"soft\", \"-\" ]\n  limit_item:\n    description:\n      - The limit to be set\n    required: true\n    choices: [ \"core\", \"data\", \"fsize\", \"memlock\", \"nofile\", \"rss\", \"stack\", \"cpu\", \"nproc\", \"as\", \"maxlogins\", \"maxsyslogins\", \"priority\", \"locks\", \"sigpending\", \"msgqueue\", \"nice\", \"rtprio\", \"chroot\" ]\n  value:\n    description:\n      - The value of the limit.\n    required: true\n  backup:\n    description:\n      - Create a backup file including the timestamp information so you can get\n        the original file back if you somehow clobbered it incorrectly.\n    required: false\n    choices: [ \"yes\", \"no\" ]\n    default: \"no\"\n  use_min:\n    description:\n      - If set to C(yes), the minimal value will be used or conserved.\n        If the specified value is inferior to the value in the file, file content is replaced with the new value,\n        else content is not modified.\n    required: false\n    choices: [ \"yes\", \"no\" ]\n    default: \"no\"\n  use_max:\n    description:\n      - If set to C(yes), the maximal value will be used or conserved.\n        If the specified value is superior to the value in the file, file content is replaced with the new value,\n        else content is not modified.\n    required: false\n    choices: [ \"yes\", \"no\" ]\n    default: \"no\"\n  dest:\n    description:\n      - Modify the limits.conf path.\n    required: false\n    default: \"/etc/security/limits.conf\"\n'''\n\nEXAMPLES = '''\n# Add or modify limits for the user joe\n- pam_limits: domain=joe limit_type=soft limit_item=nofile value=64000\n\n# Add or modify limits for the user joe. Keep or set the maximal value\n- pam_limits: domain=joe limit_type=soft limit_item=nofile value=1000000\n'''\n\ndef main():\n\n    pam_items = [ 'core', 'data', 'fsize', 'memlock', 'nofile', 'rss', 'stack', 'cpu', 'nproc', 'as', 'maxlogins', 'maxsyslogins', 'priority', 'locks', 'sigpending', 'msgqueue', 'nice', 'rtprio', 'chroot' ]\n\n    pam_types = [ 'soft', 'hard', '-' ]\n\n    limits_conf = '/etc/security/limits.conf'\n\n    module = AnsibleModule(\n        # not checking because of daisy chain to file module\n        argument_spec = dict(\n            domain            = dict(required=True, type='str'),\n            limit_type        = dict(required=True, type='str', choices=pam_types),\n            limit_item        = dict(required=True, type='str', choices=pam_items),\n            value             = dict(required=True, type='str'),\n            use_max           = dict(default=False, type='bool'),\n            use_min           = dict(default=False, type='bool'),\n            backup            = dict(default=False, type='bool'),\n            dest              = dict(default=limits_conf, type='str'),\n            comment           = dict(required=False, default='', type='str')\n        )\n    )\n\n    domain      =       module.params['domain']\n    limit_type  =       module.params['limit_type']\n    limit_item  =       module.params['limit_item']\n    value       =       module.params['value']\n    use_max     =       module.params['use_max']\n    use_min     =       module.params['use_min']\n    backup      =       module.params['backup']\n    limits_conf =       module.params['dest']\n    new_comment =       module.params['comment']\n\n    changed = False\n\n    if os.path.isfile(limits_conf):\n        if not os.access(limits_conf, os.W_OK):\n            module.fail_json(msg=\"%s is not writable. Use sudo\" % (limits_conf) )\n    else:\n        module.fail_json(msg=\"%s is not visible (check presence, access rights, use sudo)\" % (limits_conf) )\n\n    if use_max and use_min:\n        module.fail_json(msg=\"Cannot use use_min and use_max at the same time.\" )\n\n    if not (value in ['unlimited', 'infinity', '-1'] or value.isdigit()):\n        module.fail_json(msg=\"Argument 'value' can be one of 'unlimited', 'infinity', '-1' or positive number. Refer to manual pages for more details.\")\n\n    # Backup\n    if backup:\n        backup_file = module.backup_local(limits_conf)\n\n    space_pattern = re.compile(r'\\s+')\n\n    message = ''\n    f = open (limits_conf, 'r')\n    # Tempfile\n    nf = tempfile.NamedTemporaryFile(delete = False)\n\n    found = False\n    new_value = value\n\n    for line in f:\n\n        if line.startswith('#'):\n            nf.write(line)\n            continue\n\n        newline = re.sub(space_pattern, ' ', line).strip()\n        if not newline:\n            nf.write(line)\n            continue\n\n        # Remove comment in line\n        newline = newline.split('#',1)[0]\n        try:\n            old_comment = line.split('#',1)[1]\n        except:\n            old_comment = ''\n\n        newline = newline.rstrip()\n\n        if not new_comment:\n            new_comment = old_comment\n\n        if new_comment:\n            new_comment = \"\\t#\"+new_comment\n\n        line_fields = newline.split(' ')\n\n        if len(line_fields) != 4:\n            nf.write(line)\n            continue\n\n        line_domain     = line_fields[0]\n        line_type       = line_fields[1]\n        line_item       = line_fields[2]\n        actual_value    = line_fields[3]\n\n        if not (actual_value in ['unlimited', 'infinity', '-1'] or actual_value.isdigit()):\n            module.fail_json(msg=\"Invalid configuration of '%s'. Current value of %s is unsupported.\" % (limits_conf, line_item))\n\n        # Found the line\n        if line_domain == domain and line_type == limit_type and line_item == limit_item:\n            found = True\n            if value == actual_value:\n                message = line\n                nf.write(line)\n                continue\n\n            actual_value_unlimited = actual_value in ['unlimited', 'infinity', '-1']\n            value_unlimited = value in ['unlimited', 'infinity', '-1']\n\n            if use_max:\n                if value.isdigit() and actual_value.isdigit():\n                    new_value = max(int(value), int(actual_value))\n                elif actual_value_unlimited:\n                    new_value = actual_value\n                else:\n                    new_value = value\n\n            if use_min:\n                if value.isdigit() and actual_value.isdigit():\n                    new_value = min(int(value), int(actual_value))\n                elif value_unlimited:\n                    new_value = actual_value\n                else:\n                    new_value = value\n\n            # Change line only if value has changed\n            if new_value != actual_value:\n                changed = True\n                new_limit = domain + \"\\t\" + limit_type + \"\\t\" + limit_item + \"\\t\" + str(new_value) + new_comment + \"\\n\"\n                message = new_limit\n                nf.write(new_limit)\n            else:\n                message = line\n                nf.write(line)\n        else:\n            nf.write(line)\n\n    if not found:\n        changed = True\n        new_limit = domain + \"\\t\" + limit_type + \"\\t\" + limit_item + \"\\t\" + str(new_value) + new_comment + \"\\n\"\n        message = new_limit\n        nf.write(new_limit)\n\n    f.close()\n    nf.close()\n\n    # Copy tempfile to newfile\n    module.atomic_move(nf.name, f.name)\n\n    res_args = dict(\n        changed = changed, msg = message\n    )\n\n    if backup:\n        res_args['backup_file'] = backup_file\n\n    module.exit_json(**res_args)\n\n\n# import module snippets\nfrom ansible.module_utils.basic import *\nmain()\n", "path": "system/pam_limits.py"}]}