We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Adding new profile should add newline before
Have multiple IAM users configured in `~/.aws/credentials`

Added IAM user as follows:
`aws configure --profile NEW_PROFILE_NAME`
Completed sucessfully as expected.

However, next step of running a command resulted in error: 
```
PS C:\WINDOWS\system32> aws --profile NEW_PROFILE_NAME s3 ls
Unable to locate credentials. You can configure credentials by running "aws configure".
```
Checking `~/.aws/credentials` file showed new creds were appended to file without newline as follows:
```
[OLD_PROFILE_NAME]
aws_access_key_id = AAAAAAAAAAAAAAAAAAAA
aws_secret_access_key = KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK
region=XX-east-X
toolkit_artifact_guid=11111111-1111-1111-1111-111111111111[NEW_PROFILE_NAME]
aws_access_key_id = BBBBBBBBBBBBBBBBBBBB
aws_secret_access_key = JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJ
```

IMHO this is easily fixable by adding a newline echo before the new creds

CLI version: `aws-cli/1.12.2 Python/2.7.14 Windows/10 botocore/1.8.2`

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `awscli/customizations/configure/writer.py`
Content:
```
1 # Copyright 2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License"). You
4 # may not use this file except in compliance with the License. A copy of
5 # the License is located at
6 #
7 #     http://aws.amazon.com/apache2.0/
8 #
9 # or in the "license" file accompanying this file. This file is
10 # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
11 # ANY KIND, either express or implied. See the License for the specific
12 # language governing permissions and limitations under the License.
13 import os
14 import re
15 
16 from . import SectionNotFoundError
17 
18 
19 class ConfigFileWriter(object):
20     SECTION_REGEX = re.compile(r'^\s*\[(?P<header>[^]]+)\]')
21     OPTION_REGEX = re.compile(
22         r'(?P<option>[^:=][^:=]*)'
23         r'\s*(?P<vi>[:=])\s*'
24         r'(?P<value>.*)$'
25     )
26 
27     def update_config(self, new_values, config_filename):
28         """Update config file with new values.
29 
30         This method will update a section in a config file with
31         new key value pairs.
32 
33         This method provides a few conveniences:
34 
35         * If the ``config_filename`` does not exist, it will
36           be created.  Any parent directories will also be created
37           if necessary.
38         * If the section to update does not exist, it will be created.
39         * Any existing lines that are specified by ``new_values``
40           **will not be touched**.  This ensures that commented out
41           values are left unaltered.
42 
43         :type new_values: dict
44         :param new_values: The values to update.  There is a special
45             key ``__section__``, that specifies what section in the INI
46             file to update.  If this key is not present, then the
47             ``default`` section will be updated with the new values.
48 
49         :type config_filename: str
50         :param config_filename: The config filename where values will be
51             written.
52 
53         """
54         section_name = new_values.pop('__section__', 'default')
55         if not os.path.isfile(config_filename):
56             self._create_file(config_filename)
57             self._write_new_section(section_name, new_values, config_filename)
58             return
59         with open(config_filename, 'r') as f:
60             contents = f.readlines()
61         # We can only update a single section at a time so we first need
62         # to find the section in question
63         try:
64             self._update_section_contents(contents, section_name, new_values)
65             with open(config_filename, 'w') as f:
66                 f.write(''.join(contents))
67         except SectionNotFoundError:
68             self._write_new_section(section_name, new_values, config_filename)
69 
70     def _create_file(self, config_filename):
71         # Create the file as well as the parent dir if needed.
72         dirname = os.path.split(config_filename)[0]
73         if not os.path.isdir(dirname):
74             os.makedirs(dirname)
75         with os.fdopen(os.open(config_filename,
76                                os.O_WRONLY | os.O_CREAT, 0o600), 'w'):
77             pass
78 
79     def _write_new_section(self, section_name, new_values, config_filename):
80         with open(config_filename, 'a') as f:
81             f.write('[%s]\n' % section_name)
82             contents = []
83             self._insert_new_values(line_number=0,
84                                     contents=contents,
85                                     new_values=new_values)
86             f.write(''.join(contents))
87 
88     def _find_section_start(self, contents, section_name):
89         for i in range(len(contents)):
90             line = contents[i]
91             if line.strip().startswith(('#', ';')):
92                 # This is a comment, so we can safely ignore this line.
93                 continue
94             match = self.SECTION_REGEX.search(line)
95             if match is not None and self._matches_section(match,
96                                                            section_name):
97                 return i
98         raise SectionNotFoundError(section_name)
99 
100     def _update_section_contents(self, contents, section_name, new_values):
101         # First, find the line where the section_name is defined.
102         # This will be the value of i.
103         new_values = new_values.copy()
104         # ``contents`` is a list of file line contents.
105         section_start_line_num = self._find_section_start(contents,
106                                                           section_name)
107         # If we get here, then we've found the section.  We now need
108         # to figure out if we're updating a value or adding a new value.
109         # There's 2 cases.  Either we're setting a normal scalar value
110         # of, we're setting a nested value.
111         last_matching_line = section_start_line_num
112         j = last_matching_line + 1
113         while j < len(contents):
114             line = contents[j]
115             if self.SECTION_REGEX.search(line) is not None:
116                 # We've hit a new section which means the config key is
117                 # not in the section.  We need to add it here.
118                 self._insert_new_values(line_number=last_matching_line,
119                                         contents=contents,
120                                         new_values=new_values)
121                 return
122             match = self.OPTION_REGEX.search(line)
123             if match is not None:
124                 last_matching_line = j
125                 key_name = match.group(1).strip()
126                 if key_name in new_values:
127                     # We've found the line that defines the option name.
128                     # if the value is not a dict, then we can write the line
129                     # out now.
130                     if not isinstance(new_values[key_name], dict):
131                         option_value = new_values[key_name]
132                         new_line = '%s = %s\n' % (key_name, option_value)
133                         contents[j] = new_line
134                         del new_values[key_name]
135                     else:
136                         j = self._update_subattributes(
137                             j, contents, new_values[key_name],
138                             len(match.group(1)) - len(match.group(1).lstrip()))
139                         return
140             j += 1
141 
142         if new_values:
143             if not contents[-1].endswith('\n'):
144                 contents.append('\n')
145             self._insert_new_values(line_number=last_matching_line + 1,
146                                     contents=contents,
147                                     new_values=new_values)
148 
149     def _update_subattributes(self, index, contents, values, starting_indent):
150         index += 1
151         for i in range(index, len(contents)):
152             line = contents[i]
153             match = self.OPTION_REGEX.search(line)
154             if match is not None:
155                 current_indent = len(
156                     match.group(1)) - len(match.group(1).lstrip())
157                 key_name = match.group(1).strip()
158                 if key_name in values:
159                     option_value = values[key_name]
160                     new_line = '%s%s = %s\n' % (' ' * current_indent,
161                                                 key_name, option_value)
162                     contents[i] = new_line
163                     del values[key_name]
164             if starting_indent == current_indent or \
165                     self.SECTION_REGEX.search(line) is not None:
166                 # We've arrived at the starting indent level so we can just
167                 # write out all the values now.
168                 self._insert_new_values(i - 1, contents, values, '    ')
169                 break
170         else:
171             if starting_indent != current_indent:
172                 # The option is the last option in the file
173                 self._insert_new_values(i, contents, values, '    ')
174         return i
175 
176     def _insert_new_values(self, line_number, contents, new_values, indent=''):
177         new_contents = []
178         for key, value in list(new_values.items()):
179             if isinstance(value, dict):
180                 subindent = indent + '    '
181                 new_contents.append('%s%s =\n' % (indent, key))
182                 for subkey, subval in list(value.items()):
183                     new_contents.append('%s%s = %s\n' % (subindent, subkey,
184                                                          subval))
185             else:
186                 new_contents.append('%s%s = %s\n' % (indent, key, value))
187             del new_values[key]
188         contents.insert(line_number + 1, ''.join(new_contents))
189 
190     def _matches_section(self, match, section_name):
191         parts = section_name.split(' ')
192         unquoted_match = match.group(0) == '[%s]' % section_name
193         if len(parts) > 1:
194             quoted_match = match.group(0) == '[%s "%s"]' % (
195                 parts[0], ' '.join(parts[1:]))
196             return unquoted_match or quoted_match
197         return unquoted_match
198
```
--- 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/awscli/customizations/configure/writer.py b/awscli/customizations/configure/writer.py
--- a/awscli/customizations/configure/writer.py
+++ b/awscli/customizations/configure/writer.py
@@ -76,8 +76,22 @@
                                os.O_WRONLY | os.O_CREAT, 0o600), 'w'):
             pass
 
