Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/boto3/docs/resource.py: 17%

199 statements  

« prev     ^ index     » next       coverage.py v7.3.2, created at 2023-12-08 06:51 +0000

1# Copyright 2015 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# https://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. 

13import os 

14 

15from botocore import xform_name 

16from botocore.docs.bcdoc.restdoc import DocumentStructure 

17from botocore.docs.utils import get_official_service_name 

18 

19from boto3.docs.action import ActionDocumenter 

20from boto3.docs.attr import ( 

21 document_attribute, 

22 document_identifier, 

23 document_reference, 

24) 

25from boto3.docs.base import BaseDocumenter 

26from boto3.docs.collection import CollectionDocumenter 

27from boto3.docs.subresource import SubResourceDocumenter 

28from boto3.docs.utils import ( 

29 add_resource_type_overview, 

30 get_identifier_args_for_signature, 

31 get_identifier_description, 

32 get_identifier_values_for_example, 

33) 

34from boto3.docs.waiter import WaiterResourceDocumenter 

35 

36 

37class ResourceDocumenter(BaseDocumenter): 

38 def __init__(self, resource, botocore_session, root_docs_path): 

39 super().__init__(resource) 

40 self._botocore_session = botocore_session 

41 self._root_docs_path = root_docs_path 

42 self._resource_sub_path = self._resource_name.lower() 

43 if self._resource_name == self._service_name: 

44 self._resource_sub_path = 'service-resource' 

45 

46 def document_resource(self, section): 

47 self._add_title(section) 

48 self._add_resource_note(section) 

49 self._add_intro(section) 

50 self._add_identifiers(section) 

51 self._add_attributes(section) 

52 self._add_references(section) 

53 self._add_actions(section) 

54 self._add_sub_resources(section) 

55 self._add_collections(section) 

56 self._add_waiters(section) 

57 

58 def _add_title(self, section): 

59 title_section = section.add_new_section('title') 

60 title_section.style.h2(self._resource_name) 

61 

62 def _add_intro(self, section): 

63 identifier_names = [] 

64 if self._resource_model.identifiers: 

65 for identifier in self._resource_model.identifiers: 

66 identifier_names.append(identifier.name) 

67 

68 # Write out the class signature. 

69 class_args = get_identifier_args_for_signature(identifier_names) 

70 start_class = section.add_new_section('start_class') 

71 start_class.style.start_sphinx_py_class( 

72 class_name=f'{self.class_name}({class_args})' 

73 ) 

74 

75 # Add as short description about the resource 

76 description_section = start_class.add_new_section('description') 

77 self._add_description(description_section) 

78 

79 # Add an example of how to instantiate the resource 

80 example_section = start_class.add_new_section('example') 

81 self._add_example(example_section, identifier_names) 

82 

83 # Add the description for the parameters to instantiate the 

84 # resource. 

85 param_section = start_class.add_new_section('params') 

86 self._add_params_description(param_section, identifier_names) 

87 

88 end_class = section.add_new_section('end_class') 

89 end_class.style.end_sphinx_py_class() 

90 

91 def _add_description(self, section): 

92 official_service_name = get_official_service_name(self._service_model) 

93 section.write( 

94 'A resource representing an {} {}'.format( 

95 official_service_name, self._resource_name 

96 ) 

97 ) 

98 

99 def _add_example(self, section, identifier_names): 

100 section.style.start_codeblock() 

101 section.style.new_line() 

102 section.write('import boto3') 

103 section.style.new_line() 

104 section.style.new_line() 

105 section.write( 

106 '{} = boto3.resource(\'{}\')'.format( 

107 self._service_name, self._service_name 

108 ) 

109 ) 

110 section.style.new_line() 

111 example_values = get_identifier_values_for_example(identifier_names) 

112 section.write( 

113 '{} = {}.{}({})'.format( 

114 xform_name(self._resource_name), 

115 self._service_name, 

116 self._resource_name, 

117 example_values, 

118 ) 

119 ) 

120 section.style.end_codeblock() 

121 

122 def _add_params_description(self, section, identifier_names): 

123 for identifier_name in identifier_names: 

124 description = get_identifier_description( 

125 self._resource_name, identifier_name 

126 ) 

127 section.write(f':type {identifier_name}: string') 

128 section.style.new_line() 

129 section.write(f':param {identifier_name}: {description}') 

130 section.style.new_line() 

131 

132 def _add_overview_of_member_type(self, section, resource_member_type): 

133 section.style.new_line() 

134 section.write( 

135 f'These are the resource\'s available {resource_member_type}:' 

136 ) 

137 section.style.new_line() 

