python-openstackclient 8.3.0__py3-none-any.whl → 10.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (292) hide show
  1. openstackclient/__init__.py +2 -6
  2. openstackclient/api/api.py +41 -23
  3. openstackclient/api/compute_v2.py +44 -25
  4. openstackclient/api/object_store_v1.py +75 -97
  5. openstackclient/api/volume_v2.py +2 -1
  6. openstackclient/api/volume_v3.py +2 -1
  7. openstackclient/common/availability_zone.py +58 -42
  8. openstackclient/common/clientmanager.py +56 -29
  9. openstackclient/common/configuration.py +10 -3
  10. openstackclient/common/envvars.py +2 -2
  11. openstackclient/common/extension.py +14 -5
  12. openstackclient/common/limits.py +10 -5
  13. openstackclient/common/module.py +14 -6
  14. openstackclient/common/pagination.py +8 -2
  15. openstackclient/common/progressbar.py +7 -6
  16. openstackclient/common/project_cleanup.py +13 -7
  17. openstackclient/common/quota.py +126 -114
  18. openstackclient/common/versions.py +8 -2
  19. openstackclient/compute/client.py +7 -3
  20. openstackclient/compute/v2/agent.py +17 -10
  21. openstackclient/compute/v2/aggregate.py +36 -22
  22. openstackclient/compute/v2/console.py +14 -8
  23. openstackclient/compute/v2/console_connection.py +11 -3
  24. openstackclient/compute/v2/flavor.py +39 -21
  25. openstackclient/compute/v2/host.py +14 -6
  26. openstackclient/compute/v2/hypervisor.py +14 -5
  27. openstackclient/compute/v2/hypervisor_stats.py +10 -2
  28. openstackclient/compute/v2/keypair.py +29 -14
  29. openstackclient/compute/v2/server.py +251 -171
  30. openstackclient/compute/v2/server_backup.py +10 -4
  31. openstackclient/compute/v2/server_event.py +21 -12
  32. openstackclient/compute/v2/server_group.py +21 -11
  33. openstackclient/compute/v2/server_image.py +19 -10
  34. openstackclient/compute/v2/server_migration.py +24 -10
  35. openstackclient/compute/v2/server_share.py +274 -0
  36. openstackclient/compute/v2/server_volume.py +10 -4
  37. openstackclient/compute/v2/service.py +14 -7
  38. openstackclient/compute/v2/usage.py +26 -21
  39. openstackclient/identity/client.py +8 -3
  40. openstackclient/identity/common.py +103 -41
  41. openstackclient/identity/v2_0/catalog.py +14 -7
  42. openstackclient/identity/v2_0/ec2creds.py +21 -10
  43. openstackclient/identity/v2_0/endpoint.py +23 -11
  44. openstackclient/identity/v2_0/project.py +25 -14
  45. openstackclient/identity/v2_0/role.py +28 -14
  46. openstackclient/identity/v2_0/role_assignment.py +9 -3
  47. openstackclient/identity/v2_0/service.py +26 -12
  48. openstackclient/identity/v2_0/token.py +12 -5
  49. openstackclient/identity/v2_0/user.py +26 -15
  50. openstackclient/identity/v3/access_rule.py +26 -12
  51. openstackclient/identity/v3/application_credential.py +59 -24
  52. openstackclient/identity/v3/catalog.py +14 -7
  53. openstackclient/identity/v3/consumer.py +22 -11
  54. openstackclient/identity/v3/credential.py +36 -16
  55. openstackclient/identity/v3/domain.py +37 -18
  56. openstackclient/identity/v3/ec2creds.py +25 -12
  57. openstackclient/identity/v3/endpoint.py +42 -20
  58. openstackclient/identity/v3/endpoint_group.py +28 -17
  59. openstackclient/identity/v3/federation_protocol.py +71 -50
  60. openstackclient/identity/v3/group.py +55 -32
  61. openstackclient/identity/v3/identity_provider.py +92 -57
  62. openstackclient/identity/v3/implied_role.py +21 -9
  63. openstackclient/identity/v3/limit.py +115 -92
  64. openstackclient/identity/v3/mapping.py +26 -13
  65. openstackclient/identity/v3/policy.py +23 -12
  66. openstackclient/identity/v3/project.py +211 -122
  67. openstackclient/identity/v3/region.py +36 -16
  68. openstackclient/identity/v3/registered_limit.py +116 -109
  69. openstackclient/identity/v3/role.py +61 -31
  70. openstackclient/identity/v3/role_assignment.py +23 -6
  71. openstackclient/identity/v3/service.py +36 -16
  72. openstackclient/identity/v3/service_provider.py +37 -15
  73. openstackclient/identity/v3/tag.py +23 -17
  74. openstackclient/identity/v3/token.py +30 -14
  75. openstackclient/identity/v3/trust.py +32 -14
  76. openstackclient/identity/v3/unscoped_saml.py +10 -2
  77. openstackclient/identity/v3/user.py +49 -26
  78. openstackclient/image/client.py +7 -3
  79. openstackclient/image/v1/image.py +33 -26
  80. openstackclient/image/v2/cache.py +14 -9
  81. openstackclient/image/v2/image.py +76 -49
  82. openstackclient/image/v2/info.py +7 -1
  83. openstackclient/image/v2/metadef_namespaces.py +109 -13
  84. openstackclient/image/v2/metadef_objects.py +28 -15
  85. openstackclient/image/v2/metadef_properties.py +24 -13
  86. openstackclient/image/v2/metadef_resource_type_association.py +14 -7
  87. openstackclient/image/v2/metadef_resource_types.py +7 -1
  88. openstackclient/image/v2/task.py +15 -6
  89. openstackclient/locale/tr_TR/LC_MESSAGES/openstackclient.po +7 -192
  90. openstackclient/network/client.py +7 -2
  91. openstackclient/network/common.py +16 -241
  92. openstackclient/network/utils.py +36 -22
  93. openstackclient/network/v2/address_group.py +27 -16
  94. openstackclient/network/v2/address_scope.py +24 -13
  95. openstackclient/network/v2/bgpvpn/bgpvpn.py +463 -0
  96. openstackclient/network/v2/bgpvpn/constants.py +30 -0
  97. openstackclient/network/v2/bgpvpn/network_association.py +214 -0
  98. openstackclient/network/v2/bgpvpn/port_association.py +490 -0
  99. openstackclient/network/v2/bgpvpn/router_association.py +288 -0
  100. openstackclient/network/v2/default_security_group_rule.py +19 -10
  101. openstackclient/network/v2/floating_ip.py +110 -159
  102. openstackclient/network/v2/floating_ip_port_forwarding.py +30 -18
  103. openstackclient/network/v2/fwaas/__init__.py +0 -0
  104. openstackclient/network/v2/fwaas/group.py +466 -0
  105. openstackclient/network/v2/fwaas/policy.py +518 -0
  106. openstackclient/network/v2/fwaas/rule.py +574 -0
  107. openstackclient/network/v2/ip_availability.py +13 -5
  108. openstackclient/network/v2/l3_conntrack_helper.py +22 -13
  109. openstackclient/network/v2/local_ip.py +24 -13
  110. openstackclient/network/v2/local_ip_association.py +14 -7
  111. openstackclient/network/v2/ndp_proxy.py +20 -11
  112. openstackclient/network/v2/network.py +129 -196
  113. openstackclient/network/v2/network_agent.py +46 -25
  114. openstackclient/network/v2/network_auto_allocated_topology.py +22 -11
  115. openstackclient/network/v2/network_flavor.py +27 -16
  116. openstackclient/network/v2/network_flavor_profile.py +23 -12
  117. openstackclient/network/v2/network_meter.py +21 -10
  118. openstackclient/network/v2/network_meter_rule.py +21 -11
  119. openstackclient/network/v2/network_qos_policy.py +25 -15
  120. openstackclient/network/v2/network_qos_rule.py +32 -17
  121. openstackclient/network/v2/network_qos_rule_type.py +13 -5
  122. openstackclient/network/v2/network_rbac.py +23 -12
  123. openstackclient/network/v2/network_segment.py +20 -11
  124. openstackclient/network/v2/network_segment_range.py +56 -29
  125. openstackclient/network/v2/network_service_provider.py +7 -1
  126. openstackclient/network/v2/network_trunk.py +38 -22
  127. openstackclient/network/v2/port.py +54 -29
  128. openstackclient/network/v2/router.py +75 -52
  129. openstackclient/network/v2/security_group.py +87 -157
  130. openstackclient/network/v2/security_group_rule.py +100 -280
  131. openstackclient/network/v2/subnet.py +49 -28
  132. openstackclient/network/v2/subnet_pool.py +30 -17
  133. openstackclient/network/v2/taas/tap_flow.py +22 -11
  134. openstackclient/network/v2/taas/tap_mirror.py +22 -11
  135. openstackclient/network/v2/taas/tap_service.py +23 -12
  136. openstackclient/object/client.py +7 -2
  137. openstackclient/object/v1/account.py +13 -6
  138. openstackclient/object/v1/container.py +25 -15
  139. openstackclient/object/v1/object.py +25 -15
  140. openstackclient/py.typed +0 -0
  141. openstackclient/shell.py +46 -10
  142. openstackclient/tests/functional/base.py +55 -20
  143. openstackclient/tests/functional/common/test_extension.py +4 -0
  144. openstackclient/tests/functional/common/test_quota.py +3 -1
  145. openstackclient/tests/functional/compute/v2/common.py +14 -13
  146. openstackclient/tests/functional/compute/v2/test_flavor.py +3 -1
  147. openstackclient/tests/functional/compute/v2/test_server.py +3 -0
  148. openstackclient/tests/functional/identity/v2/common.py +10 -6
  149. openstackclient/tests/functional/identity/v2/test_role.py +4 -4
  150. openstackclient/tests/functional/identity/v3/common.py +25 -19
  151. openstackclient/tests/functional/identity/v3/test_group.py +20 -20
  152. openstackclient/tests/functional/identity/v3/test_idp.py +3 -1
  153. openstackclient/tests/functional/identity/v3/test_limit.py +47 -0
  154. openstackclient/tests/functional/identity/v3/test_project.py +10 -10
  155. openstackclient/tests/functional/identity/v3/test_role.py +18 -18
  156. openstackclient/tests/functional/identity/v3/test_role_assignment.py +12 -12
  157. openstackclient/tests/functional/identity/v3/test_user.py +8 -8
  158. openstackclient/tests/functional/image/base.py +1 -6
  159. openstackclient/tests/functional/image/v2/test_metadef_objects.py +69 -0
  160. openstackclient/tests/functional/network/v2/common.py +5 -2
  161. openstackclient/tests/functional/network/v2/test_floating_ip.py +10 -4
  162. openstackclient/tests/functional/network/v2/test_ip_availability.py +4 -0
  163. openstackclient/tests/functional/network/v2/test_network_meter_rule.py +3 -2
  164. openstackclient/tests/functional/network/v2/test_network_segment.py +5 -0
  165. openstackclient/tests/functional/network/v2/test_subnet.py +13 -9
  166. openstackclient/tests/functional/object/v1/common.py +4 -0
  167. openstackclient/tests/functional/volume/v2/common.py +4 -0
  168. openstackclient/tests/functional/volume/v2/test_volume_snapshot.py +27 -11
  169. openstackclient/tests/functional/volume/v2/test_volume_type.py +2 -2
  170. openstackclient/tests/functional/volume/v3/common.py +4 -0
  171. openstackclient/tests/functional/volume/v3/test_volume_snapshot.py +56 -138
  172. openstackclient/tests/functional/volume/v3/test_volume_type.py +2 -2
  173. openstackclient/tests/unit/common/test_availability_zone.py +35 -49
  174. openstackclient/tests/unit/common/test_extension.py +2 -2
  175. openstackclient/tests/unit/common/test_module.py +12 -7
  176. openstackclient/tests/unit/common/test_project_cleanup.py +3 -1
  177. openstackclient/tests/unit/common/test_quota.py +62 -23
  178. openstackclient/tests/unit/compute/v2/fakes.py +25 -0
  179. openstackclient/tests/unit/compute/v2/test_flavor.py +28 -2
  180. openstackclient/tests/unit/compute/v2/test_keypair.py +6 -6
  181. openstackclient/tests/unit/compute/v2/test_server.py +17 -104
  182. openstackclient/tests/unit/compute/v2/test_server_share.py +287 -0
  183. openstackclient/tests/unit/identity/v3/fakes.py +3 -0
  184. openstackclient/tests/unit/identity/v3/test_group.py +4 -14
  185. openstackclient/tests/unit/identity/v3/test_identity_provider.py +303 -299
  186. openstackclient/tests/unit/identity/v3/test_limit.py +197 -145
  187. openstackclient/tests/unit/identity/v3/test_project.py +831 -512
  188. openstackclient/tests/unit/identity/v3/test_protocol.py +97 -88
  189. openstackclient/tests/unit/identity/v3/test_registered_limit.py +355 -220
  190. openstackclient/tests/unit/identity/v3/test_user.py +4 -4
  191. openstackclient/tests/unit/image/v2/test_image.py +16 -16
  192. openstackclient/tests/unit/image/v2/test_metadef_namespaces.py +105 -6
  193. openstackclient/tests/unit/network/test_common.py +0 -155
  194. openstackclient/tests/unit/network/v2/bgpvpn/__init__.py +0 -0
  195. openstackclient/tests/unit/network/v2/bgpvpn/fakes.py +179 -0
  196. openstackclient/tests/unit/network/v2/bgpvpn/test_bgpvpn.py +584 -0
  197. openstackclient/tests/unit/network/v2/bgpvpn/test_network_association.py +285 -0
  198. openstackclient/tests/unit/network/v2/bgpvpn/test_port_association.py +384 -0
  199. openstackclient/tests/unit/network/v2/bgpvpn/test_router_association.py +297 -0
  200. openstackclient/tests/unit/network/v2/fwaas/__init__.py +0 -0
  201. openstackclient/tests/unit/network/v2/fwaas/test_group.py +897 -0
  202. openstackclient/tests/unit/network/v2/fwaas/test_policy.py +869 -0
  203. openstackclient/tests/unit/network/v2/fwaas/test_rule.py +980 -0
  204. openstackclient/tests/unit/network/v2/taas/{test_osc_tap_flow.py → test_tap_flow.py} +18 -25
  205. openstackclient/tests/unit/network/v2/taas/{test_osc_tap_mirror.py → test_tap_mirror.py} +19 -29
  206. openstackclient/tests/unit/network/v2/taas/{test_osc_tap_service.py → test_tap_service.py} +19 -29
  207. openstackclient/tests/unit/network/v2/test_address_group.py +2 -2
  208. openstackclient/tests/unit/network/v2/{test_floating_ip_network.py → test_floating_ip.py} +3 -2
  209. openstackclient/tests/unit/network/v2/test_floating_ip_port_forwarding.py +13 -13
  210. openstackclient/tests/unit/network/v2/test_network_agent.py +8 -4
  211. openstackclient/tests/unit/network/v2/test_network_auto_allocated_topology.py +3 -3
  212. openstackclient/tests/unit/network/v2/test_network_flavor.py +2 -2
  213. openstackclient/tests/unit/network/v2/test_network_qos_policy.py +1 -1
  214. openstackclient/tests/unit/network/v2/test_network_qos_rule.py +2 -2
  215. openstackclient/tests/unit/network/v2/test_network_rbac.py +1 -1
  216. openstackclient/tests/unit/network/v2/test_network_segment.py +1 -1
  217. openstackclient/tests/unit/network/v2/test_network_segment_range.py +7 -10
  218. openstackclient/tests/unit/network/v2/test_network_trunk.py +1 -1
  219. openstackclient/tests/unit/network/v2/test_router.py +8 -9
  220. openstackclient/tests/unit/network/v2/{test_security_group_network.py → test_security_group.py} +1 -20
  221. openstackclient/tests/unit/network/v2/{test_security_group_rule_network.py → test_security_group_rule.py} +7 -41
  222. openstackclient/tests/unit/network/v2/test_subnet.py +2 -1
  223. openstackclient/tests/unit/network/v2/test_subnet_pool.py +2 -1
  224. openstackclient/tests/unit/object/v1/fakes.py +8 -7
  225. openstackclient/tests/unit/object/v1/test_container.py +65 -101
  226. openstackclient/tests/unit/object/v1/test_container_all.py +8 -1
  227. openstackclient/tests/unit/object/v1/test_object.py +44 -84
  228. openstackclient/tests/unit/object/v1/test_object_all.py +8 -1
  229. openstackclient/tests/unit/test_hacking.py +108 -0
  230. openstackclient/tests/unit/volume/v2/fakes.py +1 -0
  231. openstackclient/tests/unit/volume/v2/test_consistency_group.py +8 -2
  232. openstackclient/tests/unit/volume/v2/test_volume.py +7 -6
  233. openstackclient/tests/unit/volume/v2/test_volume_backup.py +1 -5
  234. openstackclient/tests/unit/volume/v2/test_volume_snapshot.py +2 -1
  235. openstackclient/tests/unit/volume/v2/test_volume_type.py +2 -4
  236. openstackclient/tests/unit/volume/v3/fakes.py +1 -0
  237. openstackclient/tests/unit/volume/v3/test_volume.py +94 -15
  238. openstackclient/tests/unit/volume/v3/test_volume_attachment.py +1 -1
  239. openstackclient/tests/unit/volume/v3/test_volume_backup.py +1 -5
  240. openstackclient/tests/unit/volume/v3/test_volume_snapshot.py +55 -1
  241. openstackclient/tests/unit/volume/v3/test_volume_type.py +2 -4
  242. openstackclient/volume/client.py +7 -3
  243. openstackclient/volume/v2/backup_record.py +15 -6
  244. openstackclient/volume/v2/consistency_group.py +37 -25
  245. openstackclient/volume/v2/consistency_group_snapshot.py +27 -12
  246. openstackclient/volume/v2/qos_specs.py +30 -19
  247. openstackclient/volume/v2/service.py +17 -6
  248. openstackclient/volume/v2/volume.py +69 -34
  249. openstackclient/volume/v2/volume_backend.py +19 -6
  250. openstackclient/volume/v2/volume_backup.py +48 -22
  251. openstackclient/volume/v2/volume_host.py +6 -4
  252. openstackclient/volume/v2/volume_snapshot.py +52 -26
  253. openstackclient/volume/v2/volume_transfer_request.py +33 -15
  254. openstackclient/volume/v2/volume_type.py +46 -27
  255. openstackclient/volume/v3/block_storage_cleanup.py +11 -3
  256. openstackclient/volume/v3/block_storage_cluster.py +19 -7
  257. openstackclient/volume/v3/block_storage_log_level.py +15 -6
  258. openstackclient/volume/v3/block_storage_manage.py +10 -4
  259. openstackclient/volume/v3/block_storage_resource_filter.py +17 -5
  260. openstackclient/volume/v3/service.py +16 -6
  261. openstackclient/volume/v3/volume.py +103 -46
  262. openstackclient/volume/v3/volume_attachment.py +43 -21
  263. openstackclient/volume/v3/volume_backup.py +55 -26
  264. openstackclient/volume/v3/volume_group.py +23 -13
  265. openstackclient/volume/v3/volume_group_snapshot.py +32 -13
  266. openstackclient/volume/v3/volume_group_type.py +26 -13
  267. openstackclient/volume/v3/volume_message.py +15 -7
  268. openstackclient/volume/v3/volume_snapshot.py +71 -34
  269. openstackclient/volume/v3/volume_transfer_request.py +33 -15
  270. openstackclient/volume/v3/volume_type.py +45 -27
  271. {python_openstackclient-8.3.0.dist-info → python_openstackclient-10.0.0.dist-info}/METADATA +6 -6
  272. {python_openstackclient-8.3.0.dist-info → python_openstackclient-10.0.0.dist-info}/RECORD +279 -267
  273. {python_openstackclient-8.3.0.dist-info → python_openstackclient-10.0.0.dist-info}/WHEEL +1 -1
  274. {python_openstackclient-8.3.0.dist-info → python_openstackclient-10.0.0.dist-info}/entry_points.txt +53 -1
  275. {python_openstackclient-8.3.0.dist-info → python_openstackclient-10.0.0.dist-info}/licenses/AUTHORS +9 -0
  276. python_openstackclient-10.0.0.dist-info/pbr.json +1 -0
  277. openstackclient/api/image_v1.py +0 -69
  278. openstackclient/api/image_v2.py +0 -79
  279. openstackclient/network/v2/floating_ip_pool.py +0 -38
  280. openstackclient/tests/functional/image/v1/test_image.py +0 -97
  281. openstackclient/tests/unit/api/test_image_v1.py +0 -96
  282. openstackclient/tests/unit/api/test_image_v2.py +0 -96
  283. openstackclient/tests/unit/network/v2/test_floating_ip_compute.py +0 -248
  284. openstackclient/tests/unit/network/v2/test_floating_ip_pool_compute.py +0 -49
  285. openstackclient/tests/unit/network/v2/test_floating_ip_pool_network.py +0 -39
  286. openstackclient/tests/unit/network/v2/test_network_compute.py +0 -404
  287. openstackclient/tests/unit/network/v2/test_security_group_compute.py +0 -392
  288. openstackclient/tests/unit/network/v2/test_security_group_rule_compute.py +0 -555
  289. python_openstackclient-8.3.0.dist-info/pbr.json +0 -1
  290. /openstackclient/{tests/functional/image/v1 → network/v2/bgpvpn}/__init__.py +0 -0
  291. {python_openstackclient-8.3.0.dist-info → python_openstackclient-10.0.0.dist-info}/licenses/LICENSE +0 -0
  292. {python_openstackclient-8.3.0.dist-info → python_openstackclient-10.0.0.dist-info}/top_level.txt +0 -0