+    def _check_file_needs_newline(self, filename):
+        # check if the last byte is a newline
+        with open(filename, 'rb') as f:
+            # check if the file is empty
+            f.seek(0, os.SEEK_END)
+            if not f.tell():
+                return False
+            f.seek(-1, os.SEEK_END)
+            last = f.read()
+            return last != b'\n'
+
     def _write_new_section(self, section_name, new_values, config_filename):
+        needs_newline = self._check_file_needs_newline(config_filename)
         with open(config_filename, 'a') as f:
+            if needs_newline:
+                f.write('\n')
             f.write('[%s]\n' % section_name)
             contents = []
             self._insert_new_values(line_number=0,

{"golden_diff": "diff --git a/awscli/customizations/configure/writer.py b/awscli/customizations/configure/writer.py\n--- a/awscli/customizations/configure/writer.py\n+++ b/awscli/customizations/configure/writer.py\n@@ -76,8 +76,22 @@\n                                os.O_WRONLY | os.O_CREAT, 0o600), 'w'):\n             pass\n \n+    def _check_file_needs_newline(self, filename):\n+        # check if the last byte is a newline\n+        with open(filename, 'rb') as f:\n+            # check if the file is empty\n+            f.seek(0, os.SEEK_END)\n+            if not f.tell():\n+                return False\n+            f.seek(-1, os.SEEK_END)\n+            last = f.read()\n+            return last != b'\\n'\n+\n     def _write_new_section(self, section_name, new_values, config_filename):\n+        needs_newline = self._check_file_needs_newline(config_filename)\n         with open(config_filename, 'a') as f:\n+            if needs_newline:\n+                f.write('\\n')\n             f.write('[%s]\\n' % section_name)\n             contents = []\n             self._insert_new_values(line_number=0,\n", "issue": "Adding new profile should add newline before\nHave multiple IAM users configured in `~/.aws/credentials`\r\n\r\nAdded IAM user as follows:\r\n`aws configure --profile NEW_PROFILE_NAME`\r\nCompleted sucessfully as expected.\r\n\r\nHowever, next step of running a command resulted in error: \r\n```\r\nPS C:\\WINDOWS\\system32> aws --profile NEW_PROFILE_NAME s3 ls\r\nUnable to locate credentials. You can configure credentials by running \"aws configure\".\r\n```\r\nChecking `~/.aws/credentials` file showed new creds were appended to file without newline as follows:\r\n```\r\n[OLD_PROFILE_NAME]\r\naws_access_key_id = AAAAAAAAAAAAAAAAAAAA\r\naws_secret_access_key = KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK\r\nregion=XX-east-X\r\ntoolkit_artifact_guid=11111111-1111-1111-1111-111111111111[NEW_PROFILE_NAME]\r\naws_access_key_id = BBBBBBBBBBBBBBBBBBBB\r\naws_secret_access_key = JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJ\r\n```\r\n\r\nIMHO this is easily fixable by adding a newline echo before the new creds\r\n\r\nCLI version: `aws-cli/1.12.2 Python/2.7.14 Windows/10 botocore/1.8.2`\n", "before_files": [{"content": "# Copyright 2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\"). You\n# may not use this file except in compliance with the License. A copy of\n# the License is located at\n#\n#     http://aws.amazon.com/apache2.0/\n#\n# or in the \"license\" file accompanying this file. This file is\n# distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF\n# ANY KIND, either express or implied. See the License for the specific\n# language governing permissions and limitations under the License.\nimport os\nimport re\n\nfrom . import SectionNotFoundError\n\n\nclass ConfigFileWriter(object):\n    SECTION_REGEX = re.compile(r'^\\s*\\[(?P<header>[^]]+)\\]')\n    OPTION_REGEX = re.compile(\n        r'(?P<option>[^:=][^:=]*)'\n        r'\\s*(?P<vi>[:=])\\s*'\n        r'(?P<value>.*)$'\n    )\n\n    def update_config(self, new_values, config_filename):\n        \"\"\"Update config file with new values.\n\n        This method will update a section in a config file with\n        new key value pairs.\n\n        This method provides a few conveniences:\n\n        * If the ``config_filename`` does not exist, it will\n          be created.  Any parent directories will also be created\n          if necessary.\n        * If the section to update does not exist, it will be created.\n        * Any existing lines that are specified by ``new_values``\n          **will not be touched**.  This ensures that commented out\n          values are left unaltered.\n\n        :type new_values: dict\n        :param new_values: The values to update.  There is a special\n            key ``__section__``, that specifies what section in the INI\n            file to update.  If this key is not present, then the\n            ``default`` section will be updated with the new values.\n\n        :type config_filename: str\n        :param config_filename: The config filename where values will be\n            written.\n\n        \"\"\"\n        section_name = new_values.pop('__section__', 'default')\n        if not os.path.isfile(config_filename):\n            self._create_file(config_filename)\n            self._write_new_section(section_name, new_values, config_filename)\n            return\n        with open(config_filename, 'r') as f:\n            contents = f.readlines()\n        # We can only update a single section at a time so we first need\n        # to find the section in question\n        try:\n            self._update_section_contents(contents, section_name, new_values)\n            with open(config_filename, 'w') as f:\n                f.write(''.join(contents))\n        except SectionNotFoundError:\n            self._write_new_section(section_name, new_values, config_filename)\n\n    def _create_file(self, config_filename):\n        # Create the file as well as the parent dir if needed.\n        dirname = os.path.split(config_filename)[0]\n        if not os.path.isdir(dirname):\n            os.makedirs(dirname)\n        with os.fdopen(os.open(config_filename,\n                               os.O_WRONLY | os.O_CREAT, 0o600), 'w'):\n            pass\n\n    def _write_new_section(self, section_name, new_values, config_filename):\n        with open(config_filename, 'a') as f:\n            f.write('[%s]\\n' % section_name)\n            contents = []\n            self._insert_new_values(line_number=0,\n                                    contents=contents,\n                                    new_values=new_values)\n            f.write(''.join(contents))\n\n    def _find_section_start(self, contents, section_name):\n        for i in range(len(contents)):\n            line = contents[i]\n            if line.strip().startswith(('#', ';')):\n                # This is a comment, so we can safely ignore this line.\n                continue\n            match = self.SECTION_REGEX.search(line)\n            if match is not None and self._matches_section(match,\n                                                           section_name):\n                return i\n        raise SectionNotFoundError(section_name)\n\n    def _update_section_contents(self, contents, section_name, new_values):\n        # First, find the line where the section_name is defined.\n        # This will be the value of i.\n        new_values = new_values.copy()\n        # ``contents`` is a list of file line contents.\n        section_start_line_num = self._find_section_start(contents,\n                                                          section_name)\n        # If we get here, then we've found the section.  We now need\n        # to figure out if we're updating a value or adding a new value.\n        # There's 2 cases.  Either we're setting a normal scalar value\n        # of, we're setting a nested value.\n        last_matching_line = section_start_line_num\n        j = last_matching_line + 1\n        while j < len(contents):\n            line = contents[j]\n            if self.SECTION_REGEX.search(line) is not None:\n                # We've hit a new section which means the config key is\n                # not in the section.  We need to add it here.\n                self._insert_new_values(line_number=last_matching_line,\n                                        contents=contents,\n                                        new_values=new_values)\n                return\n            match = self.OPTION_REGEX.search(line)\n            if match is not None:\n                last_matching_line = j\n                key_name = match.group(1).strip()\n                if key_name in new_values:\n                    # We've found the line that defines the option name.\n                    # if the value is not a dict, then we can write the line\n                    # out now.\n                    if not isinstance(new_values[key_name], dict):\n                        option_value = new_values[key_name]\n                        new_line = '%s = %s\\n' % (key_name, option_value)\n                        contents[j] = new_line\n                        del new_values[key_name]\n                    else:\n                        j = self._update_subattributes(\n                            j, contents, new_values[key_name],\n                            len(match.group(1)) - len(match.group(1).lstrip()))\n                        return\n            j += 1\n\n        if new_values:\n            if not contents[-1].endswith('\\n'):\n                contents.append('\\n')\n            self._insert_new_values(line_number=last_matching_line + 1,\n                                    contents=contents,\n                                    new_values=new_values)\n\n    def _update_subattributes(self, index, contents, values, starting_indent):\n        index += 1\n        for i in range(index, len(contents)):\n            line = contents[i]\n            match = self.OPTION_REGEX.search(line)\n            if match is not None:\n                current_indent = len(\n                    match.group(1)) - len(match.group(1).lstrip())\n                key_name = match.group(1).strip()\n                if key_name in values:\n                    option_value = values[key_name]\n                    new_line = '%s%s = %s\\n' % (' ' * current_indent,\n                                                key_name, option_value)\n                    contents[i] = new_line\n                    del values[key_name]\n            if starting_indent == current_indent or \\\n                    self.SECTION_REGEX.search(line) is not None:\n                # We've arrived at the starting indent level so we can just\n                # write out all the values now.\n                self._insert_new_values(i - 1, contents, values, '    ')\n                break\n        else:\n            if starting_indent != current_indent:\n                # The option is the last option in the file\n                self._insert_new_values(i, contents, values, '    ')\n        return i\n\n    def _insert_new_values(self, line_number, contents, new_values, indent=''):\n        new_contents = []\n        for key, value in list(new_values.items()):\n            if isinstance(value, dict):\n                subindent = indent + '    '\n                new_contents.append('%s%s =\\n' % (indent, key))\n                for subkey, subval in list(value.items()):\n                    new_contents.append('%s%s = %s\\n' % (subindent, subkey,\n                                                         subval))\n            else:\n                new_contents.append('%s%s = %s\\n' % (indent, key, value))\n            del new_values[key]\n        contents.insert(line_number + 1, ''.join(new_contents))\n\n    def _matches_section(self, match, section_name):\n        parts = section_name.split(' ')\n        unquoted_match = match.group(0) == '[%s]' % section_name\n        if len(parts) > 1:\n            quoted_match = match.group(0) == '[%s \"%s\"]' % (\n                parts[0], ' '.join(parts[1:]))\n            return unquoted_match or quoted_match\n        return unquoted_match\n", "path": "awscli/customizations/configure/writer.py"}], "after_files": [{"content": "# Copyright 2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\"). You\n# may not use this file except in compliance with the License. A copy of\n# the License is located at\n#\n#     http://aws.amazon.com/apache2.0/\n#\n# or in the \"license\" file accompanying this file. This file is\n# distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF\n# ANY KIND, either express or implied. See the License for the specific\n# language governing permissions and limitations under the License.\nimport os\nimport re\n\nfrom . import SectionNotFoundError\n\n\nclass ConfigFileWriter(object):\n    SECTION_REGEX = re.compile(r'^\\s*\\[(?P<header>[^]]+)\\]')\n    OPTION_REGEX = re.compile(\n        r'(?P<option>[^:=][^:=]*)'\n        r'\\s*(?P<vi>[:=])\\s*'\n        r'(?P<value>.*)$'\n    )\n\n    def update_config(self, new_values, config_filename):\n        \"\"\"Update config file with new values.\n\n        This method will update a section in a config file with\n        new key value pairs.\n\n        This method provides a few conveniences:\n\n        * If the ``config_filename`` does not exist, it will\n          be created.  Any parent directories will also be created\n          if necessary.\n        * If the section to update does not exist, it will be created.\n        * Any existing lines that are specified by ``new_values``\n          **will not be touched**.  This ensures that commented out\n          values are left unaltered.\n\n        :type new_values: dict\n        :param new_values: The values to update.  There is a special\n            key ``__section__``, that specifies what section in the INI\n            file to update.  If this key is not present, then the\n            ``default`` section will be updated with the new values.\n\n        :type config_filename: str\n        :param config_filename: The config filename where values will be\n            written.\n\n        \"\"\"\n        section_name = new_values.pop('__section__', 'default')\n        if not os.path.isfile(config_filename):\n            self._create_file(config_filename)\n            self._write_new_section(section_name, new_values, config_filename)\n            return\n        with open(config_filename, 'r') as f:\n            contents = f.readlines()\n        # We can only update a single section at a time so we first need\n        # to find the section in question\n        try:\n            self._update_section_contents(contents, section_name, new_values)\n            with open(config_filename, 'w') as f:\n                f.write(''.join(contents))\n        except SectionNotFoundError:\n            self._write_new_section(section_name, new_values, config_filename)\n\n    def _create_file(self, config_filename):\n        # Create the file as well as the parent dir if needed.\n        dirname = os.path.split(config_filename)[0]\n        if not os.path.isdir(dirname):\n            os.makedirs(dirname)\n        with os.fdopen(os.open(config_filename,\n                               os.O_WRONLY | os.O_CREAT, 0o600), 'w'):\n            pass\n\n    def _check_file_needs_newline(self, filename):\n        # check if the last byte is a newline\n        with open(filename, 'rb') as f:\n            # check if the file is empty\n            f.seek(0, os.SEEK_END)\n            if not f.tell():\n                return False\n            f.seek(-1, os.SEEK_END)\n            last = f.read()\n            return last != b'\\n'\n\n    def _write_new_section(self, section_name, new_values, config_filename):\n        needs_newline = self._check_file_needs_newline(config_filename)\n        with open(config_filename, 'a') as f:\n            if needs_newline:\n                f.write('\\n')\n            f.write('[%s]\\n' % section_name)\n            contents = []\n            self._insert_new_values(line_number=0,\n                                    contents=contents,\n                                    new_values=new_values)\n            f.write(''.join(contents))\n\n    def _find_section_start(self, contents, section_name):\n        for i in range(len(contents)):\n            line = contents[i]\n            if line.strip().startswith(('#', ';')):\n                # This is a comment, so we can safely ignore this line.\n                continue\n            match = self.SECTION_REGEX.search(line)\n            if match is not None and self._matches_section(match,\n                                                           section_name):\n                return i\n        raise SectionNotFoundError(section_name)\n\n    def _update_section_contents(self, contents, section_name, new_values):\n        # First, find the line where the section_name is defined.\n        # This will be the value of i.\n        new_values = new_values.copy()\n        # ``contents`` is a list of file line contents.\n        section_start_line_num = self._find_section_start(contents,\n                                                          section_name)\n        # If we get here, then we've found the section.  We now need\n        # to figure out if we're updating a value or adding a new value.\n        # There's 2 cases.  Either we're setting a normal scalar value\n        # of, we're setting a nested value.\n        last_matching_line = section_start_line_num\n        j = last_matching_line + 1\n        while j < len(contents):\n            line = contents[j]\n            if self.SECTION_REGEX.search(line) is not None:\n                # We've hit a new section which means the config key is\n                # not in the section.  We need to add it here.\n                self._insert_new_values(line_number=last_matching_line,\n                                        contents=contents,\n                                        new_values=new_values)\n                return\n            match = self.OPTION_REGEX.search(line)\n            if match is not None:\n                last_matching_line = j\n                key_name = match.group(1).strip()\n                if key_name in new_values:\n                    # We've found the line that defines the option name.\n                    # if the value is not a dict, then we can write the line\n                    # out now.\n                    if not isinstance(new_values[key_name], dict):\n                        option_value = new_values[key_name]\n                        new_line = '%s = %s\\n' % (key_name, option_value)\n                        contents[j] = new_line\n                        del new_values[key_name]\n                    else:\n                        j = self._update_subattributes(\n                            j, contents, new_values[key_name],\n                            len(match.group(1)) - len(match.group(1).lstrip()))\n                        return\n            j += 1\n\n        if new_values:\n            if not contents[-1].endswith('\\n'):\n                contents.append('\\n')\n            self._insert_new_values(line_number=last_matching_line + 1,\n                                    contents=contents,\n                                    new_values=new_values)\n\n    def _update_subattributes(self, index, contents, values, starting_indent):\n        index += 1\n        for i in range(index, len(contents)):\n            line = contents[i]\n            match = self.OPTION_REGEX.search(line)\n            if match is not None:\n                current_indent = len(\n                    match.group(1)) - len(match.group(1).lstrip())\n                key_name = match.group(1).strip()\n                if key_name in values:\n                    option_value = values[key_name]\n                    new_line = '%s%s = %s\\n' % (' ' * current_indent,\n                                                key_name, option_value)\n                    contents[i] = new_line\n                    del values[key_name]\n            if starting_indent == current_indent or \\\n                    self.SECTION_REGEX.search(line) is not None:\n                # We've arrived at the starting indent level so we can just\n                # write out all the values now.\n                self._insert_new_values(i - 1, contents, values, '    ')\n                break\n        else:\n            if starting_indent != current_indent:\n                # The option is the last option in the file\n                self._insert_new_values(i, contents, values, '    ')\n        return i\n\n    def _insert_new_values(self, line_number, contents, new_values, indent=''):\n        new_contents = []\n        for key, value in list(new_values.items()):\n            if isinstance(value, dict):\n                subindent = indent + '    '\n                new_contents.append('%s%s =\\n' % (indent, key))\n                for subkey, subval in list(value.items()):\n                    new_contents.append('%s%s = %s\\n' % (subindent, subkey,\n                                                         subval))\n            else:\n                new_contents.append('%s%s = %s\\n' % (indent, key, value))\n            del new_values[key]\n        contents.insert(line_number + 1, ''.join(new_contents))\n\n    def _matches_section(self, match, section_name):\n        parts = section_name.split(' ')\n        unquoted_match = match.group(0) == '[%s]' % section_name\n        if len(parts) > 1:\n            quoted_match = match.group(0) == '[%s \"%s\"]' % (\n                parts[0], ' '.join(parts[1:]))\n            return unquoted_match or quoted_match\n        return unquoted_match\n", "path": "awscli/customizations/configure/writer.py"}]}