apigeecli 0.53.6__tar.gz → 0.53.8__tar.gz
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.
- {apigeecli-0.53.6/apigeecli.egg-info → apigeecli-0.53.8}/PKG-INFO +27 -34
- {apigeecli-0.53.6 → apigeecli-0.53.8}/README.rst +25 -32
- {apigeecli-0.53.6 → apigeecli-0.53.8}/apigee/__init__.py +14 -16
- {apigeecli-0.53.6 → apigeecli-0.53.8}/apigee/__main__.py +7 -5
- {apigeecli-0.53.6 → apigeecli-0.53.8}/apigee/apiproducts/apiproducts.py +35 -21
- apigeecli-0.53.8/apigee/apiproducts/commands.py +167 -0
- {apigeecli-0.53.6 → apigeecli-0.53.8}/apigee/apiproducts/serializer.py +2 -2
- {apigeecli-0.53.6 → apigeecli-0.53.8}/apigee/apis/api_puller_with_dependency_extraction.py +65 -48
- {apigeecli-0.53.6 → apigeecli-0.53.8}/apigee/apis/apis.py +51 -33
- {apigeecli-0.53.6 → apigeecli-0.53.8}/apigee/apis/commands.py +121 -92
- {apigeecli-0.53.6 → apigeecli-0.53.8}/apigee/apis/deploy.py +34 -56
- {apigeecli-0.53.6 → apigeecli-0.53.8}/apigee/apis/serializer.py +12 -4
- {apigeecli-0.53.6 → apigeecli-0.53.8}/apigee/apps/apps.py +76 -37
- apigeecli-0.53.8/apigee/apps/commands.py +442 -0
- {apigeecli-0.53.6 → apigeecli-0.53.8}/apigee/apps/serializer.py +1 -0
- {apigeecli-0.53.6 → apigeecli-0.53.8}/apigee/auth.py +127 -92
- {apigeecli-0.53.6 → apigeecli-0.53.8}/apigee/backups/backups.py +163 -184
- {apigeecli-0.53.6 → apigeecli-0.53.8}/apigee/backups/commands.py +18 -25
- {apigeecli-0.53.6 → apigeecli-0.53.8}/apigee/caches/caches.py +29 -17
- apigeecli-0.53.8/apigee/caches/commands.py +194 -0
- {apigeecli-0.53.6 → apigeecli-0.53.8}/apigee/caches/serializer.py +1 -0
- {apigeecli-0.53.6 → apigeecli-0.53.8}/apigee/cls.py +4 -1
- {apigeecli-0.53.6 → apigeecli-0.53.8}/apigee/configure/commands.py +3 -1
- {apigeecli-0.53.6 → apigeecli-0.53.8}/apigee/console.py +7 -9
- {apigeecli-0.53.6 → apigeecli-0.53.8}/apigee/crypto.py +12 -11
- {apigeecli-0.53.6 → apigeecli-0.53.8}/apigee/deployments/commands.py +38 -51
- {apigeecli-0.53.6 → apigeecli-0.53.8}/apigee/deployments/deployments.py +10 -8
- apigeecli-0.53.8/apigee/deployments/serializer.py +34 -0
- apigeecli-0.53.8/apigee/developers/commands.py +361 -0
- {apigeecli-0.53.6 → apigeecli-0.53.8}/apigee/developers/developers.py +48 -24
- {apigeecli-0.53.6 → apigeecli-0.53.8}/apigee/developers/serializer.py +3 -1
- {apigeecli-0.53.6 → apigeecli-0.53.8}/apigee/encryption_utils.py +8 -8
- {apigeecli-0.53.6 → apigeecli-0.53.8}/apigee/exceptions.py +2 -1
- {apigeecli-0.53.6 → apigeecli-0.53.8}/apigee/keystores/commands.py +95 -146
- {apigeecli-0.53.6 → apigeecli-0.53.8}/apigee/keystores/keystores.py +32 -16
- {apigeecli-0.53.6 → apigeecli-0.53.8}/apigee/keystores/serializer.py +3 -1
- apigeecli-0.53.8/apigee/keyvaluemaps/commands.py +386 -0
- {apigeecli-0.53.6 → apigeecli-0.53.8}/apigee/keyvaluemaps/keyvaluemaps.py +101 -70
- {apigeecli-0.53.6 → apigeecli-0.53.8}/apigee/keyvaluemaps/serializer.py +1 -0
- apigeecli-0.53.8/apigee/maskconfigs/commands.py +136 -0
- {apigeecli-0.53.6 → apigeecli-0.53.8}/apigee/maskconfigs/maskconfigs.py +19 -14
- {apigeecli-0.53.6 → apigeecli-0.53.8}/apigee/maskconfigs/serializer.py +2 -2
- {apigeecli-0.53.6 → apigeecli-0.53.8}/apigee/permissions/commands.py +49 -55
- apigeecli-0.53.8/apigee/permissions/permissions.py +78 -0
- apigeecli-0.53.8/apigee/permissions/serializer.py +30 -0
- {apigeecli-0.53.6 → apigeecli-0.53.8}/apigee/plugins/commands.py +23 -14
- {apigeecli-0.53.6 → apigeecli-0.53.8}/apigee/prefix.py +1 -1
- {apigeecli-0.53.6 → apigeecli-0.53.8}/apigee/references/commands.py +21 -32
- {apigeecli-0.53.6 → apigeecli-0.53.8}/apigee/references/references.py +5 -3
- {apigeecli-0.53.6 → apigeecli-0.53.8}/apigee/references/serializer.py +3 -1
- apigeecli-0.53.8/apigee/sharedflows/commands.py +452 -0
- {apigeecli-0.53.6 → apigeecli-0.53.8}/apigee/sharedflows/serializer.py +6 -8
- {apigeecli-0.53.6 → apigeecli-0.53.8}/apigee/sharedflows/sharedflows.py +64 -51
- apigeecli-0.53.8/apigee/targetservers/commands.py +150 -0
- {apigeecli-0.53.6 → apigeecli-0.53.8}/apigee/targetservers/serializer.py +2 -2
- {apigeecli-0.53.6 → apigeecli-0.53.8}/apigee/targetservers/targetservers.py +29 -18
- {apigeecli-0.53.6 → apigeecli-0.53.8}/apigee/types.py +1 -0
- apigeecli-0.53.8/apigee/userroles/commands.py +333 -0
- {apigeecli-0.53.6 → apigeecli-0.53.8}/apigee/userroles/userroles.py +50 -56
- {apigeecli-0.53.6 → apigeecli-0.53.8}/apigee/utils.py +29 -16
- {apigeecli-0.53.6 → apigeecli-0.53.8}/apigee/utils_init.py +2 -1
- {apigeecli-0.53.6 → apigeecli-0.53.8}/apigee/virtualhosts/commands.py +24 -35
- {apigeecli-0.53.6 → apigeecli-0.53.8}/apigee/virtualhosts/serializer.py +2 -2
- {apigeecli-0.53.6 → apigeecli-0.53.8}/apigee/virtualhosts/virtualhosts.py +11 -3
- {apigeecli-0.53.6 → apigeecli-0.53.8/apigeecli.egg-info}/PKG-INFO +27 -34
- {apigeecli-0.53.6 → apigeecli-0.53.8}/setup.py +4 -2
- {apigeecli-0.53.6 → apigeecli-0.53.8}/tests/test_auth.py +32 -17
- {apigeecli-0.53.6 → apigeecli-0.53.8}/tests/test_echo.py +5 -1
- {apigeecli-0.53.6 → apigeecli-0.53.8}/tests/test_encryption_utils.py +9 -3
- apigeecli-0.53.6/apigee/apiproducts/commands.py +0 -175
- apigeecli-0.53.6/apigee/apps/commands.py +0 -458
- apigeecli-0.53.6/apigee/caches/commands.py +0 -262
- apigeecli-0.53.6/apigee/deployments/serializer.py +0 -30
- apigeecli-0.53.6/apigee/developers/commands.py +0 -380
- apigeecli-0.53.6/apigee/keyvaluemaps/commands.py +0 -484
- apigeecli-0.53.6/apigee/maskconfigs/commands.py +0 -165
- apigeecli-0.53.6/apigee/permissions/permissions.py +0 -68
- apigeecli-0.53.6/apigee/permissions/serializer.py +0 -25
- apigeecli-0.53.6/apigee/sharedflows/commands.py +0 -424
- apigeecli-0.53.6/apigee/targetservers/commands.py +0 -208
- apigeecli-0.53.6/apigee/userroles/commands.py +0 -400
- {apigeecli-0.53.6 → apigeecli-0.53.8}/LICENSE +0 -0
- {apigeecli-0.53.6 → apigeecli-0.53.8}/NOTICE +0 -0
- {apigeecli-0.53.6 → apigeecli-0.53.8}/apigee/apiproducts/__init__.py +0 -0
- {apigeecli-0.53.6 → apigeecli-0.53.8}/apigee/apis/__init__.py +0 -0
- {apigeecli-0.53.6 → apigeecli-0.53.8}/apigee/apps/__init__.py +0 -0
- {apigeecli-0.53.6 → apigeecli-0.53.8}/apigee/backups/__init__.py +0 -0
- {apigeecli-0.53.6 → apigeecli-0.53.8}/apigee/caches/__init__.py +0 -0
- {apigeecli-0.53.6 → apigeecli-0.53.8}/apigee/configure/__init__.py +0 -0
- {apigeecli-0.53.6 → apigeecli-0.53.8}/apigee/deployments/__init__.py +0 -0
- {apigeecli-0.53.6 → apigeecli-0.53.8}/apigee/developers/__init__.py +0 -0
- {apigeecli-0.53.6 → apigeecli-0.53.8}/apigee/keystores/__init__.py +0 -0
- {apigeecli-0.53.6 → apigeecli-0.53.8}/apigee/keyvaluemaps/__init__.py +0 -0
- {apigeecli-0.53.6 → apigeecli-0.53.8}/apigee/maskconfigs/__init__.py +0 -0
- {apigeecli-0.53.6 → apigeecli-0.53.8}/apigee/permissions/__init__.py +0 -0
- {apigeecli-0.53.6 → apigeecli-0.53.8}/apigee/plugins/__init__.py +0 -0
- {apigeecli-0.53.6 → apigeecli-0.53.8}/apigee/references/__init__.py +0 -0
- {apigeecli-0.53.6 → apigeecli-0.53.8}/apigee/sharedflows/__init__.py +0 -0
- {apigeecli-0.53.6 → apigeecli-0.53.8}/apigee/silent.py +0 -0
- {apigeecli-0.53.6 → apigeecli-0.53.8}/apigee/targetservers/__init__.py +0 -0
- {apigeecli-0.53.6 → apigeecli-0.53.8}/apigee/userroles/__init__.py +0 -0
- {apigeecli-0.53.6 → apigeecli-0.53.8}/apigee/verbose.py +0 -0
- {apigeecli-0.53.6 → apigeecli-0.53.8}/apigee/virtualhosts/__init__.py +0 -0
- {apigeecli-0.53.6 → apigeecli-0.53.8}/apigeecli.egg-info/SOURCES.txt +0 -0
- {apigeecli-0.53.6 → apigeecli-0.53.8}/apigeecli.egg-info/dependency_links.txt +0 -0
- {apigeecli-0.53.6 → apigeecli-0.53.8}/apigeecli.egg-info/entry_points.txt +0 -0
- {apigeecli-0.53.6 → apigeecli-0.53.8}/apigeecli.egg-info/requires.txt +0 -0
- {apigeecli-0.53.6 → apigeecli-0.53.8}/apigeecli.egg-info/top_level.txt +0 -0
- {apigeecli-0.53.6 → apigeecli-0.53.8}/setup.cfg +0 -0
- {apigeecli-0.53.6 → apigeecli-0.53.8}/tests/__init__.py +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: apigeecli
|
|
3
|
-
Version: 0.53.
|
|
4
|
-
Summary:
|
|
3
|
+
Version: 0.53.8
|
|
4
|
+
Summary: (DEPRECATED) apigeecli simplifies and automates Apigee Edge API usage.
|
|
5
5
|
Home-page: https://github.com/darumatic/apigee-cli
|
|
6
6
|
Author: Matthew Delotavo
|
|
7
7
|
Author-email: matthew.t.delotavo@gmail.com
|
|
@@ -29,17 +29,17 @@ apigee-cli
|
|
|
29
29
|
|
|
30
30
|
This tool is no longer actively maintained.
|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
.. warning::
|
|
33
33
|
|
|
34
|
-
|
|
34
|
+
We primarily use and test with SSO; basic and MFA authentication may still work, but we no longer actively use or verify them.
|
|
35
35
|
|
|
36
|
-
|
|
36
|
+
The Apigee Edge command-line interface is an unofficial Python command-line tool built to simplify and automate Apigee Edge API usage, with support for SSO, MFA, and basic authentication.
|
|
37
37
|
|
|
38
38
|
-----------------------------------------
|
|
39
39
|
Why use this instead of the official tool
|
|
40
40
|
-----------------------------------------
|
|
41
41
|
|
|
42
|
-
|
|
42
|
+
While the `official Apigee CLI`_ is powerful, this tool was created to better support Darumatic clients’ CI/CD and self-service workflows that were difficult to manage with the official tool, using simple and easily editable code to demonstrate how to leverage the Apigee Admin APIs.
|
|
43
43
|
|
|
44
44
|
------------
|
|
45
45
|
Installation
|
|
@@ -57,8 +57,7 @@ or for your user::
|
|
|
57
57
|
|
|
58
58
|
$ pip install --user apigeecli
|
|
59
59
|
|
|
60
|
-
If you have the apigee-cli installed and want to upgrade to the latest version
|
|
61
|
-
you can run::
|
|
60
|
+
If you have the apigee-cli installed and want to upgrade to the latest version you can run::
|
|
62
61
|
|
|
63
62
|
$ pip install --upgrade apigeecli
|
|
64
63
|
|
|
@@ -66,8 +65,7 @@ you can run::
|
|
|
66
65
|
Getting Started
|
|
67
66
|
---------------
|
|
68
67
|
|
|
69
|
-
Before using apigee-cli, you need to tell it about your Apigee Edge credentials. You
|
|
70
|
-
can do this in three ways:
|
|
68
|
+
Before using apigee-cli, you need to tell it about your Apigee Edge credentials. You can do this in three ways:
|
|
71
69
|
|
|
72
70
|
* Environment variables
|
|
73
71
|
* Config file
|
|
@@ -126,6 +124,18 @@ Run the following command to get a list of API proxies in your ``default`` Apige
|
|
|
126
124
|
$ apigee apis list
|
|
127
125
|
["helloworld", "oauth"]
|
|
128
126
|
|
|
127
|
+
^^^^^^^^^^^^^^^
|
|
128
|
+
Troubleshooting
|
|
129
|
+
^^^^^^^^^^^^^^^
|
|
130
|
+
|
|
131
|
+
If you encounter issues with commands, check the log file for detailed debug information and error messages::
|
|
132
|
+
|
|
133
|
+
~/.apigee/exceptions.log
|
|
134
|
+
|
|
135
|
+
This file can help diagnose installation problems, missing dependencies, or errors related to Apigee Edge.
|
|
136
|
+
|
|
137
|
+
You can also use the verbose flags ``-v`` or ``-vv`` with commands to see more detailed request information.
|
|
138
|
+
|
|
129
139
|
-------------
|
|
130
140
|
Running Tests
|
|
131
141
|
-------------
|
|
@@ -166,64 +176,47 @@ Disclaimer
|
|
|
166
176
|
|
|
167
177
|
This tool is not affiliated with Apigee or Google and is highly experimental.
|
|
168
178
|
|
|
169
|
-
|
|
170
179
|
.. _`official Apigee CLI`: https://github.com/apigee/apigeetool-node
|
|
171
180
|
|
|
172
181
|
.. |Upload Python Package badge| image:: https://github.com/mdelotavo/apigee-cli/workflows/Upload%20Python%20Package/badge.svg
|
|
173
|
-
|
|
182
|
+
:target: https://github.com/mdelotavo/apigee-cli/actions?query=workflow%3A%22Upload+Python+Package%22
|
|
174
183
|
|
|
175
184
|
.. |Python package badge| image:: https://github.com/mdelotavo/apigee-cli/workflows/Python%20package/badge.svg
|
|
176
|
-
|
|
185
|
+
:target: https://github.com/mdelotavo/apigee-cli/actions?query=workflow%3A%22Python+package%22
|
|
177
186
|
|
|
178
187
|
.. |Code style: black| image:: https://img.shields.io/badge/code%20style-black-000000.svg
|
|
179
|
-
|
|
188
|
+
:target: https://github.com/psf/black
|
|
180
189
|
|
|
181
190
|
.. |PyPI| image:: https://img.shields.io/pypi/v/apigeecli
|
|
182
|
-
|
|
191
|
+
:target: https://pypi.org/project/apigeecli/
|
|
183
192
|
|
|
184
193
|
.. |License| image:: https://img.shields.io/badge/License-Apache%202.0-blue.svg
|
|
185
|
-
|
|
194
|
+
:target: https://opensource.org/licenses/Apache-2.0
|
|
186
195
|
|
|
187
196
|
.. |Python version| image:: https://img.shields.io/pypi/pyversions/apigeecli
|
|
188
|
-
|
|
197
|
+
:target: https://pypi.org/project/apigeecli/
|
|
189
198
|
|
|
190
199
|
.. |PyPI Version| image:: https://badge.fury.io/py/apigeecli.svg
|
|
191
200
|
:target: https://badge.fury.io/py/apigeecli
|
|
192
201
|
|
|
193
202
|
.. |Downloads| image:: https://pepy.tech/badge/apigeecli
|
|
194
|
-
|
|
203
|
+
:target: https://pepy.tech/project/apigeecli
|
|
195
204
|
|
|
196
205
|
.. _`Apigee Product Documentation`: https://apidocs.apigee.com/management/apis
|
|
197
|
-
|
|
198
206
|
.. _`Permissions reference`: https://docs.apigee.com/api-platform/system-administration/permissions
|
|
199
|
-
|
|
200
207
|
.. _`Add permissions to testing role`: https://docs.apigee.com/api-platform/system-administration/managing-roles-api#addpermissionstotestingrole
|
|
201
|
-
|
|
202
208
|
.. _pip: http://www.pip-installer.org/en/latest/
|
|
203
|
-
|
|
204
209
|
.. _`Universal Command Line Interface for Amazon Web Services`: https://github.com/aws/aws-cli
|
|
205
|
-
|
|
206
210
|
.. _`The Apigee Management API command-line interface documentation`: https://darumatic.github.io/apigee-cli/index.html
|
|
207
|
-
|
|
208
211
|
.. _`GitHub`: https://github.com/darumatic/apigee-cli
|
|
209
|
-
|
|
210
212
|
.. _`Python Package Index (PyPI)`: https://pypi.org/project/apigeecli/
|
|
211
|
-
|
|
212
213
|
.. _`Access the Edge API with SAML`: https://docs.apigee.com/api-platform/system-administration/using-saml
|
|
213
|
-
|
|
214
214
|
.. _`Commands cheatsheet`: https://github.com/mdelotavo/apigee-cli-docs
|
|
215
|
-
|
|
216
215
|
.. _`Using SAML with automated tasks`: https://github.com/mdelotavo/apigee-cli-docs
|
|
217
|
-
|
|
218
216
|
.. _`Tabulating deployments`: https://github.com/mdelotavo/apigee-cli-docs
|
|
219
|
-
|
|
220
217
|
.. _`Tabulating resource permissions`: https://github.com/mdelotavo/apigee-cli-docs
|
|
221
|
-
|
|
222
218
|
.. _`Troubleshooting`: https://github.com/mdelotavo/apigee-cli-docs
|
|
223
|
-
|
|
224
219
|
.. _`Mirror`: https://github.com/mdelotavo/apigee-cli
|
|
225
|
-
|
|
226
220
|
.. _`Apigee CI/CD Docker releases`: https://hub.docker.com/r/darumatic/apigee-cicd
|
|
227
221
|
|
|
228
222
|
|
|
229
|
-
|
|
@@ -8,17 +8,17 @@ apigee-cli
|
|
|
8
8
|
|
|
9
9
|
This tool is no longer actively maintained.
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
.. warning::
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
We primarily use and test with SSO; basic and MFA authentication may still work, but we no longer actively use or verify them.
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
The Apigee Edge command-line interface is an unofficial Python command-line tool built to simplify and automate Apigee Edge API usage, with support for SSO, MFA, and basic authentication.
|
|
16
16
|
|
|
17
17
|
-----------------------------------------
|
|
18
18
|
Why use this instead of the official tool
|
|
19
19
|
-----------------------------------------
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
While the `official Apigee CLI`_ is powerful, this tool was created to better support Darumatic clients’ CI/CD and self-service workflows that were difficult to manage with the official tool, using simple and easily editable code to demonstrate how to leverage the Apigee Admin APIs.
|
|
22
22
|
|
|
23
23
|
------------
|
|
24
24
|
Installation
|
|
@@ -36,8 +36,7 @@ or for your user::
|
|
|
36
36
|
|
|
37
37
|
$ pip install --user apigeecli
|
|
38
38
|
|
|
39
|
-
If you have the apigee-cli installed and want to upgrade to the latest version
|
|
40
|
-
you can run::
|
|
39
|
+
If you have the apigee-cli installed and want to upgrade to the latest version you can run::
|
|
41
40
|
|
|
42
41
|
$ pip install --upgrade apigeecli
|
|
43
42
|
|
|
@@ -45,8 +44,7 @@ you can run::
|
|
|
45
44
|
Getting Started
|
|
46
45
|
---------------
|
|
47
46
|
|
|
48
|
-
Before using apigee-cli, you need to tell it about your Apigee Edge credentials. You
|
|
49
|
-
can do this in three ways:
|
|
47
|
+
Before using apigee-cli, you need to tell it about your Apigee Edge credentials. You can do this in three ways:
|
|
50
48
|
|
|
51
49
|
* Environment variables
|
|
52
50
|
* Config file
|
|
@@ -105,6 +103,18 @@ Run the following command to get a list of API proxies in your ``default`` Apige
|
|
|
105
103
|
$ apigee apis list
|
|
106
104
|
["helloworld", "oauth"]
|
|
107
105
|
|
|
106
|
+
^^^^^^^^^^^^^^^
|
|
107
|
+
Troubleshooting
|
|
108
|
+
^^^^^^^^^^^^^^^
|
|
109
|
+
|
|
110
|
+
If you encounter issues with commands, check the log file for detailed debug information and error messages::
|
|
111
|
+
|
|
112
|
+
~/.apigee/exceptions.log
|
|
113
|
+
|
|
114
|
+
This file can help diagnose installation problems, missing dependencies, or errors related to Apigee Edge.
|
|
115
|
+
|
|
116
|
+
You can also use the verbose flags ``-v`` or ``-vv`` with commands to see more detailed request information.
|
|
117
|
+
|
|
108
118
|
-------------
|
|
109
119
|
Running Tests
|
|
110
120
|
-------------
|
|
@@ -145,62 +155,45 @@ Disclaimer
|
|
|
145
155
|
|
|
146
156
|
This tool is not affiliated with Apigee or Google and is highly experimental.
|
|
147
157
|
|
|
148
|
-
|
|
149
158
|
.. _`official Apigee CLI`: https://github.com/apigee/apigeetool-node
|
|
150
159
|
|
|
151
160
|
.. |Upload Python Package badge| image:: https://github.com/mdelotavo/apigee-cli/workflows/Upload%20Python%20Package/badge.svg
|
|
152
|
-
|
|
161
|
+
:target: https://github.com/mdelotavo/apigee-cli/actions?query=workflow%3A%22Upload+Python+Package%22
|
|
153
162
|
|
|
154
163
|
.. |Python package badge| image:: https://github.com/mdelotavo/apigee-cli/workflows/Python%20package/badge.svg
|
|
155
|
-
|
|
164
|
+
:target: https://github.com/mdelotavo/apigee-cli/actions?query=workflow%3A%22Python+package%22
|
|
156
165
|
|
|
157
166
|
.. |Code style: black| image:: https://img.shields.io/badge/code%20style-black-000000.svg
|
|
158
|
-
|
|
167
|
+
:target: https://github.com/psf/black
|
|
159
168
|
|
|
160
169
|
.. |PyPI| image:: https://img.shields.io/pypi/v/apigeecli
|
|
161
|
-
|
|
170
|
+
:target: https://pypi.org/project/apigeecli/
|
|
162
171
|
|
|
163
172
|
.. |License| image:: https://img.shields.io/badge/License-Apache%202.0-blue.svg
|
|
164
|
-
|
|
173
|
+
:target: https://opensource.org/licenses/Apache-2.0
|
|
165
174
|
|
|
166
175
|
.. |Python version| image:: https://img.shields.io/pypi/pyversions/apigeecli
|
|
167
|
-
|
|
176
|
+
:target: https://pypi.org/project/apigeecli/
|
|
168
177
|
|
|
169
178
|
.. |PyPI Version| image:: https://badge.fury.io/py/apigeecli.svg
|
|
170
179
|
:target: https://badge.fury.io/py/apigeecli
|
|
171
180
|
|
|
172
181
|
.. |Downloads| image:: https://pepy.tech/badge/apigeecli
|
|
173
|
-
|
|
182
|
+
:target: https://pepy.tech/project/apigeecli
|
|
174
183
|
|
|
175
184
|
.. _`Apigee Product Documentation`: https://apidocs.apigee.com/management/apis
|
|
176
|
-
|
|
177
185
|
.. _`Permissions reference`: https://docs.apigee.com/api-platform/system-administration/permissions
|
|
178
|
-
|
|
179
186
|
.. _`Add permissions to testing role`: https://docs.apigee.com/api-platform/system-administration/managing-roles-api#addpermissionstotestingrole
|
|
180
|
-
|
|
181
187
|
.. _pip: http://www.pip-installer.org/en/latest/
|
|
182
|
-
|
|
183
188
|
.. _`Universal Command Line Interface for Amazon Web Services`: https://github.com/aws/aws-cli
|
|
184
|
-
|
|
185
189
|
.. _`The Apigee Management API command-line interface documentation`: https://darumatic.github.io/apigee-cli/index.html
|
|
186
|
-
|
|
187
190
|
.. _`GitHub`: https://github.com/darumatic/apigee-cli
|
|
188
|
-
|
|
189
191
|
.. _`Python Package Index (PyPI)`: https://pypi.org/project/apigeecli/
|
|
190
|
-
|
|
191
192
|
.. _`Access the Edge API with SAML`: https://docs.apigee.com/api-platform/system-administration/using-saml
|
|
192
|
-
|
|
193
193
|
.. _`Commands cheatsheet`: https://github.com/mdelotavo/apigee-cli-docs
|
|
194
|
-
|
|
195
194
|
.. _`Using SAML with automated tasks`: https://github.com/mdelotavo/apigee-cli-docs
|
|
196
|
-
|
|
197
195
|
.. _`Tabulating deployments`: https://github.com/mdelotavo/apigee-cli-docs
|
|
198
|
-
|
|
199
196
|
.. _`Tabulating resource permissions`: https://github.com/mdelotavo/apigee-cli-docs
|
|
200
|
-
|
|
201
197
|
.. _`Troubleshooting`: https://github.com/mdelotavo/apigee-cli-docs
|
|
202
|
-
|
|
203
198
|
.. _`Mirror`: https://github.com/mdelotavo/apigee-cli
|
|
204
|
-
|
|
205
199
|
.. _`Apigee CI/CD Docker releases`: https://hub.docker.com/r/darumatic/apigee-cicd
|
|
206
|
-
|
|
@@ -6,32 +6,30 @@ from apigee import utils_init
|
|
|
6
6
|
|
|
7
7
|
APP = "apigeecli"
|
|
8
8
|
CMD = "apigee"
|
|
9
|
-
__version__ = "0.53.
|
|
10
|
-
description = "
|
|
11
|
-
long_description = """
|
|
9
|
+
__version__ = "0.53.8"
|
|
10
|
+
description = "(DEPRECATED) apigeecli simplifies and automates Apigee Edge API usage."
|
|
11
|
+
long_description = """The Apigee Edge command-line interface is an unofficial Python command-line tool built to simplify and automate Apigee Edge API usage, with support for SSO, MFA, and basic authentication."""
|
|
12
12
|
|
|
13
13
|
APIGEE_CLI_DIRECTORY = utils_init.join_path_components(Path.home(), ".apigee")
|
|
14
|
-
APIGEE_CLI_PLUGINS_DIRECTORY = utils_init.join_path_components(
|
|
14
|
+
APIGEE_CLI_PLUGINS_DIRECTORY = utils_init.join_path_components(
|
|
15
|
+
APIGEE_CLI_DIRECTORY, "plugins")
|
|
15
16
|
|
|
16
17
|
APIGEE_ADMIN_API_URL = "https://api.enterprise.apigee.com"
|
|
17
18
|
APIGEE_CLI_ACCESS_TOKEN_FILE = utils_init.join_path_components(
|
|
18
|
-
APIGEE_CLI_DIRECTORY, "access_token"
|
|
19
|
-
)
|
|
19
|
+
APIGEE_CLI_DIRECTORY, "access_token")
|
|
20
20
|
APIGEE_CLI_REFRESH_TOKEN_FILE = utils_init.join_path_components(
|
|
21
|
-
APIGEE_CLI_DIRECTORY, "refresh_token"
|
|
22
|
-
|
|
23
|
-
|
|
21
|
+
APIGEE_CLI_DIRECTORY, "refresh_token")
|
|
22
|
+
APIGEE_CLI_CREDENTIALS_FILE = utils_init.join_path_components(
|
|
23
|
+
APIGEE_CLI_DIRECTORY, "credentials")
|
|
24
24
|
# APIGEE_CLI_EXCEPTION_LOG_FILE = utils.build_path_str(APIGEE_CLI_DIRECTORY, 'exception.log')
|
|
25
25
|
APIGEE_CLI_EXCEPTIONS_LOG_FILE = utils_init.join_path_components(
|
|
26
|
-
APIGEE_CLI_DIRECTORY, "exceptions.log"
|
|
27
|
-
|
|
28
|
-
|
|
26
|
+
APIGEE_CLI_DIRECTORY, "exceptions.log")
|
|
27
|
+
APIGEE_CLI_IS_MACHINE_USER = utils_init.is_truthy_envvar(
|
|
28
|
+
getenv("APIGEE_CLI_IS_MACHINE_USER"))
|
|
29
29
|
APIGEE_CLI_PLUGINS_CONFIG_FILE = utils_init.join_path_components(
|
|
30
|
-
APIGEE_CLI_PLUGINS_DIRECTORY, "config"
|
|
31
|
-
)
|
|
30
|
+
APIGEE_CLI_PLUGINS_DIRECTORY, "config")
|
|
32
31
|
APIGEE_CLI_PLUGINS_PATH = utils_init.join_path_components(
|
|
33
|
-
APIGEE_CLI_PLUGINS_DIRECTORY, "__init__.py"
|
|
34
|
-
)
|
|
32
|
+
APIGEE_CLI_PLUGINS_DIRECTORY, "__init__.py")
|
|
35
33
|
APIGEE_CLI_PREFIX = getenv("APIGEE_CLI_PREFIX")
|
|
36
34
|
APIGEE_CLI_SYMMETRIC_KEY = getenv("APIGEE_CLI_SYMMETRIC_KEY")
|
|
37
35
|
APIGEE_CLI_TOGGLE_SILENT = False
|
|
@@ -5,7 +5,8 @@ from functools import update_wrapper
|
|
|
5
5
|
|
|
6
6
|
import click
|
|
7
7
|
|
|
8
|
-
from apigee import (APIGEE_CLI_EXCEPTIONS_LOG_FILE,
|
|
8
|
+
from apigee import (APIGEE_CLI_EXCEPTIONS_LOG_FILE,
|
|
9
|
+
APIGEE_CLI_PLUGINS_DIRECTORY, CMD)
|
|
9
10
|
from apigee import __version__ as version
|
|
10
11
|
from apigee.apiproducts.commands import apiproducts
|
|
11
12
|
from apigee.apis.commands import apis
|
|
@@ -17,7 +18,8 @@ from apigee.cls import AliasedGroup
|
|
|
17
18
|
from apigee.configure.commands import configure
|
|
18
19
|
from apigee.deployments.commands import deployments
|
|
19
20
|
from apigee.developers.commands import developers
|
|
20
|
-
from apigee.exceptions import
|
|
21
|
+
from apigee.exceptions import (configure_global_logger,
|
|
22
|
+
wrap_with_exception_handling)
|
|
21
23
|
from apigee.keystores.commands import keystores
|
|
22
24
|
from apigee.keyvaluemaps.commands import keyvaluemaps
|
|
23
25
|
from apigee.maskconfigs.commands import maskconfigs
|
|
@@ -27,12 +29,12 @@ from apigee.references.commands import references
|
|
|
27
29
|
from apigee.sharedflows.commands import sharedflows
|
|
28
30
|
from apigee.targetservers.commands import targetservers
|
|
29
31
|
from apigee.userroles.commands import userroles
|
|
30
|
-
from apigee.utils import (
|
|
32
|
+
from apigee.utils import (execute_function_on_directory_files,
|
|
33
|
+
import_plugins_from_directory)
|
|
31
34
|
from apigee.virtualhosts.commands import virtualhosts
|
|
32
35
|
|
|
33
36
|
# from click_aliases import ClickAliasedGroup
|
|
34
37
|
|
|
35
|
-
|
|
36
38
|
CONTEXT_SETTINGS = dict(help_option_names=["-h", "--help"])
|
|
37
39
|
|
|
38
40
|
|
|
@@ -89,7 +91,7 @@ def main():
|
|
|
89
91
|
execute_function_on_directory_files(
|
|
90
92
|
APIGEE_CLI_PLUGINS_DIRECTORY,
|
|
91
93
|
import_plugins_from_directory,
|
|
92
|
-
args=(cli_commands,),
|
|
94
|
+
args=(cli_commands, ),
|
|
93
95
|
glob="[!.][!__]*/__init__.py",
|
|
94
96
|
)
|
|
95
97
|
|
|
@@ -15,18 +15,21 @@ UPDATE_API_PRODUCT_PATH = "{api_url}/v1/organizations/{org}/apiproducts/{name}"
|
|
|
15
15
|
|
|
16
16
|
|
|
17
17
|
class Apiproducts:
|
|
18
|
+
|
|
18
19
|
def __init__(self, auth, org_name, apiproduct_name):
|
|
19
20
|
self.auth = auth
|
|
20
21
|
self.org_name = org_name
|
|
21
22
|
self.apiproduct_name = apiproduct_name
|
|
22
23
|
|
|
23
24
|
def create_api_product(self, request_body):
|
|
24
|
-
uri = CREATE_API_PRODUCT_PATH.format(
|
|
25
|
-
|
|
26
|
-
)
|
|
25
|
+
uri = CREATE_API_PRODUCT_PATH.format(api_url=APIGEE_ADMIN_API_URL,
|
|
26
|
+
org=self.org_name)
|
|
27
27
|
hdrs = auth.set_authentication_headers(
|
|
28
28
|
self.auth,
|
|
29
|
-
custom_headers={
|
|
29
|
+
custom_headers={
|
|
30
|
+
"Accept": "application/json",
|
|
31
|
+
"Content-Type": "application/json"
|
|
32
|
+
},
|
|
30
33
|
)
|
|
31
34
|
body = json.loads(request_body)
|
|
32
35
|
resp = requests.post(uri, headers=hdrs, json=body)
|
|
@@ -34,26 +37,31 @@ class Apiproducts:
|
|
|
34
37
|
return resp
|
|
35
38
|
|
|
36
39
|
def delete_api_product(self):
|
|
37
|
-
uri = DELETE_API_PRODUCT_PATH.format(
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
hdrs = auth.set_authentication_headers(
|
|
40
|
+
uri = DELETE_API_PRODUCT_PATH.format(api_url=APIGEE_ADMIN_API_URL,
|
|
41
|
+
org=self.org_name,
|
|
42
|
+
name=self.apiproduct_name)
|
|
43
|
+
hdrs = auth.set_authentication_headers(
|
|
44
|
+
self.auth, custom_headers={"Accept": "application/json"})
|
|
41
45
|
resp = requests.delete(uri, headers=hdrs)
|
|
42
46
|
resp.raise_for_status()
|
|
43
47
|
return resp
|
|
44
48
|
|
|
45
49
|
def get_api_product(self): # sourcery skip: class-extract-method
|
|
46
|
-
uri = GET_API_PRODUCT_PATH.format(
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
hdrs = auth.set_authentication_headers(
|
|
50
|
+
uri = GET_API_PRODUCT_PATH.format(api_url=APIGEE_ADMIN_API_URL,
|
|
51
|
+
org=self.org_name,
|
|
52
|
+
name=self.apiproduct_name)
|
|
53
|
+
hdrs = auth.set_authentication_headers(
|
|
54
|
+
self.auth, custom_headers={"Accept": "application/json"})
|
|
50
55
|
resp = requests.get(uri, headers=hdrs)
|
|
51
56
|
resp.raise_for_status()
|
|
52
57
|
return resp
|
|
53
58
|
|
|
54
|
-
def list_api_products(
|
|
55
|
-
|
|
56
|
-
|
|
59
|
+
def list_api_products(self,
|
|
60
|
+
prefix=None,
|
|
61
|
+
expand=False,
|
|
62
|
+
count=1000,
|
|
63
|
+
startkey="",
|
|
64
|
+
format="json"):
|
|
57
65
|
uri = LIST_API_PRODUCTS_PATH.format(
|
|
58
66
|
api_url=APIGEE_ADMIN_API_URL,
|
|
59
67
|
org=self.org_name,
|
|
@@ -61,10 +69,13 @@ class Apiproducts:
|
|
|
61
69
|
count=count,
|
|
62
70
|
startkey=startkey,
|
|
63
71
|
)
|
|
64
|
-
hdrs = auth.set_authentication_headers(
|
|
72
|
+
hdrs = auth.set_authentication_headers(
|
|
73
|
+
self.auth, custom_headers={"Accept": "application/json"})
|
|
65
74
|
resp = requests.get(uri, headers=hdrs)
|
|
66
75
|
resp.raise_for_status()
|
|
67
|
-
return ApiproductsSerializer().serialize_details(resp,
|
|
76
|
+
return ApiproductsSerializer().serialize_details(resp,
|
|
77
|
+
format,
|
|
78
|
+
prefix=prefix)
|
|
68
79
|
|
|
69
80
|
def push_apiproducts(self, file):
|
|
70
81
|
apiproduct = read_file_content(file, type="json")
|
|
@@ -80,12 +91,15 @@ class Apiproducts:
|
|
|
80
91
|
console.echo(self.create_api_product(json.dumps(apiproduct)).text)
|
|
81
92
|
|
|
82
93
|
def update_api_product(self, request_body):
|
|
83
|
-
uri = UPDATE_API_PRODUCT_PATH.format(
|
|
84
|
-
|
|
85
|
-
|
|
94
|
+
uri = UPDATE_API_PRODUCT_PATH.format(api_url=APIGEE_ADMIN_API_URL,
|
|
95
|
+
org=self.org_name,
|
|
96
|
+
name=self.apiproduct_name)
|
|
86
97
|
hdrs = auth.set_authentication_headers(
|
|
87
98
|
self.auth,
|
|
88
|
-
custom_headers={
|
|
99
|
+
custom_headers={
|
|
100
|
+
"Accept": "application/json",
|
|
101
|
+
"Content-Type": "application/json"
|
|
102
|
+
},
|
|
89
103
|
)
|
|
90
104
|
body = json.loads(request_body)
|
|
91
105
|
resp = requests.put(uri, headers=hdrs, json=body)
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import click
|
|
2
|
+
|
|
3
|
+
from apigee import console
|
|
4
|
+
from apigee.apiproducts.apiproducts import Apiproducts
|
|
5
|
+
from apigee.auth import common_auth_options, generate_authentication
|
|
6
|
+
from apigee.prefix import common_prefix_options
|
|
7
|
+
from apigee.silent import common_silent_options
|
|
8
|
+
from apigee.verbose import common_verbose_options
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@click.group(
|
|
12
|
+
help=
|
|
13
|
+
"API products enable you to bundle and distribute your APIs to multiple developer groups simultaneously, without having to modify code."
|
|
14
|
+
)
|
|
15
|
+
def apiproducts():
|
|
16
|
+
pass
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def _create_api_product(username, password, mfa_secret, token, zonename, org,
|
|
20
|
+
profile, name, body, **kwargs):
|
|
21
|
+
return (Apiproducts(
|
|
22
|
+
generate_authentication(username, password, mfa_secret, token,
|
|
23
|
+
zonename), org,
|
|
24
|
+
name).create_api_product(body).text)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
@apiproducts.command(help="Creates an API product in an organization.")
|
|
28
|
+
@common_auth_options
|
|
29
|
+
@common_verbose_options
|
|
30
|
+
@common_silent_options
|
|
31
|
+
@click.option("-n", "--name", help="name", required=True)
|
|
32
|
+
@click.option("-b", "--body", help="request body", required=True)
|
|
33
|
+
def create(*args, **kwargs):
|
|
34
|
+
console.echo(_create_api_product(*args, **kwargs))
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def _delete_api_product(username, password, mfa_secret, token, zonename, org,
|
|
38
|
+
profile, name, **kwargs):
|
|
39
|
+
return (Apiproducts(
|
|
40
|
+
generate_authentication(username, password, mfa_secret, token,
|
|
41
|
+
zonename), org,
|
|
42
|
+
name).delete_api_product().text)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
@apiproducts.command(help="Deletes an API product from an organization.")
|
|
46
|
+
@common_auth_options
|
|
47
|
+
@common_verbose_options
|
|
48
|
+
@common_silent_options
|
|
49
|
+
@click.option("-n", "--name", help="name", required=True)
|
|
50
|
+
def delete(*args, **kwargs):
|
|
51
|
+
console.echo(_delete_api_product(*args, **kwargs))
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def _get_api_product(username, password, mfa_secret, token, zonename, org,
|
|
55
|
+
profile, name, **kwargs):
|
|
56
|
+
return (Apiproducts(
|
|
57
|
+
generate_authentication(username, password, mfa_secret, token,
|
|
58
|
+
zonename), org, name).get_api_product().text)
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
@apiproducts.command(
|
|
62
|
+
help=
|
|
63
|
+
'Gets configuration data for an API product. The API product name required in the request URL is not the "Display Name" value displayed for the API product in the Edge UI. While they may be the same, they are not always the same depending on whether the API product was created via UI or API.'
|
|
64
|
+
)
|
|
65
|
+
@common_auth_options
|
|
66
|
+
@common_verbose_options
|
|
67
|
+
@common_silent_options
|
|
68
|
+
@click.option("-n", "--name", help="name", required=True)
|
|
69
|
+
def get(*args, **kwargs):
|
|
70
|
+
console.echo(_get_api_product(*args, **kwargs))
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def _list_api_products(username,
|
|
74
|
+
password,
|
|
75
|
+
mfa_secret,
|
|
76
|
+
token,
|
|
77
|
+
zonename,
|
|
78
|
+
org,
|
|
79
|
+
profile,
|
|
80
|
+
prefix=None,
|
|
81
|
+
expand=False,
|
|
82
|
+
count=1000,
|
|
83
|
+
startkey="",
|
|
84
|
+
**kwargs):
|
|
85
|
+
return Apiproducts(
|
|
86
|
+
generate_authentication(username, password, mfa_secret, token,
|
|
87
|
+
zonename), org,
|
|
88
|
+
None).list_api_products(prefix=prefix,
|
|
89
|
+
expand=expand,
|
|
90
|
+
count=count,
|
|
91
|
+
startkey=startkey)
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
@apiproducts.command(
|
|
95
|
+
help="Get a list of all API product names for an organization.")
|
|
96
|
+
@common_auth_options
|
|
97
|
+
@common_verbose_options
|
|
98
|
+
@common_silent_options
|
|
99
|
+
@common_prefix_options
|
|
100
|
+
@click.option(
|
|
101
|
+
"--expand/--no-expand",
|
|
102
|
+
default=False,
|
|
103
|
+
help="Set to 'true' to get expanded details about each product.",
|
|
104
|
+
)
|
|
105
|
+
@click.option(
|
|
106
|
+
"--count",
|
|
107
|
+
type=click.INT,
|
|
108
|
+
default=1000,
|
|
109
|
+
show_default=True,
|
|
110
|
+
help=
|
|
111
|
+
"Number of API products to return in the API call. The maximum limit is 1000. Use with the startkey to provide more targeted filtering.",
|
|
112
|
+
)
|
|
113
|
+
@click.option(
|
|
114
|
+
"--startkey",
|
|
115
|
+
default="",
|
|
116
|
+
show_default=True,
|
|
117
|
+
help=
|
|
118
|
+
"Returns a list of API products starting with the specified API product.",
|
|
119
|
+
)
|
|
120
|
+
def list(*args, **kwargs):
|
|
121
|
+
console.echo(_list_api_products(*args, **kwargs))
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def _update_api_product(username, password, mfa_secret, token, zonename, org,
|
|
125
|
+
profile, name, body, **kwargs):
|
|
126
|
+
return (Apiproducts(
|
|
127
|
+
generate_authentication(username, password, mfa_secret, token,
|
|
128
|
+
zonename), org,
|
|
129
|
+
name).update_api_product(body).text)
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
@apiproducts.command(
|
|
133
|
+
help=
|
|
134
|
+
"Updates an existing API product. You must include all required values, whether or not you are updating them, as well as any optional values that you are updating."
|
|
135
|
+
)
|
|
136
|
+
@common_auth_options
|
|
137
|
+
@common_verbose_options
|
|
138
|
+
@common_silent_options
|
|
139
|
+
@click.option("-n", "--name", help="name", required=True)
|
|
140
|
+
@click.option("-b", "--body", help="request body", required=True)
|
|
141
|
+
def update(*args, **kwargs):
|
|
142
|
+
console.echo(_update_api_product(*args, **kwargs))
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
def _push_apiproducts(username, password, mfa_secret, token, zonename, org,
|
|
146
|
+
profile, file, **kwargs):
|
|
147
|
+
return Apiproducts(
|
|
148
|
+
generate_authentication(username, password, mfa_secret, token,
|
|
149
|
+
zonename), org, None).push_apiproducts(file)
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
@apiproducts.command(
|
|
153
|
+
help="Push API product to Apigee. This will create/update an API product.")
|
|
154
|
+
@common_auth_options
|
|
155
|
+
@common_silent_options
|
|
156
|
+
@common_verbose_options
|
|
157
|
+
@click.option(
|
|
158
|
+
"-f",
|
|
159
|
+
"--file",
|
|
160
|
+
type=click.Path(exists=True,
|
|
161
|
+
dir_okay=False,
|
|
162
|
+
file_okay=True,
|
|
163
|
+
resolve_path=False),
|
|
164
|
+
required=True,
|
|
165
|
+
)
|
|
166
|
+
def push(*args, **kwargs):
|
|
167
|
+
_push_apiproducts(*args, **kwargs)
|
|
@@ -2,6 +2,7 @@ import json
|
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
class ApiproductsSerializer:
|
|
5
|
+
|
|
5
6
|
def serialize_details(self, apiproducts, format, prefix=None):
|
|
6
7
|
resp = apiproducts
|
|
7
8
|
if format == "text":
|
|
@@ -9,8 +10,7 @@ class ApiproductsSerializer:
|
|
|
9
10
|
apiproducts = apiproducts.json()
|
|
10
11
|
if prefix:
|
|
11
12
|
apiproducts = [
|
|
12
|
-
apiproduct
|
|
13
|
-
for apiproduct in apiproducts
|
|
13
|
+
apiproduct for apiproduct in apiproducts
|
|
14
14
|
if apiproduct.startswith(prefix)
|
|
15
15
|
]
|
|
16
16
|
if format == "dict":
|