138 section.style.toctree() 

139 for member in self.member_map[resource_member_type]: 

140 section.style.tocitem(f'{member}') 

141 

142 def _add_identifiers(self, section): 

143 identifiers = self._resource.meta.resource_model.identifiers 

144 section = section.add_new_section('identifiers') 

145 member_list = [] 

146 if identifiers: 

147 self.member_map['identifiers'] = member_list 

148 add_resource_type_overview( 

149 section=section, 

150 resource_type='Identifiers', 

151 description=( 

152 'Identifiers are properties of a resource that are ' 

153 'set upon instantiation of the resource.' 

154 ), 

155 intro_link='identifiers_attributes_intro', 

156 ) 

157 for identifier in identifiers: 

158 member_list.append(identifier.name) 

159 # Create a new DocumentStructure for each identifier and add contents. 

160 identifier_doc = DocumentStructure(identifier.name, target='html') 

161 breadcrumb_section = identifier_doc.add_new_section('breadcrumb') 

162 breadcrumb_section.style.ref(self._resource_class_name, 'index') 

163 breadcrumb_section.write(f' / Identifier / {identifier.name}') 

164 identifier_doc.add_title_section(identifier.name) 

165 identifier_section = identifier_doc.add_new_section( 

166 identifier.name, 

167 context={'qualifier': f'{self.class_name}.'}, 

168 ) 

169 document_identifier( 

170 section=identifier_section, 

171 resource_name=self._resource_name, 

172 identifier_model=identifier, 

173 ) 

174 # Write identifiers in individual/nested files. 

175 # Path: <root>/reference/services/<service>/<resource_name>/<identifier_name>.rst 

176 identifiers_dir_path = os.path.join( 

177 self._root_docs_path, 

178 f'{self._service_name}', 

179 f'{self._resource_sub_path}', 

180 ) 

181 identifier_doc.write_to_file(identifiers_dir_path, identifier.name) 

182 

183 if identifiers: 

184 self._add_overview_of_member_type(section, 'identifiers') 

185 

186 def _add_attributes(self, section): 

187 service_model = self._resource.meta.client.meta.service_model 

188 attributes = {} 

189 if self._resource.meta.resource_model.shape: 

190 shape = service_model.shape_for( 

191 self._resource.meta.resource_model.shape 

192 ) 

193 attributes = self._resource.meta.resource_model.get_attributes( 

194 shape 

195 ) 

196 section = section.add_new_section('attributes') 

197 attribute_list = [] 

198 if attributes: 

199 add_resource_type_overview( 

200 section=section, 

201 resource_type='Attributes', 

202 description=( 

203 'Attributes provide access' 

204 ' to the properties of a resource. Attributes are lazy-' 

205 'loaded the first time one is accessed via the' 

206 ' :py:meth:`load` method.' 

207 ), 

208 intro_link='identifiers_attributes_intro', 

209 ) 

210 self.member_map['attributes'] = attribute_list 

211 for attr_name in sorted(attributes): 

212 _, attr_shape = attributes[attr_name] 

213 attribute_list.append(attr_name) 

214 # Create a new DocumentStructure for each attribute and add contents. 

215 attribute_doc = DocumentStructure(attr_name, target='html') 

216 breadcrumb_section = attribute_doc.add_new_section('breadcrumb') 

217 breadcrumb_section.style.ref(self._resource_class_name, 'index') 

218 breadcrumb_section.write(f' / Attribute / {attr_name}') 

219 attribute_doc.add_title_section(attr_name) 

220 attribute_section = attribute_doc.add_new_section( 

221 attr_name, 

222 context={'qualifier': f'{self.class_name}.'}, 

223 ) 

224 document_attribute( 

225 section=attribute_section, 

226 service_name=self._service_name, 

227 resource_name=self._resource_name, 

228 attr_name=attr_name, 

229 event_emitter=self._resource.meta.client.meta.events, 

230 attr_model=attr_shape, 

231 ) 

232 # Write attributes in individual/nested files. 

233 # Path: <root>/reference/services/<service>/<resource_name>/<attribute_name>.rst 

234 attributes_dir_path = os.path.join( 

235 self._root_docs_path, 

236 f'{self._service_name}', 

237 f'{self._resource_sub_path}', 

238 ) 

239 attribute_doc.write_to_file(attributes_dir_path, attr_name) 

240 if attributes: 

241 self._add_overview_of_member_type(section, 'attributes') 

242 

243 def _add_references(self, section): 

244 section = section.add_new_section('references') 

245 references = self._resource.meta.resource_model.references 

246 reference_list = [] 