@@ -14,6 +14,11 @@
14
14
 
15
15
  """Storage backend action implementations"""
16
16
 
17
+ import argparse
18
+ from collections.abc import Iterable, Sequence
19
+ from typing import Any
20
+
21
+ from openstack import utils as sdk_utils
17
22
  from osc_lib.cli import format_columns
18
23
  from osc_lib import utils
19
24
 
@@ -24,7 +29,7 @@ from openstackclient.i18n import _
24
29
  class ShowCapability(command.Lister):
25
30
  _description = _("Show capability command")
26
31
 
27
- def get_parser(self, prog_name):
32
+ def get_parser(self, prog_name: str) -> argparse.ArgumentParser:
28
33
  parser = super().get_parser(prog_name)
29
34
  parser.add_argument(
30
35
  "host",
@@ -33,8 +38,12 @@ class ShowCapability(command.Lister):
33
38
  )
34
39
  return parser
35
40
 
36
- def take_action(self, parsed_args):
37
- volume_client = self.app.client_manager.sdk_connection.volume
41
+ def take_action(
42
+ self, parsed_args: argparse.Namespace
43
+ ) -> tuple[Sequence[str], Iterable[tuple[Any, ...]]]:
44
+ volume_client = sdk_utils.ensure_service_version(
45
+ self.app.client_manager.sdk_connection.volume, '2'
46
+ )
38
47
 
