Repository: boto/botocore
Pull request #569 (2015-06-17 21:42:07)

Add functionality for shapes with no members
This fixed the formatting issues where an empty method call/structure had
the starting and ending parenthesis/bracket on separate lines.

It currently looks like this:
![screen shot 2015-06-17 at 2 38 18 pm](https://cloud.githubusercontent.com/assets/4605355/8219373/70d32510-14fe-11e5-845f-576fa297a264.png)

The PR changes it to be like this:
![screen shot 2015-06-17 at 2 41 55 pm](https://cloud.githubusercontent.com/assets/4605355/8219436/ee087c2e-14fe-11e5-9891-cba6b37373f6.png)

cc @jamesls @mtdowling 


Patch:
diff --git a/botocore/docs/bcdoc/restdoc.py b/botocore/docs/bcdoc/restdoc.py
index 96566a990..2cbd29ef8 100644
--- a/botocore/docs/bcdoc/restdoc.py
+++ b/botocore/docs/bcdoc/restdoc.py
@@ -197,3 +197,6 @@ class DocumentStructure(ReSTDocument):
 
     def getvalue(self):
         return ''.join(self._writes).encode('utf-8')
+
+    def clear_text(self):
+        self._writes = []
diff --git a/botocore/docs/example.py b/botocore/docs/example.py
index b4179f710..7d6c0a0e5 100644
--- a/botocore/docs/example.py
+++ b/botocore/docs/example.py
@@ -94,8 +94,7 @@ class BaseExampleDocumenter(ShapeDocumenter):
                     'ending-comma')
                 ending_comma_section.write(',')
                 ending_comma_section.style.new_line()
-        ending_bracket_section = section.add_new_section('ending-bracket')
-        self._end_nested_param(ending_bracket_section, '}')
+        self._end_structure(section, '{', '}')
 
     def document_shape_type_map(self, section, shape, history,
                                 include=None, exclude=None, **kwargs):
@@ -131,6 +130,18 @@ class BaseExampleDocumenter(ShapeDocumenter):
         if end is not None:
             section.write(end)
 
+    def _end_structure(self, section, start, end):
+        # If there are no members in the strucuture, then make sure the
+        # start and the end bracket are on the same line, by removing all
+        # previous text and writing the start and end.
+        if not section.available_sections:
+            section.clear_text()
+            section.write(start + end)
+            self._end_nested_param(section)
+        else:
+            end_bracket_section = section.add_new_section('ending-bracket')
+            self._end_nested_param(end_bracket_section, end)
+
 
 class ResponseExampleDocumenter(BaseExampleDocumenter):
     EVENT_NAME = 'response-example'
@@ -171,5 +182,4 @@ class RequestExampleDocumenter(BaseExampleDocumenter):
                     'ending-comma')
                 ending_comma_section.write(',')
                 ending_comma_section.style.new_line()
-        end_bracket_section = section.add_new_section('ending-bracket')
-        self._end_nested_param(end_bracket_section, end)
+        self._end_structure(section, start, end)


Test patch:
diff --git a/tests/unit/docs/bcdoc/test_document.py b/tests/unit/docs/bcdoc/test_document.py
index 64dfb9a49..617828f26 100644
--- a/tests/unit/docs/bcdoc/test_document.py
+++ b/tests/unit/docs/bcdoc/test_document.py
@@ -131,3 +131,8 @@ class TestDocumentStructure(unittest.TestCase):
             self.doc_structure.available_sections,
             ['mysection', 'mysection2']
         )
+
+    def test_clear_text(self):
+        self.doc_structure.write('Foo')
+        self.doc_structure.clear_text()
+        self.assertEqual(self.doc_structure.flush_structure(), six.b(''))
diff --git a/tests/unit/docs/test_example.py b/tests/unit/docs/test_example.py
index 41048936a..e17afe257 100644
--- a/tests/unit/docs/test_example.py
+++ b/tests/unit/docs/test_example.py
@@ -60,6 +60,30 @@ class TestDocumentDefaultValue(BaseExampleDocumenterTest):
         ])
 
 
+class TestDocumentNoMembers(BaseExampleDocumenterTest):
+    def setUp(self):
+        super(TestDocumentNoMembers, self).setUp()
+
+    def test_request_example(self):
+        self.request_example.document_example(
+            self.doc_structure, self.operation_model.input_shape,
+            prefix='response = myclient.call'
+        )
+        self.assert_contains_lines_in_order([
+            '::',
+            '  response = myclient.call()'
+        ])
+
+    def test_response_example(self):
+        self.response_example.document_example(
+            self.doc_structure, self.operation_model.input_shape,
+        )
+        self.assert_contains_lines_in_order([
+            '::',
+            '  {}'
+        ])
+
+
 class TestTraverseAndDocumentShape(BaseExampleDocumenterTest):
     def setUp(self):
         super(TestTraverseAndDocumentShape, self).setUp()