@@ -120,16 +120,20 @@ def html_to_rst(html, indent=0, indent_first=False):
120
120
return rst
121
121
122
122
123
- def docs_for (service_name ):
123
+ def docs_for (service_name , session = None , resource_filename = None ):
124
124
"""
125
125
Generate reference documentation (low and high level) for a service
126
126
by name. This generates docs for the latest available version.
127
127
128
128
:type service_name: string
129
129
:param service_name: The service short-name, like 'ec2'
130
+ :type session: botocore.session.Session
131
+ :param session: Existing pre-setup session or ``None``.
130
132
:rtype: string
131
133
"""
132
- session = botocore .session .get_session ()
134
+ if session is None :
135
+ session = botocore .session .get_session ()
136
+
133
137
service_model = session .get_service_model (service_name )
134
138
135
139
print ('Processing {0}-{1}' .format (service_name , service_model .api_version ))
@@ -151,17 +155,26 @@ def docs_for(service_name):
151
155
152
156
docs += '.. contents:: Table of Contents\n :depth: 2\n \n '
153
157
154
- docs += document_client (service_name , official_name , service_model )
158
+ # TODO: Get this information from the model somehow in the future.
159
+ # For now creating and introspecing a client is a quick and
160
+ # dirty way to access waiters/paginators.
161
+ client = session .create_client (service_name , aws_access_key_id = 'dummy' ,
162
+ aws_secret_access_key = 'dummy' ,
163
+ region_name = 'us-east-1' )
164
+
165
+ docs += document_client (service_name , official_name , service_model ,
166
+ client )
155
167
docs += document_client_waiter (session , official_name , service_name ,
156
- service_model )
168
+ service_model , client )
157
169
158
- filename = (os .path .dirname (__file__ ) + '/data/resources/'
159
- '{0}-{1}.resources.json' ).format (service_name ,
160
- service_model .api_version )
170
+ if resource_filename is None :
171
+ resource_filename = (os .path .dirname (__file__ ) + '/data/resources/'
172
+ '{0}-{1}.resources.json' ).format (
173
+ service_name , service_model .api_version )
161
174
# We can't use a set here because dicts aren't hashable!
162
175
models = {}
163
- if os .path .exists (filename ):
164
- data = json .load (open (filename ))
176
+ if os .path .exists (resource_filename ):
177
+ data = json .load (open (resource_filename ))
165
178
model = ResourceModel (service_name , data ['service' ], data ['resources' ])
166
179
167
180
for collection_model in model .collections :
@@ -208,7 +221,7 @@ def docs_for(service_name):
208
221
209
222
return docs
210
223
211
- def document_client (service_name , official_name , service_model ):
224
+ def document_client (service_name , official_name , service_model , client ):
212
225
"""
213
226
Generate low-level client documentation for a service. This generates
214
227
documentation for all available operations.
@@ -221,13 +234,6 @@ def document_client(service_name, official_name, service_model):
221
234
docs += ' {service} = boto3.client(\' {service}\' )\n \n ' .format (
222
235
service = service_name )
223
236
224
- # TODO: Get this information from the model somehow in the future.
225
- # For now creating and introspecing a client is a quick and
226
- # dirty way to access waiters/paginators.
227
- client = boto3 .client (service_name , aws_access_key_id = 'dummy' ,
228
- aws_secret_access_key = 'dummy' ,
229
- region_name = 'us-east-1' )
230
-
231
237
wdoc = ''
232
238
if client .waiter_names :
233
239
# This gets included in alphabetical order below!
@@ -252,10 +258,7 @@ def document_client(service_name, official_name, service_model):
252
258
return docs
253
259
254
260
def document_client_waiter (session , official_name , service_name ,
255
- service_model ):
256
- client = boto3 .client (service_name , aws_access_key_id = 'dummy' ,
257
- aws_secret_access_key = 'dummy' ,
258
- region_name = 'us-east-1' )
261
+ service_model , client ):
259
262
waiter_spec_doc = ''
260
263
if client .waiter_names :
261
264
waiter_spec_doc = 'Waiter\n ------\n \n '
@@ -556,7 +559,7 @@ def document_operation(operation_model, service_name, operation_name=None,
556
559
param_desc = ', ' .join ([
557
560
', ' .join (['{0}=None' .format (k ) for k in required_params ]),
558
561
', ' .join (['{0}=None' .format (k ) for k in optional_params ])
559
- ])
562
+ ]). strip ( ', ' )
560
563
561
564
if operation_name is None :
562
565
operation_name = xform_name (operation_model .name )
@@ -601,7 +604,7 @@ def document_operation(operation_model, service_name, operation_name=None,
601
604
if param_type in ['list' , 'dict' ]:
602
605
param_desc = ('\n Structure description::\n \n ' +
603
606
' ' + key + ' = ' +
604
- document_structure (
607
+ document_param_response (
605
608
key , value , indent = 12 , indent_first = False ) +
606
609
'\n ' + param_desc )
607
610
required = key in required_params and 'Required' or 'Optional'
@@ -615,21 +618,13 @@ def document_operation(operation_model, service_name, operation_name=None,
615
618
output_shape = operation_model .output_shape
616
619
if rtype in ['list' , 'dict' ] and output_shape is not None :
617
620
docs += (' :return:\n Structure description::\n \n ' +
618
- document_structure (None , output_shape , indent = 12 ) + '\n ' )
621
+ document_param_response (None , output_shape , indent = 12 ) + '\n ' )
619
622
620
623
return docs
621
624
622
625
623
- PARAM_NAME = "'{name}': "
624
- ELLIPSIS = '...\n '
625
- STRUCT_START = '{\n '
626
- STRUCT_END = '}'
627
- LIST_START = '[\n '
628
- LIST_END = ']'
629
-
630
-
631
- def document_structure (name , shape , indent = 0 , indent_first = True ,
632
- parent_type = None , eol = '\n ' ):
626
+ def document_param_response (name , shape , indent = 0 , indent_first = True ,
627
+ parent_type = None , eol = '\n ' ):
633
628
"""
634
629
Document a nested structure (list or dict) parameter or return value as
635
630
a snippet of Python code with dummy placeholders. For example:
@@ -661,6 +656,7 @@ def document_structure(name, shape, indent=0, indent_first=True,
661
656
:param eol: The end-of-line string to use when finishing a member.
662
657
:rtype: string
663
658
"""
659
+ param_name = "'{name}': "
664
660
docs = ''
665
661
spaces = ' ' * indent
666
662
@@ -671,43 +667,100 @@ def document_structure(name, shape, indent=0, indent_first=True,
671
667
if shape .type_name == 'structure' :
672
668
# Only include the name if the parent is also a structure.
673
669
if parent_type == 'structure' :
674
- docs += PARAM_NAME .format (name = name )
675
-
676
- docs += STRUCT_START
677
-
678
- # Go through each member and recursively process them.
679
- for i , member_name in enumerate (shape .members ):
680
- # Individual members get a trailing comma only if they
681
- # are not the last item.
682
- member_eol = '\n '
683
- if i < len (shape .members ) - 1 :
684
- member_eol = ',' + member_eol
685
-
686
- docs += document_structure (
687
- member_name , shape .members [member_name ],
688
- indent = indent + 4 , parent_type = shape .type_name ,
689
- eol = member_eol )
690
- docs += spaces + STRUCT_END + eol
670
+ docs += param_name .format (name = name )
671
+
672
+ docs += render_structure (shape , spaces , indent , eol )
691
673
elif shape .type_name == 'list' :
692
674
# Only include the name if the parent is a structure.
693
675
if parent_type == 'structure' :
694
- docs += PARAM_NAME .format (name = name )
676
+ docs += param_name .format (name = name )
695
677
696
- docs += LIST_START
678
+ docs += render_list (shape , spaces , indent , eol )
679
+ elif shape .type_name == 'map' :
680
+ if parent_type == 'structure' :
681
+ docs += param_name .format (name = name )
697
682
698
- # Lists have only a single member. Here we document it, plus add
699
- # an ellipsis to signify that more of the same member type can be
700
- # added in a list.
701
- docs += document_structure (
702
- None , shape .member , indent = indent + 4 , eol = ',\n ' )
703
- docs += spaces + ' ' + ELLIPSIS
704
- docs += spaces + LIST_END + eol
683
+ docs += render_map (shape , spaces , indent , eol )
705
684
else :
706
685
# It's not a structure or list, so document the type. Here we
707
686
# try to use the equivalent Python type name for clarity.
708
687
if name is not None :
709
- docs += PARAM_NAME .format (name = name )
688
+ docs += param_name .format (name = name )
710
689
711
690
docs += py_type_name (shape .type_name ).upper () + eol
712
691
713
692
return docs
693
+
694
+
695
+ def render_structure (shape , spaces , indent , eol ):
696
+ """
697
+ Render out a ``structure`` type. This renders info about each
698
+ member in the shape::
699
+
700
+ {
701
+ 'MemberName': 'Value'
702
+ }
703
+
704
+ """
705
+ docs = '{\n '
706
+
707
+ # Go through each member and recursively process them.
708
+ for i , member_name in enumerate (shape .members ):
709
+ # Individual members get a trailing comma only if they
710
+ # are not the last item.
711
+ member_eol = '\n '
712
+ if i < len (shape .members ) - 1 :
713
+ member_eol = ',' + member_eol
714
+
715
+ docs += document_param_response (
716
+ member_name , shape .members [member_name ],
717
+ indent = indent + 4 , parent_type = shape .type_name ,
718
+ eol = member_eol )
719
+ docs += spaces + '}' + eol
720
+
721
+ return docs
722
+
723
+
724
+ def render_list (shape , spaces , indent , eol ):
725
+ """
726
+ Render out a ``list`` type. This renders info about the member
727
+ type of the list and adds an ellipsis to indicate it can contain
728
+ many items::
729
+
730
+ [
731
+ 'STRING',
732
+ ...
733
+ ]
734
+
735
+ """
736
+ docs = '[\n '
737
+
738
+ # Lists have only a single member. Here we document it, plus add
739
+ # an ellipsis to signify that more of the same member type can be
740
+ # added in a list.
741
+ docs += document_param_response (
742
+ None , shape .member , indent = indent + 4 , eol = ',\n ' )
743
+ docs += spaces + ' ...\n '
744
+ docs += spaces + ']' + eol
745
+
746
+ return docs
747
+
748
+
749
+ def render_map (shape , spaces , indent , eol ):
750
+ """
751
+ Render out a ``structure`` type. This renders info about each
752
+ member in the shape::
753
+
754
+ {
755
+ 'MemberName': 'Value'
756
+ }
757
+
758
+ """
759
+ docs = '{\n '
760
+
761
+ # Document the types for the keys and values.
762
+ docs += (spaces + ' ' + py_type_name (shape .key .type_name ).upper ()
763
+ + ': ' + py_type_name (shape .value .type_name ).upper () + '\n ' )
764
+ docs += spaces + '}' + eol
765
+
766
+ return docs
0 commit comments