cloudsmith-cli 1.9.2__tar.gz → 1.9.4__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.
- {cloudsmith_cli-1.9.2/cloudsmith_cli.egg-info → cloudsmith_cli-1.9.4}/PKG-INFO +1 -1
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/cli/commands/dependencies.py +1 -1
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/cli/commands/list_.py +13 -7
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/cli/commands/policy/license.py +15 -8
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/cli/commands/policy/vulnerability.py +15 -7
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/cli/commands/repos.py +38 -17
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/cli/commands/upstream.py +16 -8
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/cli/decorators.py +20 -8
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/cli/tests/commands/policy/test_licence.py +16 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/cli/tests/commands/policy/test_vulnerability.py +18 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/cli/tests/commands/test_package_commands.py +7 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/cli/tests/commands/test_repos.py +24 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/cli/tests/commands/test_upstream.py +30 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/cli/utils.py +31 -25
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/cli/validators.py +35 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/core/pagination.py +55 -0
- cloudsmith_cli-1.9.4/cloudsmith_cli/data/VERSION +1 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4/cloudsmith_cli.egg-info}/PKG-INFO +1 -1
- cloudsmith_cli-1.9.2/cloudsmith_cli/data/VERSION +0 -1
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/LICENSE +0 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/MANIFEST.in +0 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/README.md +0 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/__init__.py +0 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/__main__.py +0 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/cli/__init__.py +0 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/cli/command.py +0 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/cli/commands/__init__.py +0 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/cli/commands/auth.py +0 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/cli/commands/check.py +0 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/cli/commands/copy.py +0 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/cli/commands/delete.py +0 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/cli/commands/docs.py +0 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/cli/commands/download.py +0 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/cli/commands/entitlements.py +0 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/cli/commands/help_.py +0 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/cli/commands/login.py +0 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/cli/commands/main.py +0 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/cli/commands/metrics/__init__.py +0 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/cli/commands/metrics/command.py +0 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/cli/commands/metrics/entitlements.py +0 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/cli/commands/metrics/packages.py +0 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/cli/commands/move.py +0 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/cli/commands/policy/__init__.py +0 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/cli/commands/policy/command.py +0 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/cli/commands/push.py +0 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/cli/commands/quarantine.py +0 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/cli/commands/quota/__init__.py +0 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/cli/commands/quota/command.py +0 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/cli/commands/quota/history.py +0 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/cli/commands/quota/quota.py +0 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/cli/commands/resync.py +0 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/cli/commands/status.py +0 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/cli/commands/tags.py +0 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/cli/commands/tokens.py +0 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/cli/commands/whoami.py +0 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/cli/config.py +0 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/cli/exceptions.py +0 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/cli/saml.py +0 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/cli/table.py +0 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/cli/tests/__init__.py +0 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/cli/tests/commands/__init__.py +0 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/cli/tests/commands/policy/__init__.py +0 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/cli/tests/commands/test_check.py +0 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/cli/tests/commands/test_download.py +0 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/cli/tests/commands/test_login.py +0 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/cli/tests/commands/test_main.py +0 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/cli/tests/commands/test_tokens.py +0 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/cli/tests/conftest.py +0 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/cli/tests/test_push.py +0 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/cli/tests/test_saml.py +0 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/cli/tests/test_utils.py +0 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/cli/tests/utils.py +0 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/cli/types.py +0 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/cli/webserver.py +0 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/core/__init__.py +0 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/core/api/__init__.py +0 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/core/api/distros.py +0 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/core/api/entitlements.py +0 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/core/api/exceptions.py +0 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/core/api/files.py +0 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/core/api/init.py +0 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/core/api/metrics.py +0 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/core/api/orgs.py +0 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/core/api/packages.py +0 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/core/api/quota.py +0 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/core/api/rates.py +0 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/core/api/repos.py +0 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/core/api/status.py +0 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/core/api/upstreams.py +0 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/core/api/user.py +0 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/core/api/version.py +0 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/core/config.py +0 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/core/download.py +0 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/core/keyring.py +0 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/core/ratelimits.py +0 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/core/rest.py +0 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/core/tests/__init__.py +0 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/core/tests/test_download.py +0 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/core/tests/test_init.py +0 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/core/tests/test_keyring.py +0 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/core/tests/test_rest.py +0 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/core/tests/test_version.py +0 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/core/utils.py +0 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/core/version.py +0 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/data/config.ini +0 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/data/credentials.ini +0 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/templates/__init__.py +0 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/templates/auth_error.html +0 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/templates/auth_success.html +0 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli.egg-info/SOURCES.txt +0 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli.egg-info/dependency_links.txt +0 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli.egg-info/entry_points.txt +0 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli.egg-info/not-zip-safe +0 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli.egg-info/requires.txt +0 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli.egg-info/top_level.txt +0 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/setup.cfg +0 -0
- {cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/setup.py +0 -0
|
@@ -42,7 +42,7 @@ def list_dependencies(ctx, opts, owner_repo_package):
|
|
|
42
42
|
for the package format yet.
|
|
43
43
|
|
|
44
44
|
- OWNER/REPO/PACKAGE: Specify the OWNER namespace (i.e. user or org), the
|
|
45
|
-
REPO name where the package is stored, and the PACKAGE name (identifier) of the
|
|
45
|
+
REPO name where the package is stored, and the PACKAGE name (identifier/slug) of the
|
|
46
46
|
package itself. All separated by a slash.
|
|
47
47
|
|
|
48
48
|
Example: 'your-org/awesome-repo/better-pkg'.
|
|
@@ -7,6 +7,7 @@ import click
|
|
|
7
7
|
|
|
8
8
|
from ...core.api.distros import list_distros
|
|
9
9
|
from ...core.api.packages import get_package_format_names_with_distros, list_packages
|
|
10
|
+
from ...core.pagination import paginate_results
|
|
10
11
|
from .. import command, decorators, utils, validators
|
|
11
12
|
from ..exceptions import handle_api_exceptions
|
|
12
13
|
from ..utils import maybe_spinner
|
|
@@ -156,7 +157,7 @@ def entitlements_(*args, **kwargs): # pylint: disable=missing-docstring
|
|
|
156
157
|
help=("Sort packages by field. Prefix with '-' for descending order."),
|
|
157
158
|
)
|
|
158
159
|
@click.pass_context
|
|
159
|
-
def packages(ctx, opts, owner_repo, page, page_size, query, sort):
|
|
160
|
+
def packages(ctx, opts, owner_repo, page, page_size, query, sort, show_all):
|
|
160
161
|
"""
|
|
161
162
|
List packages for a repository.
|
|
162
163
|
|
|
@@ -217,11 +218,13 @@ def packages(ctx, opts, owner_repo, page, page_size, query, sort):
|
|
|
217
218
|
context_msg = "Failed to get list of packages!"
|
|
218
219
|
with handle_api_exceptions(ctx, opts=opts, context_msg=context_msg):
|
|
219
220
|
with maybe_spinner(opts):
|
|
220
|
-
packages_, page_info =
|
|
221
|
-
|
|
222
|
-
|
|
221
|
+
packages_, page_info = paginate_results(
|
|
222
|
+
list_packages,
|
|
223
|
+
show_all=show_all,
|
|
223
224
|
page=page,
|
|
224
225
|
page_size=page_size,
|
|
226
|
+
owner=owner,
|
|
227
|
+
repo=repo,
|
|
225
228
|
query=query,
|
|
226
229
|
sort=sort,
|
|
227
230
|
)
|
|
@@ -256,9 +259,12 @@ def packages(ctx, opts, owner_repo, page, page_size, query, sort):
|
|
|
256
259
|
click.echo()
|
|
257
260
|
|
|
258
261
|
num_results = len(packages_)
|
|
259
|
-
list_suffix = "package%s
|
|
262
|
+
list_suffix = "package%s" % ("s" if num_results != 1 else "")
|
|
260
263
|
utils.pretty_print_list_info(
|
|
261
|
-
num_results=num_results,
|
|
264
|
+
num_results=num_results,
|
|
265
|
+
page_info=None if show_all else page_info,
|
|
266
|
+
suffix=f"{list_suffix} retrieved" if show_all else f"{list_suffix} visible",
|
|
267
|
+
show_all=show_all,
|
|
262
268
|
)
|
|
263
269
|
|
|
264
270
|
|
|
@@ -276,7 +282,7 @@ def packages(ctx, opts, owner_repo, page, page_size, query, sort):
|
|
|
276
282
|
required=False,
|
|
277
283
|
)
|
|
278
284
|
@click.pass_context
|
|
279
|
-
def repos(ctx, opts, owner_repo, page, page_size):
|
|
285
|
+
def repos(ctx, opts, owner_repo, page, page_size, show_all):
|
|
280
286
|
"""
|
|
281
287
|
List repositories for a namespace (owner).
|
|
282
288
|
|
|
@@ -5,6 +5,7 @@ import json
|
|
|
5
5
|
import click
|
|
6
6
|
|
|
7
7
|
from ....core.api import orgs as api
|
|
8
|
+
from ....core.pagination import paginate_results
|
|
8
9
|
from ... import command, decorators, utils, validators
|
|
9
10
|
from ...exceptions import handle_api_exceptions
|
|
10
11
|
from ...utils import (
|
|
@@ -19,7 +20,6 @@ from .command import policy
|
|
|
19
20
|
|
|
20
21
|
def print_license_policies(policies):
|
|
21
22
|
"""Print license policies as a table or output in another format."""
|
|
22
|
-
|
|
23
23
|
headers = [
|
|
24
24
|
"Name",
|
|
25
25
|
"Description",
|
|
@@ -57,10 +57,6 @@ def print_license_policies(policies):
|
|
|
57
57
|
utils.pretty_print_table(headers, rows)
|
|
58
58
|
click.echo()
|
|
59
59
|
|
|
60
|
-
num_results = len(rows)
|
|
61
|
-
list_suffix = "license polic%s" % ("y" if num_results == 1 else "ies")
|
|
62
|
-
utils.pretty_print_list_info(num_results=num_results, suffix=list_suffix)
|
|
63
|
-
|
|
64
60
|
|
|
65
61
|
@policy.group(cls=command.AliasGroup, name="license", aliases=[])
|
|
66
62
|
@decorators.common_cli_config_options
|
|
@@ -86,7 +82,7 @@ def licence(*args, **kwargs):
|
|
|
86
82
|
"owner", metavar="OWNER", callback=validators.validate_owner, required=True
|
|
87
83
|
)
|
|
88
84
|
@click.pass_context
|
|
89
|
-
def ls(ctx, opts, owner, page, page_size):
|
|
85
|
+
def ls(ctx, opts, owner, page, page_size, show_all):
|
|
90
86
|
"""
|
|
91
87
|
List license policies.
|
|
92
88
|
|
|
@@ -111,8 +107,8 @@ def ls(ctx, opts, owner, page, page_size):
|
|
|
111
107
|
context_msg = "Failed to get license policies!"
|
|
112
108
|
with handle_api_exceptions(ctx, opts=opts, context_msg=context_msg):
|
|
113
109
|
with maybe_spinner(opts):
|
|
114
|
-
policies, page_info =
|
|
115
|
-
|
|
110
|
+
policies, page_info = paginate_results(
|
|
111
|
+
api.list_license_policies, show_all, page, page_size, owner=owner
|
|
116
112
|
)
|
|
117
113
|
|
|
118
114
|
click.secho("OK", fg="green", err=use_stderr)
|
|
@@ -122,6 +118,17 @@ def ls(ctx, opts, owner, page, page_size):
|
|
|
122
118
|
|
|
123
119
|
print_license_policies(policies)
|
|
124
120
|
|
|
121
|
+
click.echo()
|
|
122
|
+
|
|
123
|
+
num_results = len(policies)
|
|
124
|
+
list_suffix = "license polic%s" % ("y" if num_results == 1 else "ies")
|
|
125
|
+
utils.pretty_print_list_info(
|
|
126
|
+
num_results=num_results,
|
|
127
|
+
page_info=None if show_all else page_info,
|
|
128
|
+
suffix=list_suffix,
|
|
129
|
+
show_all=show_all,
|
|
130
|
+
)
|
|
131
|
+
|
|
125
132
|
|
|
126
133
|
@licence.command(aliases=["new"])
|
|
127
134
|
@decorators.common_cli_config_options
|
{cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/cli/commands/policy/vulnerability.py
RENAMED
|
@@ -5,6 +5,7 @@ import json
|
|
|
5
5
|
import click
|
|
6
6
|
|
|
7
7
|
from ....core.api import orgs as api
|
|
8
|
+
from ....core.pagination import paginate_results
|
|
8
9
|
from ... import command, decorators, utils, validators
|
|
9
10
|
from ...exceptions import handle_api_exceptions
|
|
10
11
|
from ...utils import fmt_bool, fmt_datetime, maybe_spinner, maybe_truncate_string
|
|
@@ -46,10 +47,6 @@ def print_vulnerability_policies(policies):
|
|
|
46
47
|
utils.pretty_print_table(headers, rows, title="Vulnerability Policies")
|
|
47
48
|
click.echo()
|
|
48
49
|
|
|
49
|
-
num_results = len(rows)
|
|
50
|
-
list_suffix = "vulnerability polic%s" % ("y" if num_results == 1 else "ies")
|
|
51
|
-
utils.pretty_print_list_info(num_results=num_results, suffix=list_suffix)
|
|
52
|
-
|
|
53
50
|
|
|
54
51
|
@policy.group(cls=command.AliasGroup, name="vulnerability", aliases=[])
|
|
55
52
|
@decorators.common_cli_config_options
|
|
@@ -75,7 +72,7 @@ def vulnerability(*args, **kwargs):
|
|
|
75
72
|
"owner", metavar="OWNER", callback=validators.validate_owner, required=True
|
|
76
73
|
)
|
|
77
74
|
@click.pass_context
|
|
78
|
-
def ls(ctx, opts, owner, page, page_size):
|
|
75
|
+
def ls(ctx, opts, owner, page, page_size, show_all):
|
|
79
76
|
"""
|
|
80
77
|
List vulnerability policies.
|
|
81
78
|
|
|
@@ -100,8 +97,8 @@ def ls(ctx, opts, owner, page, page_size):
|
|
|
100
97
|
context_msg = "Failed to get package vulnerability policies!"
|
|
101
98
|
with handle_api_exceptions(ctx, opts=opts, context_msg=context_msg):
|
|
102
99
|
with maybe_spinner(opts):
|
|
103
|
-
policies, page_info =
|
|
104
|
-
|
|
100
|
+
policies, page_info = paginate_results(
|
|
101
|
+
api.list_vulnerability_policies, show_all, page, page_size, owner=owner
|
|
105
102
|
)
|
|
106
103
|
|
|
107
104
|
click.secho("OK", fg="green", err=use_stderr)
|
|
@@ -111,6 +108,17 @@ def ls(ctx, opts, owner, page, page_size):
|
|
|
111
108
|
|
|
112
109
|
print_vulnerability_policies(policies)
|
|
113
110
|
|
|
111
|
+
click.echo()
|
|
112
|
+
|
|
113
|
+
num_results = len(policies)
|
|
114
|
+
list_suffix = "vulnerability polic%s" % ("y" if num_results == 1 else "ies")
|
|
115
|
+
utils.pretty_print_list_info(
|
|
116
|
+
num_results=num_results,
|
|
117
|
+
page_info=None if show_all else page_info,
|
|
118
|
+
suffix=list_suffix,
|
|
119
|
+
show_all=show_all,
|
|
120
|
+
)
|
|
121
|
+
|
|
114
122
|
|
|
115
123
|
@vulnerability.command(aliases=["new"])
|
|
116
124
|
@decorators.common_cli_config_options
|
|
@@ -6,13 +6,14 @@ from operator import itemgetter
|
|
|
6
6
|
import click
|
|
7
7
|
|
|
8
8
|
from ...core.api import repos as api
|
|
9
|
+
from ...core.pagination import paginate_results
|
|
9
10
|
from .. import command, decorators, utils, validators
|
|
10
11
|
from ..exceptions import handle_api_exceptions
|
|
11
12
|
from ..utils import maybe_spinner
|
|
12
13
|
from .main import main
|
|
13
14
|
|
|
14
15
|
|
|
15
|
-
def print_repositories(opts, data, page_info=None, show_list_info=True):
|
|
16
|
+
def print_repositories(opts, data, page_info=None, show_list_info=True, show_all=False):
|
|
16
17
|
"""Print repositories as a table or output in another format."""
|
|
17
18
|
headers = [
|
|
18
19
|
"Name",
|
|
@@ -48,10 +49,16 @@ def print_repositories(opts, data, page_info=None, show_list_info=True):
|
|
|
48
49
|
|
|
49
50
|
click.echo()
|
|
50
51
|
|
|
52
|
+
if not show_list_info:
|
|
53
|
+
return
|
|
54
|
+
|
|
51
55
|
num_results = len(data)
|
|
52
|
-
list_suffix = "repositor%s
|
|
56
|
+
list_suffix = "repositor%s" % ("ies" if num_results != 1 else "y")
|
|
53
57
|
utils.pretty_print_list_info(
|
|
54
|
-
num_results=num_results,
|
|
58
|
+
num_results=num_results,
|
|
59
|
+
page_info=None if show_all else page_info,
|
|
60
|
+
suffix=f"{list_suffix} retrieved" if show_all else f"{list_suffix} visible",
|
|
61
|
+
show_all=show_all,
|
|
55
62
|
)
|
|
56
63
|
|
|
57
64
|
|
|
@@ -83,7 +90,7 @@ def repositories(ctx, opts): # pylink: disable=unused-argument
|
|
|
83
90
|
required=False,
|
|
84
91
|
)
|
|
85
92
|
@click.pass_context
|
|
86
|
-
def get(ctx, opts, owner_repo, page, page_size):
|
|
93
|
+
def get(ctx, opts, owner_repo, page, page_size, show_all):
|
|
87
94
|
"""
|
|
88
95
|
List repositories for a namespace (owner).
|
|
89
96
|
|
|
@@ -96,30 +103,34 @@ def get(ctx, opts, owner_repo, page, page_size):
|
|
|
96
103
|
If OWNER isn't specified it'll default to the currently authenticated user
|
|
97
104
|
(if any). If you're unauthenticated, no results will be returned.
|
|
98
105
|
"""
|
|
99
|
-
# Use stderr for messages if the output is something else (e.g.
|
|
106
|
+
# Use stderr for messages if the output is something else (e.g. JSON)
|
|
100
107
|
use_stderr = opts.output != "pretty"
|
|
101
108
|
|
|
102
|
-
click.echo("Getting list of repositories ... ", nl=False, err=use_stderr)
|
|
103
|
-
|
|
104
109
|
if isinstance(owner_repo, list):
|
|
105
110
|
if len(owner_repo) == 1:
|
|
106
111
|
owner = owner_repo[0]
|
|
107
112
|
repo = None
|
|
108
113
|
else:
|
|
109
114
|
owner, repo = owner_repo
|
|
110
|
-
|
|
115
|
+
elif isinstance(owner_repo, str):
|
|
116
|
+
repo = None
|
|
117
|
+
owner = owner_repo or None
|
|
118
|
+
else:
|
|
119
|
+
owner = None
|
|
111
120
|
repo = None
|
|
112
121
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
122
|
+
if show_all and repo:
|
|
123
|
+
raise click.UsageError(
|
|
124
|
+
"The --show-all option cannot be used when specifying a single repository (OWNER/REPO). Omit the repository slug or remove --show-all."
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
click.echo("Getting list of repositories ... ", nl=False, err=use_stderr)
|
|
117
128
|
|
|
118
129
|
context_msg = "Failed to get list of repositories!"
|
|
119
130
|
with handle_api_exceptions(ctx, opts=opts, context_msg=context_msg):
|
|
120
131
|
with maybe_spinner(opts):
|
|
121
|
-
repos_, page_info =
|
|
122
|
-
|
|
132
|
+
repos_, page_info = paginate_results(
|
|
133
|
+
api.list_repos, show_all, page, page_size, owner=owner, repo=repo
|
|
123
134
|
)
|
|
124
135
|
|
|
125
136
|
click.secho("OK", fg="green", err=use_stderr)
|
|
@@ -128,7 +139,11 @@ def get(ctx, opts, owner_repo, page, page_size):
|
|
|
128
139
|
return
|
|
129
140
|
|
|
130
141
|
print_repositories(
|
|
131
|
-
opts=opts,
|
|
142
|
+
opts=opts,
|
|
143
|
+
data=repos_,
|
|
144
|
+
show_list_info=True,
|
|
145
|
+
page_info=page_info,
|
|
146
|
+
show_all=show_all,
|
|
132
147
|
)
|
|
133
148
|
|
|
134
149
|
|
|
@@ -192,7 +207,10 @@ def create(ctx, opts, owner, repo_config_file):
|
|
|
192
207
|
|
|
193
208
|
click.secho("OK", fg="green", err=use_stderr)
|
|
194
209
|
|
|
195
|
-
|
|
210
|
+
if utils.maybe_print_as_json(opts, [repository]):
|
|
211
|
+
return
|
|
212
|
+
|
|
213
|
+
print_repositories(opts=opts, data=[repository], show_list_info=True)
|
|
196
214
|
|
|
197
215
|
|
|
198
216
|
@repositories.command()
|
|
@@ -252,7 +270,10 @@ def update(ctx, opts, owner_repo, repo_config_file):
|
|
|
252
270
|
|
|
253
271
|
click.secho("OK", fg="green", err=use_stderr)
|
|
254
272
|
|
|
255
|
-
|
|
273
|
+
if utils.maybe_print_as_json(opts, [repository]):
|
|
274
|
+
return
|
|
275
|
+
|
|
276
|
+
print_repositories(opts=opts, data=[repository], show_list_info=True)
|
|
256
277
|
|
|
257
278
|
|
|
258
279
|
@repositories.command(aliases=["rm"])
|
|
@@ -5,6 +5,7 @@ import json
|
|
|
5
5
|
import click
|
|
6
6
|
|
|
7
7
|
from ...core.api import upstreams as api
|
|
8
|
+
from ...core.pagination import paginate_results
|
|
8
9
|
from .. import command, decorators, utils, validators
|
|
9
10
|
from ..exceptions import handle_api_exceptions
|
|
10
11
|
from ..utils import (
|
|
@@ -37,7 +38,7 @@ UPSTREAM_FORMATS = [
|
|
|
37
38
|
]
|
|
38
39
|
|
|
39
40
|
|
|
40
|
-
def print_upstreams(upstreams, upstream_fmt):
|
|
41
|
+
def print_upstreams(upstreams, upstream_fmt, page_info=None, show_all=False):
|
|
41
42
|
"""Print upstreams as a table or output in another format."""
|
|
42
43
|
|
|
43
44
|
def build_row(u):
|
|
@@ -115,9 +116,14 @@ def print_upstreams(upstreams, upstream_fmt):
|
|
|
115
116
|
utils.pretty_print_table(headers, rows)
|
|
116
117
|
click.echo()
|
|
117
118
|
|
|
118
|
-
num_results = len(
|
|
119
|
+
num_results = len(upstreams)
|
|
119
120
|
list_suffix = "upstream%s" % ("" if num_results == 1 else "s")
|
|
120
|
-
utils.pretty_print_list_info(
|
|
121
|
+
utils.pretty_print_list_info(
|
|
122
|
+
num_results=num_results,
|
|
123
|
+
page_info=None if show_all else page_info,
|
|
124
|
+
suffix=list_suffix,
|
|
125
|
+
show_all=show_all,
|
|
126
|
+
)
|
|
121
127
|
|
|
122
128
|
|
|
123
129
|
@main.group(cls=command.AliasGroup, name="upstream", aliases=[])
|
|
@@ -164,7 +170,7 @@ def build_upstream_list_command(upstream_fmt):
|
|
|
164
170
|
"owner_repo", metavar="OWNER/REPO", callback=validators.validate_owner_repo
|
|
165
171
|
)
|
|
166
172
|
@click.pass_context
|
|
167
|
-
def func(ctx, opts, owner_repo, page, page_size):
|
|
173
|
+
def func(ctx, opts, owner_repo, page, page_size, show_all):
|
|
168
174
|
owner, repo = owner_repo
|
|
169
175
|
|
|
170
176
|
# Use stderr for messages if the output is something else (e.g. # JSON)
|
|
@@ -176,12 +182,14 @@ def build_upstream_list_command(upstream_fmt):
|
|
|
176
182
|
context_msg = "Failed to get upstreams!"
|
|
177
183
|
with handle_api_exceptions(ctx, opts=opts, context_msg=context_msg):
|
|
178
184
|
with maybe_spinner(opts):
|
|
179
|
-
upstreams, page_info =
|
|
185
|
+
upstreams, page_info = paginate_results(
|
|
186
|
+
api.list_upstreams,
|
|
187
|
+
show_all,
|
|
188
|
+
page,
|
|
189
|
+
page_size,
|
|
180
190
|
owner=owner,
|
|
181
191
|
repo=repo,
|
|
182
192
|
upstream_format=upstream_fmt,
|
|
183
|
-
page=page,
|
|
184
|
-
page_size=page_size,
|
|
185
193
|
)
|
|
186
194
|
|
|
187
195
|
if not use_stderr:
|
|
@@ -190,7 +198,7 @@ def build_upstream_list_command(upstream_fmt):
|
|
|
190
198
|
if utils.maybe_print_as_json(opts, upstreams, page_info):
|
|
191
199
|
return
|
|
192
200
|
|
|
193
|
-
print_upstreams(upstreams, upstream_fmt)
|
|
201
|
+
print_upstreams(upstreams, upstream_fmt, page_info, show_all)
|
|
194
202
|
|
|
195
203
|
func.__doc__ = f"""
|
|
196
204
|
List {upstream_fmt} upstreams for a repository.
|
|
@@ -4,8 +4,10 @@ import functools
|
|
|
4
4
|
|
|
5
5
|
import click
|
|
6
6
|
|
|
7
|
+
from cloudsmith_cli.cli import validators
|
|
8
|
+
|
|
7
9
|
from ..core.api.init import initialise_api as _initialise_api
|
|
8
|
-
from . import config, utils
|
|
10
|
+
from . import config, utils
|
|
9
11
|
|
|
10
12
|
|
|
11
13
|
def report_retry(seconds, context=None):
|
|
@@ -144,6 +146,14 @@ def common_cli_output_options(f):
|
|
|
144
146
|
def common_cli_list_options(f):
|
|
145
147
|
"""Add common list options to commands."""
|
|
146
148
|
|
|
149
|
+
@click.option(
|
|
150
|
+
"-l",
|
|
151
|
+
"--page-size",
|
|
152
|
+
default=30,
|
|
153
|
+
type=int,
|
|
154
|
+
help="The amount of items to view per page for lists.",
|
|
155
|
+
callback=validators.validate_page_size,
|
|
156
|
+
)
|
|
147
157
|
@click.option(
|
|
148
158
|
"-p",
|
|
149
159
|
"--page",
|
|
@@ -153,18 +163,20 @@ def common_cli_list_options(f):
|
|
|
153
163
|
callback=validators.validate_page,
|
|
154
164
|
)
|
|
155
165
|
@click.option(
|
|
156
|
-
"-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
callback=validators.validate_page_size,
|
|
162
|
-
)
|
|
166
|
+
"--show-all",
|
|
167
|
+
default=False,
|
|
168
|
+
is_flag=True,
|
|
169
|
+
help="Show all results. Cannot be used with --page (-p) or --page-size (-l).",
|
|
170
|
+
) # Validation performed post-parse for order-independence.
|
|
163
171
|
@click.pass_context
|
|
164
172
|
@functools.wraps(f)
|
|
165
173
|
def wrapper(ctx, *args, **kwargs):
|
|
166
174
|
# pylint: disable=missing-docstring
|
|
167
175
|
opts = config.get_or_create_options(ctx)
|
|
176
|
+
# Order-independent validation: perform after all options parsed.
|
|
177
|
+
show_all = kwargs.get("show_all")
|
|
178
|
+
if show_all:
|
|
179
|
+
validators.enforce_show_all_exclusive(ctx)
|
|
168
180
|
kwargs["opts"] = opts
|
|
169
181
|
return ctx.invoke(f, *args, **kwargs)
|
|
170
182
|
|
|
@@ -125,6 +125,22 @@ def test_license_policy_commands(runner, organization, tmp_path):
|
|
|
125
125
|
assert "Getting license policies ... OK" in result.output
|
|
126
126
|
assert_output_matches_policy_config(result.output, policy_config_file_path)
|
|
127
127
|
|
|
128
|
+
# Minimal show-all success
|
|
129
|
+
result = runner.invoke(
|
|
130
|
+
ls, args=[organization, "--show-all"], catch_exceptions=False
|
|
131
|
+
)
|
|
132
|
+
assert result.exit_code == 0
|
|
133
|
+
assert "Getting license policies" in result.output
|
|
134
|
+
assert "Invalid value for '--show-all'" not in result.output
|
|
135
|
+
|
|
136
|
+
# Conflict: show-all with explicit page
|
|
137
|
+
conflict = runner.invoke(
|
|
138
|
+
ls, args=[organization, "--page", "1", "--show-all"], catch_exceptions=False
|
|
139
|
+
)
|
|
140
|
+
assert conflict.exit_code != 0
|
|
141
|
+
assert "Invalid value for '--show-all'" in conflict.output
|
|
142
|
+
assert "Cannot be used with --page (-p) or --page-size (-l)." in conflict.output
|
|
143
|
+
|
|
128
144
|
# Change the values in the config file
|
|
129
145
|
policy_config_file_path = create_license_policy_config_file(
|
|
130
146
|
directory=tmp_path,
|
|
@@ -127,6 +127,24 @@ def test_vulnerability_policy_commands(runner, organization, tmp_path):
|
|
|
127
127
|
assert "Getting vulnerability policies ... OK" in result.output
|
|
128
128
|
assert_output_matches_policy_config(result.output, policy_config_file_path)
|
|
129
129
|
|
|
130
|
+
# Minimal show-all success (no pagination args besides flag)
|
|
131
|
+
result = runner.invoke(
|
|
132
|
+
ls, args=[organization, "--show-all"], catch_exceptions=False
|
|
133
|
+
)
|
|
134
|
+
assert result.exit_code == 0
|
|
135
|
+
assert "Getting vulnerability policies" in result.output
|
|
136
|
+
assert "Invalid value for '--show-all'" not in result.output
|
|
137
|
+
|
|
138
|
+
# Conflict: show-all with explicit page
|
|
139
|
+
conflict = runner.invoke(
|
|
140
|
+
ls,
|
|
141
|
+
args=[organization, "--show-all", "--page-size", "2"],
|
|
142
|
+
catch_exceptions=False,
|
|
143
|
+
)
|
|
144
|
+
assert conflict.exit_code != 0
|
|
145
|
+
assert "Invalid value for '--show-all'" in conflict.output
|
|
146
|
+
assert "Cannot be used with --page (-p) or --page-size (-l)." in conflict.output
|
|
147
|
+
|
|
130
148
|
# Change the values in the config file
|
|
131
149
|
policy_config_file_path = create_vulnerability_policy_config_file(
|
|
132
150
|
directory=tmp_path,
|
|
@@ -50,6 +50,13 @@ def test_push_and_delete_raw_package(
|
|
|
50
50
|
small_file_data = data[0]
|
|
51
51
|
assert small_file_data["filename"] == pkg_file.name
|
|
52
52
|
|
|
53
|
+
# List packages with --show-all flag
|
|
54
|
+
result = runner.invoke(
|
|
55
|
+
list_, args=["pkgs", org_repo, "--show-all"], catch_exceptions=False
|
|
56
|
+
)
|
|
57
|
+
assert "Getting list of packages ... OK" in result.output
|
|
58
|
+
assert "Results: 1 package retrieved" in result.output
|
|
59
|
+
|
|
53
60
|
# Wait for the package to sync.
|
|
54
61
|
org_repo_package = f"{org_repo}/{small_file_data['slug']}"
|
|
55
62
|
for _ in range(10):
|
{cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/cli/tests/commands/test_repos.py
RENAMED
|
@@ -2,6 +2,7 @@ import json
|
|
|
2
2
|
|
|
3
3
|
import pytest
|
|
4
4
|
|
|
5
|
+
from ...commands.list_ import repos as list_repos
|
|
5
6
|
from ...commands.repos import create, delete, get, update
|
|
6
7
|
from ..utils import random_str
|
|
7
8
|
|
|
@@ -119,6 +120,21 @@ def test_repos_commands(runner, organization, tmp_path):
|
|
|
119
120
|
result.output, organization, repo_config_file_path
|
|
120
121
|
)
|
|
121
122
|
|
|
123
|
+
# Demonstrate list repos with --show-all succeeds (no pagination args).
|
|
124
|
+
result = runner.invoke(
|
|
125
|
+
list_repos, [organization, "--show-all"], catch_exceptions=False
|
|
126
|
+
)
|
|
127
|
+
assert result.exit_code == 0
|
|
128
|
+
assert "Getting list of repositories ... OK" in result.output
|
|
129
|
+
|
|
130
|
+
# Show that --show-all with an explicit page conflicts.
|
|
131
|
+
conflict = runner.invoke(
|
|
132
|
+
list_repos, [organization, "--show-all", "--page", "2"], catch_exceptions=False
|
|
133
|
+
)
|
|
134
|
+
assert conflict.exit_code != 0
|
|
135
|
+
assert "Invalid value for '--show-all'" in conflict.output
|
|
136
|
+
assert "Cannot be used with --page (-p) or --page-size (-l)." in conflict.output
|
|
137
|
+
|
|
122
138
|
# Change the repository description in the repo config file.
|
|
123
139
|
repository_description = random_str()
|
|
124
140
|
repo_config_file_path = create_repo_config_file(
|
|
@@ -134,6 +150,14 @@ def test_repos_commands(runner, organization, tmp_path):
|
|
|
134
150
|
update, [owner_slash_repo, str(repo_config_file_path)], catch_exceptions=False
|
|
135
151
|
)
|
|
136
152
|
assert result.exit_code == 0
|
|
153
|
+
assert (
|
|
154
|
+
"Updating "
|
|
155
|
+
+ repository_slug
|
|
156
|
+
+ " repository in the "
|
|
157
|
+
+ organization
|
|
158
|
+
+ " namespace ...OK"
|
|
159
|
+
in result.output
|
|
160
|
+
)
|
|
137
161
|
assert "Results: 1 repository visible" in result.output
|
|
138
162
|
assert_output_is_equal_to_repo_config(
|
|
139
163
|
result.output, organization, repo_config_file_path
|
{cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/cli/tests/commands/test_upstream.py
RENAMED
|
@@ -71,6 +71,36 @@ def test_upstream_commands(
|
|
|
71
71
|
assert result_data["name"] == upstream_config["name"]
|
|
72
72
|
assert result_data["upstream_url"] == upstream_config["upstream_url"]
|
|
73
73
|
|
|
74
|
+
# Minimal show-all success (no pagination args besides flag)
|
|
75
|
+
show_all = runner.invoke(
|
|
76
|
+
upstream,
|
|
77
|
+
args=[upstream_format, "ls", org_repo, "--show-all", "-F", "json"],
|
|
78
|
+
catch_exceptions=False,
|
|
79
|
+
)
|
|
80
|
+
assert show_all.exit_code == 0
|
|
81
|
+
show_all_data = json.loads(show_all.output)["data"]
|
|
82
|
+
assert len(show_all_data) == 1 # Should return the same single upstream
|
|
83
|
+
assert "Invalid value for '--show-all'" not in show_all.output
|
|
84
|
+
|
|
85
|
+
# Conflict: show-all with explicit page number
|
|
86
|
+
conflict = runner.invoke(
|
|
87
|
+
upstream,
|
|
88
|
+
args=[
|
|
89
|
+
upstream_format,
|
|
90
|
+
"ls",
|
|
91
|
+
org_repo,
|
|
92
|
+
"--show-all",
|
|
93
|
+
"--page",
|
|
94
|
+
"1",
|
|
95
|
+
"-F",
|
|
96
|
+
"json",
|
|
97
|
+
],
|
|
98
|
+
catch_exceptions=False,
|
|
99
|
+
)
|
|
100
|
+
assert conflict.exit_code != 0
|
|
101
|
+
assert "Invalid value for '--show-all'" in conflict.output
|
|
102
|
+
assert "Cannot be used with --page (-p) or --page-size (-l)." in conflict.output
|
|
103
|
+
|
|
74
104
|
slug_perm = result_data["slug_perm"]
|
|
75
105
|
assert slug_perm
|
|
76
106
|
org_repo_slug_perm = f"{org_repo}/{slug_perm}"
|
|
@@ -19,32 +19,38 @@ def make_user_agent(prefix=None):
|
|
|
19
19
|
return f"cloudsmith-cli/{prefix} cli:{get_cli_version()} api:{get_api_version()}"
|
|
20
20
|
|
|
21
21
|
|
|
22
|
-
def pretty_print_list_info(num_results, page_info=None, suffix=
|
|
23
|
-
"""
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
22
|
+
def pretty_print_list_info(num_results, page_info=None, suffix="", show_all=False):
|
|
23
|
+
"""Print information about list results."""
|
|
24
|
+
if show_all:
|
|
25
|
+
click.echo(
|
|
26
|
+
"Results: %(num_results)d %(suffix)s"
|
|
27
|
+
% {
|
|
28
|
+
"num_results": num_results,
|
|
29
|
+
"suffix": suffix,
|
|
30
|
+
}
|
|
31
|
+
)
|
|
32
|
+
elif page_info and page_info.page is not None and page_info.page_size is not None:
|
|
33
|
+
start = (page_info.page - 1) * page_info.page_size + 1
|
|
34
|
+
end = min(start + num_results - 1, page_info.count or 0)
|
|
35
|
+
click.echo(
|
|
36
|
+
"Results: %(start)d-%(end)d (%(count)d) of %(total)d %(suffix)s "
|
|
37
|
+
"(page: %(page)d/%(pages)d, page size: %(page_size)d)"
|
|
38
|
+
% {
|
|
39
|
+
"start": start,
|
|
40
|
+
"end": end,
|
|
41
|
+
"count": num_results,
|
|
42
|
+
"total": page_info.count or 0,
|
|
43
|
+
"suffix": suffix,
|
|
44
|
+
"page": page_info.page,
|
|
45
|
+
"pages": page_info.page_total or 1,
|
|
46
|
+
"page_size": page_info.page_size,
|
|
47
|
+
}
|
|
48
|
+
)
|
|
36
49
|
else:
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
"Results: %(range_results)s %(suffix)s%(page_info)s"
|
|
42
|
-
% {
|
|
43
|
-
"range_results": range_results_text,
|
|
44
|
-
"page_info": " (%s)" % page_info_text if page_info_text else "",
|
|
45
|
-
"suffix": suffix or "item(s)",
|
|
46
|
-
}
|
|
47
|
-
)
|
|
50
|
+
click.echo(
|
|
51
|
+
"Results: %(num_results)d %(suffix)s"
|
|
52
|
+
% {"num_results": num_results, "suffix": suffix}
|
|
53
|
+
)
|
|
48
54
|
|
|
49
55
|
|
|
50
56
|
def fmt_datetime(value):
|
|
@@ -4,6 +4,7 @@ import base64
|
|
|
4
4
|
from datetime import datetime
|
|
5
5
|
|
|
6
6
|
import click
|
|
7
|
+
from click.core import ParameterSource
|
|
7
8
|
|
|
8
9
|
from .types import ExpandPath
|
|
9
10
|
|
|
@@ -157,6 +158,40 @@ def validate_page_size(ctx, param, value):
|
|
|
157
158
|
return value
|
|
158
159
|
|
|
159
160
|
|
|
161
|
+
def enforce_show_all_exclusive(ctx):
|
|
162
|
+
"""Order-independent mutual exclusivity check for pagination options.
|
|
163
|
+
|
|
164
|
+
Raises click.BadParameter bound to the --show-all option if it was used
|
|
165
|
+
together with explicit --page or --page-size. "Explicit" means supplied
|
|
166
|
+
via command line, environment variable, or prompt (Click ParameterSource).
|
|
167
|
+
"""
|
|
168
|
+
show_all = ctx.params.get("show_all")
|
|
169
|
+
if not show_all:
|
|
170
|
+
return
|
|
171
|
+
|
|
172
|
+
explicit_sources = {
|
|
173
|
+
src
|
|
174
|
+
for src in (
|
|
175
|
+
ParameterSource.COMMANDLINE,
|
|
176
|
+
ParameterSource.ENVIRONMENT,
|
|
177
|
+
getattr(ParameterSource, "PROMPT", None),
|
|
178
|
+
)
|
|
179
|
+
if src is not None
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
page_explicit = ctx.get_parameter_source("page") in explicit_sources
|
|
183
|
+
size_explicit = ctx.get_parameter_source("page_size") in explicit_sources
|
|
184
|
+
|
|
185
|
+
if page_explicit or size_explicit:
|
|
186
|
+
show_all_param = next(
|
|
187
|
+
(p for p in ctx.command.params if p.name == "show_all"), None
|
|
188
|
+
)
|
|
189
|
+
raise click.BadParameter(
|
|
190
|
+
"Cannot be used with --page (-p) or --page-size (-l).",
|
|
191
|
+
param=show_all_param,
|
|
192
|
+
)
|
|
193
|
+
|
|
194
|
+
|
|
160
195
|
def validate_optional_timestamp(ctx, param, value):
|
|
161
196
|
"""Ensure that a valid value for a timestamp is used."""
|
|
162
197
|
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
"""Core pagination utilities."""
|
|
2
2
|
|
|
3
|
+
from typing import Any, Callable, List, Optional, Sequence, Tuple
|
|
4
|
+
|
|
5
|
+
MAX_PAGE_SIZE = 1000
|
|
6
|
+
|
|
3
7
|
|
|
4
8
|
class PageInfo:
|
|
5
9
|
"""Data for pagination results."""
|
|
@@ -73,3 +77,54 @@ class PageInfo:
|
|
|
73
77
|
info.page_total = int(headers["X-Pagination-PageTotal"])
|
|
74
78
|
|
|
75
79
|
return info
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def paginate_results(
|
|
83
|
+
api_function: Callable[..., Tuple[Sequence[Any], PageInfo]],
|
|
84
|
+
show_all: bool,
|
|
85
|
+
page: int,
|
|
86
|
+
page_size: int = MAX_PAGE_SIZE,
|
|
87
|
+
**kwargs: Any,
|
|
88
|
+
) -> Tuple[List[Any], PageInfo]:
|
|
89
|
+
"""Retrieve paginated results.
|
|
90
|
+
|
|
91
|
+
Behaviour:
|
|
92
|
+
- If ``show_all`` is False: perform a single paged request and return the
|
|
93
|
+
results plus the (possibly invalid) ``PageInfo``. Single-resource API
|
|
94
|
+
endpoints frequently omit pagination headers; we tolerate that here.
|
|
95
|
+
- If ``show_all`` is True: iterate all pages requesting ``MAX_PAGE_SIZE``.
|
|
96
|
+
Missing pagination headers during aggregation are treated as a user
|
|
97
|
+
misuse (e.g. attempting ``--show-all`` against a single-resource
|
|
98
|
+
endpoint) and raise a ``click.ClickException`` for consistent UX.
|
|
99
|
+
|
|
100
|
+
Raises:
|
|
101
|
+
click.ClickException: If pagination headers are absent while trying to
|
|
102
|
+
aggregate multiple pages with ``show_all``.
|
|
103
|
+
"""
|
|
104
|
+
if not show_all:
|
|
105
|
+
results, page_info = api_function(page=page, page_size=page_size, **kwargs)
|
|
106
|
+
# For single resource endpoints (e.g. repos_read) pagination headers may be absent.
|
|
107
|
+
# In that case we return the results with potentially invalid page_info (empty when serialized)
|
|
108
|
+
# rather than raising. Downstream pretty printers handle an invalid page_info gracefully.
|
|
109
|
+
return list(results), page_info
|
|
110
|
+
|
|
111
|
+
all_results: List[Any] = []
|
|
112
|
+
current_page = 1
|
|
113
|
+
last_page_info: Optional[PageInfo] = None
|
|
114
|
+
while True:
|
|
115
|
+
page_results, last_page_info = api_function(
|
|
116
|
+
page=current_page, page_size=MAX_PAGE_SIZE, **kwargs
|
|
117
|
+
)
|
|
118
|
+
if not last_page_info.is_valid:
|
|
119
|
+
# No pagination headers (single-resource endpoint). Treat as single page.
|
|
120
|
+
# Return accumulated results without raising; command-level validators
|
|
121
|
+
# handle misuse of --show-all with single-resource endpoints.
|
|
122
|
+
all_results.extend(page_results)
|
|
123
|
+
return all_results, last_page_info
|
|
124
|
+
all_results.extend(page_results)
|
|
125
|
+
|
|
126
|
+
if current_page >= last_page_info.page_total:
|
|
127
|
+
break
|
|
128
|
+
current_page += 1
|
|
129
|
+
|
|
130
|
+
return all_results, last_page_info
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
1.9.4
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
1.9.2
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/cli/commands/metrics/__init__.py
RENAMED
|
File without changes
|
{cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/cli/commands/metrics/command.py
RENAMED
|
File without changes
|
{cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/cli/commands/metrics/entitlements.py
RENAMED
|
File without changes
|
{cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/cli/commands/metrics/packages.py
RENAMED
|
File without changes
|
|
File without changes
|
{cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/cli/commands/policy/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/cli/tests/commands/policy/__init__.py
RENAMED
|
File without changes
|
{cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/cli/tests/commands/test_check.py
RENAMED
|
File without changes
|
{cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/cli/tests/commands/test_download.py
RENAMED
|
File without changes
|
{cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/cli/tests/commands/test_login.py
RENAMED
|
File without changes
|
{cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/cli/tests/commands/test_main.py
RENAMED
|
File without changes
|
{cloudsmith_cli-1.9.2 → cloudsmith_cli-1.9.4}/cloudsmith_cli/cli/tests/commands/test_tokens.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|