39
48
  columns = [
40
49
  'Title',
@@ -71,7 +80,7 @@ class ShowCapability(command.Lister):
71
80
  class ListPool(command.Lister):
72
81
  _description = _("List pool command")
73
82
 
74
- def get_parser(self, prog_name):
83
+ def get_parser(self, prog_name: str) -> argparse.ArgumentParser:
75
84
  parser = super().get_parser(prog_name)
76
85
  parser.add_argument(
77
86
  "--long",
@@ -83,8 +92,12 @@ class ListPool(command.Lister):
83
92
  # able to pass in --filters with a <key>=<value> pair to filter on.
84
93
  return parser
85
94
 
86
- def take_action(self, parsed_args):
87
- volume_client = self.app.client_manager.sdk_connection.volume
95
+ def take_action(
96
+ self, parsed_args: argparse.Namespace
97
+ ) -> tuple[Sequence[str], Iterable[tuple[Any, ...]]]:
98
+ volume_client = sdk_utils.ensure_service_version(
99
+ self.app.client_manager.sdk_connection.volume, '2'
100
+ )
88
101
 
89
102
  if parsed_args.long:
90
103
  columns = [
@@ -14,10 +14,14 @@
14
14
 
15
15
  """Volume v2 Backup action implementations"""
16
16
 
17
+ import argparse
17
18
  import functools
18
19
  import logging
20
+ from collections.abc import Iterable, Sequence
21
+ from typing import Any
19
22
 
20
23
  from cliff import columns as cliff_columns
24
+ from openstack import utils as sdk_utils
21
25
  from osc_lib import exceptions
22
26
  from osc_lib import utils
23
27
 
@@ -39,11 +43,13 @@ class VolumeIdColumn(cliff_columns.FormattableColumn[str]):
39
43
  ``functools.partial(VolumeIdColumn, volume_cache)``.
40
44
  """
41
45
 
42
- def __init__(self, value, volume_cache=None):
46
+ def __init__(
47
+ self, value: str, volume_cache: dict[str, Any] | None = None
48
+ ) -> None:
43
49
  super().__init__(value)
44
50
  self._volume_cache = volume_cache or {}
45
51
 
46
- def human_readable(self):
52
+ def human_readable(self) -> str:
47
53
  """Return a volume name if available
48
54
 
49
55
  :rtype: either the volume ID or name
@@ -58,7 +64,7 @@ class VolumeIdColumn(cliff_columns.FormattableColumn[str]):
58
64
  class CreateVolumeBackup(command.ShowOne):
59
65
  _description = _("Create new volume backup")
60
66
 
61
- def get_parser(self, prog_name):
67
+ def get_parser(self, prog_name: str) -> argparse.ArgumentParser:
62
68
  parser = super().get_parser(prog_name)
63
69
  parser.add_argument(
64
70
  "volume",
@@ -102,8 +108,12 @@ class CreateVolumeBackup(command.ShowOne):
102
108
  )
103
109
  return parser
104
110
 
105
- def take_action(self, parsed_args):
106
- volume_client = self.app.client_manager.sdk_connection.volume
111
+ def take_action(
112
+ self, parsed_args: argparse.Namespace
113
+ ) -> tuple[Sequence[str], Iterable[Any]]:
114
+ volume_client = sdk_utils.ensure_service_version(
115
+ self.app.client_manager.sdk_connection.volume, '2'
116
+ )
107
117
 
108
118
  volume_id = volume_client.find_volume(
109
119
  parsed_args.volume,
@@ -139,7 +149,7 @@ class CreateVolumeBackup(command.ShowOne):
139
149
  class DeleteVolumeBackup(command.Command):
140
150
  _description = _("Delete volume backup(s)")
141
151
 
142
- def get_parser(self, prog_name):
152
+ def get_parser(self, prog_name: str) -> argparse.ArgumentParser:
143
153
  parser = super().get_parser(prog_name)
144
154
  parser.add_argument(
145
155
  "backups",
@@ -155,8 +165,10 @@ class DeleteVolumeBackup(command.Command):
155
165
  )
156
166
  return parser
157
167
 
158
- def take_action(self, parsed_args):
159
- volume_client = self.app.client_manager.sdk_connection.volume
168
+ def take_action(self, parsed_args: argparse.Namespace) -> None:
169
+ volume_client = sdk_utils.ensure_service_version(
170
+ self.app.client_manager.sdk_connection.volume, '2'
171
+ )
160
172
  result = 0
161
173
 
162
174
  for backup in parsed_args.backups:
@@ -175,8 +187,8 @@ class DeleteVolumeBackup(command.Command):
175
187
  _(
176
188
  "Failed to delete backup with "
177
189
  "name or ID '%(backup)s': %(e)s"
178
- )
179
- % {'backup': backup, 'e': e}
190
+ ),
191
+ {'backup': backup, 'e': e},
180
192
  )
181
193
 
182
194
  if result > 0:
@@ -191,7 +203,7 @@ class DeleteVolumeBackup(command.Command):
191
203
  class ListVolumeBackup(command.Lister):
192
204
  _description = _("List volume backups")
193
205
 
194
- def get_parser(self, prog_name):
206
+ def get_parser(self, prog_name: str) -> argparse.ArgumentParser:
195
207
  parser = super().get_parser(prog_name)
196
208
  parser.add_argument(
197
209
  "--long",
@@ -237,8 +249,12 @@ class ListVolumeBackup(command.Lister):
237
249
  )
238
250
  return parser
239
251
 
240
- def take_action(self, parsed_args):
241
- volume_client = self.app.client_manager.sdk_connection.volume
252
+ def take_action(
253
+ self, parsed_args: argparse.Namespace
254
+ ) -> tuple[Sequence[str], Iterable[tuple[Any, ...]]]:
255
+ volume_client = sdk_utils.ensure_service_version(
256
+ self.app.client_manager.sdk_connection.volume, '2'
257
+ )
242
258
 
243
259
  columns: tuple[str, ...] = (
244
260
  'id',
@@ -324,7 +340,7 @@ class ListVolumeBackup(command.Lister):
324
340
  class RestoreVolumeBackup(command.ShowOne):
325
341
  _description = _("Restore volume backup")
326
342
 
327
- def get_parser(self, prog_name):
343
+ def get_parser(self, prog_name: str) -> argparse.ArgumentParser:
328
344
  parser = super().get_parser(prog_name)
329
345
  parser.add_argument(
330
346
  "backup",
@@ -350,8 +366,12 @@ class RestoreVolumeBackup(command.ShowOne):
350
366
  )
351
367
  return parser
352
368
 
353
- def take_action(self, parsed_args):
354
- volume_client = self.app.client_manager.sdk_connection.volume
369
+ def take_action(
370
+ self, parsed_args: argparse.Namespace
371
+ ) -> tuple[Sequence[str], Iterable[Any]]:
372
+ volume_client = sdk_utils.ensure_service_version(
373
+ self.app.client_manager.sdk_connection.volume, '2'
374
+ )
355
375
 
356
376
  backup = volume_client.find_backup(
357
377
  parsed_args.backup,
@@ -396,7 +416,7 @@ class RestoreVolumeBackup(command.ShowOne):
396
416
  class SetVolumeBackup(command.Command):
397
417
  _description = _("Set volume backup properties")
398
418
 
399
- def get_parser(self, prog_name):
419
+ def get_parser(self, prog_name: str) -> argparse.ArgumentParser:
400
420
  parser = super().get_parser(prog_name)
401
421
  parser.add_argument(
402
422
  "backup",
@@ -416,8 +436,10 @@ class SetVolumeBackup(command.Command):
416
436
  )
417
437
  return parser
418
438
 
419
- def take_action(self, parsed_args):
420
- volume_client = self.app.client_manager.sdk_connection.volume
439
+ def take_action(self, parsed_args: argparse.Namespace) -> None:
440
+ volume_client = sdk_utils.ensure_service_version(
441
+ self.app.client_manager.sdk_connection.volume, '2'
442
+ )
421
443
 
422
444
  backup = volume_client.find_backup(
423
445
  parsed_args.backup,
@@ -442,7 +464,7 @@ class SetVolumeBackup(command.Command):
442
464
  class ShowVolumeBackup(command.ShowOne):
443
465
  _description = _("Display volume backup details")
444
466
 
445
- def get_parser(self, prog_name):
467
+ def get_parser(self, prog_name: str) -> argparse.ArgumentParser:
446
468
  parser = super().get_parser(prog_name)
447
469
  parser.add_argument(
448
470
  "backup",
@@ -451,8 +473,12 @@ class ShowVolumeBackup(command.ShowOne):
451
473
  )
452
474
  return parser
453
475
 
454
- def take_action(self, parsed_args):
455
- volume_client = self.app.client_manager.sdk_connection.volume
476
+ def take_action(
477
+ self, parsed_args: argparse.Namespace
478
+ ) -> tuple[Sequence[str], Iterable[Any]]:
479
+ volume_client = sdk_utils.ensure_service_version(
480
+ self.app.client_manager.sdk_connection.volume, '2'
481
+ )
456
482
  backup = volume_client.find_backup(
457
483
  parsed_args.backup, ignore_missing=False
458
484
  )
@@ -14,6 +14,8 @@
14
14
 
15
15
  """Volume v2 host action implementations"""
16
16
 
17
+ import argparse
18
+
17
19
  from openstackclient import command
18
20
  from openstackclient.i18n import _
19
21
 
@@ -21,7 +23,7 @@ from openstackclient.i18n import _
21
23
  class FailoverVolumeHost(command.Command):
22
24
  _description = _("Failover volume host to different backend")
23
25
 
24
- def get_parser(self, prog_name):
26
+ def get_parser(self, prog_name: str) -> argparse.ArgumentParser:
25
27
  parser = super().get_parser(prog_name)
26
28
  parser.add_argument(
27
29
  "host", metavar="<host-name>", help=_("Name of volume host")
@@ -37,7 +39,7 @@ class FailoverVolumeHost(command.Command):
37
39
  )
38
40
  return parser
39
41
 
40
- def take_action(self, parsed_args):
42
+ def take_action(self, parsed_args: argparse.Namespace) -> None:
41
43
  service_client = self.app.client_manager.volume
42
44
  service_client.services.failover_host(
43
45
  parsed_args.host, parsed_args.volume_backend
@@ -47,7 +49,7 @@ class FailoverVolumeHost(command.Command):
47
49
  class SetVolumeHost(command.Command):
48
50
  _description = _("Set volume host properties")
49
51
 
50
- def get_parser(self, prog_name):
52
+ def get_parser(self, prog_name: str) -> argparse.ArgumentParser:
51
53
  parser = super().get_parser(prog_name)
52
54
  parser.add_argument(
53
55
  "host", metavar="<host-name>", help=_("Name of volume host")
@@ -65,7 +67,7 @@ class SetVolumeHost(command.Command):
65
67
  )
66
68
  return parser
67
69
 
68
- def take_action(self, parsed_args):
70
+ def take_action(self, parsed_args: argparse.Namespace) -> None:
69
71
  service_client = self.app.client_manager.volume
70
72
  if parsed_args.enable:
71
73
  service_client.services.thaw_host(parsed_args.host)
@@ -14,12 +14,15 @@
14
14
 
15
15
  """Volume v2 snapshot action implementations"""
16
16
 
17
+ import argparse
17
18
  import functools
18
19
  import logging
19
- import typing as ty
20
+ from collections.abc import Iterable, Sequence
21
+ from typing import Any
20
22
 
21
23
  from cliff import columns as cliff_columns
22
24
  from openstack.block_storage.v2 import snapshot as _snapshot
25
+ from openstack import utils as sdk_utils
23
26
  from osc_lib.cli import format_columns
24
27
  from osc_lib.cli import parseractions
25
28
  from osc_lib import exceptions
@@ -45,11 +48,13 @@ class VolumeIdColumn(cliff_columns.FormattableColumn[str]):
45
48
  ``functools.partial(VolumeIdColumn, volume_cache)``.
46
49
  """
47
50
 
48
- def __init__(self, value, volume_cache=None):
51
+ def __init__(
52
+ self, value: str, volume_cache: dict[str, Any] | None = None
53
+ ) -> None:
49
54
  super().__init__(value)
50
55
  self._volume_cache = volume_cache or {}
51
56
 
52
- def human_readable(self):
57
+ def human_readable(self) -> str:
53
58
  """Return a volume name if available
54
59
 
55
60
  :rtype: either the volume ID or name
@@ -61,7 +66,7 @@ class VolumeIdColumn(cliff_columns.FormattableColumn[str]):
61
66
  return volume
62
67
 
63
68
 
64
- def _format_snapshot(snapshot: _snapshot.Snapshot) -> dict[str, ty.Any]:
69
+ def _format_snapshot(snapshot: _snapshot.Snapshot) -> dict[str, Any]:
65
70
  # Some columns returned by openstacksdk should not be shown because they're
66
71
  # either irrelevant or duplicates
67
72
  ignored_columns = {
@@ -100,7 +105,7 @@ def _format_snapshot(snapshot: _snapshot.Snapshot) -> dict[str, ty.Any]:
100
105
  class CreateVolumeSnapshot(command.ShowOne):
101
106
  _description = _("Create new volume snapshot")
102
107
 
103
- def get_parser(self, prog_name):
108
+ def get_parser(self, prog_name: str) -> argparse.ArgumentParser:
104
109
  parser = super().get_parser(prog_name)
105
110
  parser.add_argument(
106
111
  "snapshot_name",
@@ -150,8 +155,12 @@ class CreateVolumeSnapshot(command.ShowOne):
150
155
  )
151
156
  return parser
152
157
 
153
- def take_action(self, parsed_args):
154
- volume_client = self.app.client_manager.sdk_connection.volume
158
+ def take_action(
159
+ self, parsed_args: argparse.Namespace
160
+ ) -> tuple[Sequence[str], Iterable[Any]]:
161
+ volume_client = sdk_utils.ensure_service_version(
162
+ self.app.client_manager.sdk_connection.volume, '2'
163
+ )
155
164
 
156
165
  volume = parsed_args.volume
157
166
  if not parsed_args.volume:
@@ -186,13 +195,14 @@ class CreateVolumeSnapshot(command.ShowOne):
186
195
  )
187
196
 
188
197
  data = _format_snapshot(snapshot)
189
- return zip(*sorted(data.items()))
198
+ col_headers, col_data = zip(*sorted(data.items()))
199
+ return col_headers, col_data
190
200
 
191
201
 
192
202
  class DeleteVolumeSnapshot(command.Command):
193
203
  _description = _("Delete volume snapshot(s)")
194
204
 
195
- def get_parser(self, prog_name):
205
+ def get_parser(self, prog_name: str) -> argparse.ArgumentParser:
196
206
  parser = super().get_parser(prog_name)
197
207
  parser.add_argument(
198
208
  "snapshots",
@@ -210,8 +220,10 @@ class DeleteVolumeSnapshot(command.Command):
210
220
  )
211
221
  return parser
212
222
 
213
- def take_action(self, parsed_args):
214
- volume_client = self.app.client_manager.sdk_connection.volume
223
+ def take_action(self, parsed_args: argparse.Namespace) -> None:
224
+ volume_client = sdk_utils.ensure_service_version(
225
+ self.app.client_manager.sdk_connection.volume, '2'
226
+ )
215
227
  result = 0
216
228
 
217
229
  for snapshot in parsed_args.snapshots:
@@ -219,8 +231,11 @@ class DeleteVolumeSnapshot(command.Command):
219
231
  snapshot_id = volume_client.find_snapshot(
220
232
  snapshot, ignore_missing=False
221
233
  ).id
234
+ # FIXME(stephenfin): This parameter is missing from sdk
235
+ # https://review.opendev.org/c/openstack/openstacksdk/+/984529
222
236
  volume_client.delete_snapshot(
223
- snapshot_id, force=parsed_args.force
237
+ snapshot_id,
238
+ force=parsed_args.force, # type: ignore
224
239
  )
225
240
  except Exception as e:
226
241
  result += 1
@@ -228,8 +243,8 @@ class DeleteVolumeSnapshot(command.Command):
228
243
  _(
229
244
  "Failed to delete snapshot with "
230
245
  "name or ID '%(snapshot)s': %(e)s"
231
- )
232
- % {'snapshot': snapshot, 'e': e}
246
+ ),
247
+ {'snapshot': snapshot, 'e': e},
233
248
  )
234
249
 
235
250
  if result > 0:
@@ -244,7 +259,7 @@ class DeleteVolumeSnapshot(command.Command):
244
259
  class ListVolumeSnapshot(command.Lister):
245
260
  _description = _("List volume snapshots")
246
261
 
247
- def get_parser(self, prog_name):
262
+ def get_parser(self, prog_name: str) -> argparse.ArgumentParser:
248
263
  parser = super().get_parser(prog_name)
249
264
  parser.add_argument(
250
265
  '--all-projects',
@@ -295,8 +310,12 @@ class ListVolumeSnapshot(command.Lister):
295
310
  pagination.add_marker_pagination_option_to_parser(parser)
296
311
  return parser
297
312
 
298
- def take_action(self, parsed_args):
299
- volume_client = self.app.client_manager.sdk_connection.volume
313
+ def take_action(
314
+ self, parsed_args: argparse.Namespace
315
+ ) -> tuple[Sequence[str], Iterable[tuple[Any, ...]]]:
316
+ volume_client = sdk_utils.ensure_service_version(
317
+ self.app.client_manager.sdk_connection.volume, '2'
318
+ )
300
319
  identity_client = self.app.client_manager.identity
301
320
 
302
321
  columns: tuple[str, ...] = (
@@ -384,7 +403,7 @@ class ListVolumeSnapshot(command.Lister):
384
403
  class SetVolumeSnapshot(command.Command):
385
404
  _description = _("Set volume snapshot properties")
386
405
 
387
- def get_parser(self, prog_name):
406
+ def get_parser(self, prog_name: str) -> argparse.ArgumentParser:
388
407
  parser = super().get_parser(prog_name)
389
408
  parser.add_argument(
390
409
  'snapshot',
@@ -440,8 +459,10 @@ class SetVolumeSnapshot(command.Command):
440
459
  )
441
460
  return parser
442
461
 
443
- def take_action(self, parsed_args):
444
- volume_client = self.app.client_manager.sdk_connection.volume
462
+ def take_action(self, parsed_args: argparse.Namespace) -> None:
463
+ volume_client = sdk_utils.ensure_service_version(
464
+ self.app.client_manager.sdk_connection.volume, '2'
465
+ )
445
466
 
446
467
  snapshot = volume_client.find_snapshot(
447
468
  parsed_args.snapshot, ignore_missing=False
@@ -499,7 +520,7 @@ class SetVolumeSnapshot(command.Command):
499
520
  class ShowVolumeSnapshot(command.ShowOne):
500
521
  _description = _("Display volume snapshot details")
501
522
 
502
- def get_parser(self, prog_name):
523
+ def get_parser(self, prog_name: str) -> argparse.ArgumentParser:
503
524
  parser = super().get_parser(prog_name)
504
525
  parser.add_argument(
505
526
  "snapshot",
@@ -508,21 +529,26 @@ class ShowVolumeSnapshot(command.ShowOne):
508
529
  )
509
530
  return parser
510
531
 
511
- def take_action(self, parsed_args):
512
- volume_client = self.app.client_manager.sdk_connection.volume
532
+ def take_action(
533
+ self, parsed_args: argparse.Namespace
534
+ ) -> tuple[Sequence[str], Iterable[Any]]:
535
+ volume_client = sdk_utils.ensure_service_version(
536
+ self.app.client_manager.sdk_connection.volume, '2'
537
+ )
513
538
 
514
539
  snapshot = volume_client.find_snapshot(
515
540
  parsed_args.snapshot, ignore_missing=False
516
541
  )
517
542
 
518
543
  data = _format_snapshot(snapshot)
519
- return zip(*sorted(data.items()))
544
+ col_headers, col_data = zip(*sorted(data.items()))
545
+ return col_headers, col_data
520
546
 
521
547
 
522
548
  class UnsetVolumeSnapshot(command.Command):
523
549
  _description = _("Unset volume snapshot properties")
524
550
 
525
- def get_parser(self, prog_name):
551
+ def get_parser(self, prog_name: str) -> argparse.ArgumentParser:
526
552
  parser = super().get_parser(prog_name)
527
553
  parser.add_argument(
528
554
  'snapshot',
@@ -542,7 +568,7 @@ class UnsetVolumeSnapshot(command.Command):
542
568
  )
543
569
  return parser
544
570
 
545
- def take_action(self, parsed_args):
571
+ def take_action(self, parsed_args: argparse.Namespace) -> None:
546
572
  volume_client = self.app.client_manager.sdk_connection.volume
547
573
 
548
574
  snapshot = volume_client.find_snapshot(
@@ -14,7 +14,10 @@
14
14
 
15
15
  """Volume v2 transfer action implementations"""
16
16
 
17
+ import argparse
17
18
  import logging
19
+ from collections.abc import Iterable, Sequence
20
+ from typing import Any
18
21
 
19
22
  from osc_lib import exceptions
20
23
  from osc_lib import utils
@@ -29,7 +32,7 @@ LOG = logging.getLogger(__name__)
29
32
  class AcceptTransferRequest(command.ShowOne):
30
33
  _description = _("Accept volume transfer request.")
31
34
 
32
- def get_parser(self, prog_name):
35
+ def get_parser(self, prog_name: str) -> argparse.ArgumentParser:
33
36
  parser = super().get_parser(prog_name)
34
37
  parser.add_argument(
35
38
  'transfer_request',
@@ -44,7 +47,9 @@ class AcceptTransferRequest(command.ShowOne):
44
47
  )
45
48
  return parser
46
49
 
47
- def take_action(self, parsed_args):
50
+ def take_action(
51
+ self, parsed_args: argparse.Namespace
52
+ ) -> tuple[Sequence[str], Iterable[Any]]:
48
53
  volume_client = self.app.client_manager.volume
49
54
 
50
55
  try:
@@ -62,13 +67,14 @@ class AcceptTransferRequest(command.ShowOne):
62
67
  )
63
68
  transfer_accept._info.pop("links", None)
64
69
 
65
- return zip(*sorted(transfer_accept._info.items()))
70
+ col_headers, col_data = zip(*sorted(transfer_accept._info.items()))
71
+ return col_headers, col_data
66
72
 
67
73
 
68
74
  class CreateTransferRequest(command.ShowOne):
69
75
  _description = _("Create volume transfer request.")
70
76
 
71
- def get_parser(self, prog_name):
77
+ def get_parser(self, prog_name: str) -> argparse.ArgumentParser:
72
78
  parser = super().get_parser(prog_name)
73
79
  parser.add_argument(
74
80
  '--name',
@@ -82,7 +88,9 @@ class CreateTransferRequest(command.ShowOne):
82
88
  )
83
89
  return parser
84
90
 
85
- def take_action(self, parsed_args):
91
+ def take_action(
92
+ self, parsed_args: argparse.Namespace
93
+ ) -> tuple[Sequence[str], Iterable[Any]]:
86
94
  volume_client = self.app.client_manager.volume
87
95
 
88
96
  volume_id = utils.find_resource(
@@ -95,13 +103,16 @@ class CreateTransferRequest(command.ShowOne):
95
103
  )
96
104
  volume_transfer_request._info.pop("links", None)
97
105
 
98
- return zip(*sorted(volume_transfer_request._info.items()))
106
+ col_headers, col_data = zip(
107
+ *sorted(volume_transfer_request._info.items())
108
+ )
109
+ return col_headers, col_data
99
110
 
100
111
 
101
112
  class DeleteTransferRequest(command.Command):
102
113
  _description = _("Delete volume transfer request(s).")
103
114
 
104
- def get_parser(self, prog_name):
115
+ def get_parser(self, prog_name: str) -> argparse.ArgumentParser:
105
116
  parser = super().get_parser(prog_name)
106
117
  parser.add_argument(
107
118
  'transfer_request',
@@ -111,7 +122,7 @@ class DeleteTransferRequest(command.Command):
111
122
  )
112
123
  return parser
113
124
 
114
- def take_action(self, parsed_args):
125
+ def take_action(self, parsed_args: argparse.Namespace) -> None:
115
126
  volume_client = self.app.client_manager.volume
116
127
  result = 0
117
128
 
@@ -128,8 +139,8 @@ class DeleteTransferRequest(command.Command):
128
139
  _(
129
140
  "Failed to delete volume transfer request "
130
141
  "with name or ID '%(transfer)s': %(e)s"
131
- )
132
- % {'transfer': t, 'e': e}
142
+ ),
143
+ {'transfer': t, 'e': e},
133
144
  )
134
145
 
135
146
  if result > 0:
@@ -144,7 +155,7 @@ class DeleteTransferRequest(command.Command):
144
155
  class ListTransferRequest(command.Lister):
145
156
  _description = _("Lists all volume transfer requests.")
146
157
 
147
- def get_parser(self, prog_name):
158
+ def get_parser(self, prog_name: str) -> argparse.ArgumentParser:
148
159
  parser = super().get_parser(prog_name)
149
160
  parser.add_argument(
150
161
  '--all-projects',
@@ -155,7 +166,9 @@ class ListTransferRequest(command.Lister):
155
166
  )
156
167
  return parser
157
168
 
158
- def take_action(self, parsed_args):
169
+ def take_action(
170
+ self, parsed_args: argparse.Namespace
171
+ ) -> tuple[Sequence[str], Iterable[tuple[Any, ...]]]:
159
172
  columns = ['ID', 'Name', 'Volume ID']
160
173
  column_headers = ['ID', 'Name', 'Volume']
161
174
 
@@ -178,7 +191,7 @@ class ListTransferRequest(command.Lister):
178
191
  class ShowTransferRequest(command.ShowOne):
179
192
  _description = _("Show volume transfer request details.")
180
193
 
181
- def get_parser(self, prog_name):
194
+ def get_parser(self, prog_name: str) -> argparse.ArgumentParser:
182
195
  parser = super().get_parser(prog_name)
183
196
  parser.add_argument(
184
197
  'transfer_request',
@@ -187,7 +200,9 @@ class ShowTransferRequest(command.ShowOne):
187
200
  )
188
201
  return parser
189
202
 
190
- def take_action(self, parsed_args):
203
+ def take_action(
204
+ self, parsed_args: argparse.Namespace
205
+ ) -> tuple[Sequence[str], Iterable[Any]]:
191
206
  volume_client = self.app.client_manager.volume
192
207
  volume_transfer_request = utils.find_resource(
193
208
  volume_client.transfers,
@@ -195,4 +210,7 @@ class ShowTransferRequest(command.ShowOne):
195
210
  )
196
211
  volume_transfer_request._info.pop("links", None)
197
212
 
198
- return zip(*sorted(volume_transfer_request._info.items()))
213
+ col_headers, col_data = zip(
214
+ *sorted(volume_transfer_request._info.items())
215
+ )
216
+ return col_headers, col_data