247 if references: 

248 add_resource_type_overview( 

249 section=section, 

250 resource_type='References', 

251 description=( 

252 'References are related resource instances that have ' 

253 'a belongs-to relationship.' 

254 ), 

255 intro_link='references_intro', 

256 ) 

257 self.member_map['references'] = reference_list 

258 self._add_overview_of_member_type(section, 'references') 

259 for reference in references: 

260 reference_list.append(reference.name) 

261 # Create a new DocumentStructure for each reference and add contents. 

262 reference_doc = DocumentStructure(reference.name, target='html') 

263 breadcrumb_section = reference_doc.add_new_section('breadcrumb') 

264 breadcrumb_section.style.ref(self._resource_class_name, 'index') 

265 breadcrumb_section.write(f' / Reference / {reference.name}') 

266 reference_doc.add_title_section(reference.name) 

267 reference_section = reference_doc.add_new_section( 

268 reference.name, 

269 context={'qualifier': f'{self.class_name}.'}, 

270 ) 

271 document_reference( 

272 section=reference_section, 

273 reference_model=reference, 

274 ) 

275 # Write references in individual/nested files. 

276 # Path: <root>/reference/services/<service>/<resource_name>/<reference_name>.rst 

277 references_dir_path = os.path.join( 

278 self._root_docs_path, 

279 f'{self._service_name}', 

280 f'{self._resource_sub_path}', 

281 ) 

282 reference_doc.write_to_file(references_dir_path, reference.name) 

283 if references: 

284 self._add_overview_of_member_type(section, 'references') 

285 

286 def _add_actions(self, section): 

287 section = section.add_new_section('actions') 

288 actions = self._resource.meta.resource_model.actions 

289 if actions: 

290 documenter = ActionDocumenter(self._resource, self._root_docs_path) 

291 documenter.member_map = self.member_map 

292 documenter.document_actions(section) 

293 self._add_overview_of_member_type(section, 'actions') 

294 

295 def _add_sub_resources(self, section): 

296 section = section.add_new_section('sub-resources') 

297 sub_resources = self._resource.meta.resource_model.subresources 

298 if sub_resources: 

299 documenter = SubResourceDocumenter( 

300 self._resource, self._root_docs_path 

301 ) 

302 documenter.member_map = self.member_map 

303 documenter.document_sub_resources(section) 

304 self._add_overview_of_member_type(section, 'sub-resources') 

305 

306 def _add_collections(self, section): 

307 section = section.add_new_section('collections') 

308 collections = self._resource.meta.resource_model.collections 

309 if collections: 

310 documenter = CollectionDocumenter( 

311 self._resource, self._root_docs_path 

312 ) 

313 documenter.member_map = self.member_map 

314 documenter.document_collections(section) 

315 self._add_overview_of_member_type(section, 'collections') 

316 

317 def _add_waiters(self, section): 

318 section = section.add_new_section('waiters') 

319 waiters = self._resource.meta.resource_model.waiters 

320 if waiters: 

321 service_waiter_model = self._botocore_session.get_waiter_model( 

322 self._service_name 

323 ) 

324 documenter = WaiterResourceDocumenter( 

325 self._resource, service_waiter_model, self._root_docs_path 

326 ) 

327 documenter.member_map = self.member_map 

328 documenter.document_resource_waiters(section) 

329 self._add_overview_of_member_type(section, 'waiters') 

330 

331 def _add_resource_note(self, section): 

332 section = section.add_new_section('feature-freeze') 

333 section.style.start_note() 

334 section.write( 

335 "Before using anything on this page, please refer to the resources " 

336 ":doc:`user guide <../../../../guide/resources>` for the most recent " 

337 "guidance on using resources." 

338 ) 

339 section.style.end_note() 

340 

341 

342class ServiceResourceDocumenter(ResourceDocumenter): 

343 @property 

344 def class_name(self): 

345 return f'{self._service_docs_name}.ServiceResource' 

346 

347 def _add_title(self, section): 

348 title_section = section.add_new_section('title') 

349 title_section.style.h2('Service Resource') 

350 

351 def _add_description(self, section): 

352 official_service_name = get_official_service_name(self._service_model) 

353 section.write(f'A resource representing {official_service_name}') 

354 

355 def _add_example(self, section, identifier_names): 

356 section.style.start_codeblock() 

357 section.style.new_line() 

358 section.write('import boto3') 

359 section.style.new_line() 

360 section.style.new_line() 

361 section.write( 

362 f'{self._service_name} = boto3.resource(\'{self._service_name}\')' 

363 ) 

364 section.style.end_codeblock()