cloudsmith-cli 1.9.2__py2.py3-none-any.whl → 1.9.4__py2.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.
@@ -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 = list_packages(
221
- owner=owner,
222
- repo=repo,
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 visible" % ("s" if num_results != 1 else "")
262
+ list_suffix = "package%s" % ("s" if num_results != 1 else "")
260
263
  utils.pretty_print_list_info(
261
- num_results=num_results, page_info=page_info, suffix=list_suffix
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 = api.list_license_policies(
115
- owner=owner, page=page, page_size=page_size
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
@@ -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 = api.list_vulnerability_policies(
104
- owner=owner, page=page, page_size=page_size
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 visible" % ("ies" if num_results != 1 else "y")
56
+ list_suffix = "repositor%s" % ("ies" if num_results != 1 else "y")
53
57
  utils.pretty_print_list_info(
54
- num_results=num_results, page_info=page_info, suffix=list_suffix
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. # JSON)
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
- if isinstance(owner_repo, str):
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
- if owner_repo:
114
- owner = owner_repo
115
- else:
116
- owner = None
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 = api.list_repos(
122
- owner=owner, repo=repo, page=page, page_size=page_size
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, data=repos_, show_list_info=False, page_info=page_info
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
- print_repositories(opts=opts, data=[repository], show_list_info=False)
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
- print_repositories(opts=opts, data=[repository], show_list_info=False)
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(rows)
119
+ num_results = len(upstreams)
119
120
  list_suffix = "upstream%s" % ("" if num_results == 1 else "s")
120
- utils.pretty_print_list_info(num_results=num_results, suffix=list_suffix)
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 = api.list_upstreams(
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, validators
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
- "-l",
157
- "--page-size",
158
- default=30,
159
- type=int,
160
- help="The amount of items to view per page for lists.",
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):
@@ -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
@@ -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=None):
23
- """Pretty print list info, with pagination, for user display."""
24
- num_results_fg = "green" if num_results else "red"
25
- num_results_text = click.style(str(num_results), fg=num_results_fg)
26
-
27
- if page_info and page_info.is_valid:
28
- page_range = page_info.calculate_range(num_results)
29
- page_info_text = f"page: {click.style(str(page_info.page), bold=True)}/{click.style(str(page_info.page_total), bold=True)}, page size: {click.style(str(page_info.page_size), bold=True)}"
30
- range_results_text = "%(from)s-%(to)s (%(num_results)s) of %(total)s" % {
31
- "num_results": num_results_text,
32
- "from": click.style(str(page_range[0]), fg=num_results_fg),
33
- "to": click.style(str(page_range[1]), fg=num_results_fg),
34
- "total": click.style(str(page_info.count), fg=num_results_fg),
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
- page_info_text = ""
38
- range_results_text = num_results_text
39
-
40
- click.secho(
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
@@ -1 +1 @@
1
- 1.9.2
1
+ 1.9.4
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cloudsmith-cli
3
- Version: 1.9.2
3
+ Version: 1.9.4
4
4
  Summary: Cloudsmith Command-Line Interface (CLI)
5
5
  Home-page: https://github.com/cloudsmith-io/cloudsmith-cli
6
6
  Author: Cloudsmith Ltd
@@ -3,36 +3,36 @@ cloudsmith_cli/__main__.py,sha256=sWZCxOvdsp_Op1y4A7cyFVo-5fgQ667grmiy8FKX-5w,21
3
3
  cloudsmith_cli/cli/__init__.py,sha256=GK3VaqGyKB8vkN501vzSah_cirIorR5qQpVMry5wv7Y,34
4
4
  cloudsmith_cli/cli/command.py,sha256=CeIb75Vvv8GfQH5aDPq7znSWir5A6J1ZsyAQgToZWa4,2806
5
5
  cloudsmith_cli/cli/config.py,sha256=CuDlEQ7NHWP3kABeLrE_MZcPeCvwz5o58s8w9yRjv98,13131
6
- cloudsmith_cli/cli/decorators.py,sha256=y0RVM-4fGFE8q98hbKQVONqCs1gFgOPp_6oGCpVKqLU,10026
6
+ cloudsmith_cli/cli/decorators.py,sha256=XPVWrxKXDyV0cbJpd48fv69oTKbLo-UcXpcpClQmes0,10487
7
7
  cloudsmith_cli/cli/exceptions.py,sha256=OIDqBCOLutPxkG9VVx-Vhumj8pTxUdq1ITuWm1fcpP4,5382
8
8
  cloudsmith_cli/cli/saml.py,sha256=VluL-oM4mReXi0ycdFUQJQisNKo9limAiIjSVzGRBnM,3202
9
9
  cloudsmith_cli/cli/table.py,sha256=S03d5izcsz8keKYP3Ep1C4i3sEwYigjUUCSkBKPskHw,1530
10
10
  cloudsmith_cli/cli/types.py,sha256=89hPhNtUS1E6GnUxm_Lv_cj9OfNqI6G5s5gD-uRz1Dw,410
11
- cloudsmith_cli/cli/utils.py,sha256=aYeqovNZqNtYSrSrGRBs3hSyvZXvRTGxTtUQnHpZnxk,5861
12
- cloudsmith_cli/cli/validators.py,sha256=0x0zhnxo1GCLOp-A0Ys_QC0M1Sh-pMlAQWbIWHltHBM,7571
11
+ cloudsmith_cli/cli/utils.py,sha256=P-N08IBpmPO4SvMCAqGkoNCfjzOrqimVlvLAxEso6vM,5813
12
+ cloudsmith_cli/cli/validators.py,sha256=Ji6mygGSHxCrF9neo4PNzGnfXLXN9EUhNBEuTogE5xA,8732
13
13
  cloudsmith_cli/cli/webserver.py,sha256=okb3HgG4p83DW3qK3uWw6ph1hTBTLkaBeaBhCoAQEZw,8069
14
14
  cloudsmith_cli/cli/commands/__init__.py,sha256=vW6LrMnln5s0-fmsX-RVlcnUVl0ioSRaC8GP-fQAFsQ,352
15
15
  cloudsmith_cli/cli/commands/auth.py,sha256=mObKZWklR00aBwPfrTsDOecAS1IrpS9rty1V6rMi16k,2942
16
16
  cloudsmith_cli/cli/commands/check.py,sha256=greRcyhlNc6LWKh1SRjxJPiXa6X2GfMRynN9mNhRTfo,3704
17
17
  cloudsmith_cli/cli/commands/copy.py,sha256=kSQZZIW48fO6vS0hrve4wn0Pb0VvnllnI1MvW8Tvs8A,2525
18
18
  cloudsmith_cli/cli/commands/delete.py,sha256=8WGf8bKBidQu9HeAM3FrUFxXKouhNhjzlEN6IpRKTdg,1817
19
- cloudsmith_cli/cli/commands/dependencies.py,sha256=hwCVpJQak_AuLmtwvk1ZED-E8a0ZevnreG6RWG9UFy8,3409
19
+ cloudsmith_cli/cli/commands/dependencies.py,sha256=1IFMlFysWwm-S2R4GaBAlLJZMdoVJWJcxgT58MZ2Qww,3414
20
20
  cloudsmith_cli/cli/commands/docs.py,sha256=dBdYuR9hI8oxZ4B1Ax6Cqt2QWUe0llUDFmKZqFndP0Q,376
21
21
  cloudsmith_cli/cli/commands/download.py,sha256=GHF3slyJK3PRqbiGXdCwSGN4TOmKF5r9JRhydZZ4uMw,12292
22
22
  cloudsmith_cli/cli/commands/entitlements.py,sha256=d636rO_u1nRvpw12zsoDL8sKZZbT7Qzd65Pby4W5Iuc,27173
23
23
  cloudsmith_cli/cli/commands/help_.py,sha256=--_NwWZBZWfEnG6MzteaZO6u3IIlh3wufvGbh8JcSv4,226
24
- cloudsmith_cli/cli/commands/list_.py,sha256=CS8SeJ53BSo3PZKS0qiNJ0Md5jICqvjt56gUEGwT7o8,9775
24
+ cloudsmith_cli/cli/commands/list_.py,sha256=Rl8PKBFoJn2af9Y_kVWGoOW-R5gQU-fdx3NVCl7hoQE,10027
25
25
  cloudsmith_cli/cli/commands/login.py,sha256=i2a7kPsq1dUkY8ud6hTMFurV6bkYmxnDEJiXPD-_gXI,3101
26
26
  cloudsmith_cli/cli/commands/main.py,sha256=3KRh_uwdBxKfBSZugQ9y7LbZb3D0EtiB6PmYFCqeDG4,1896
27
27
  cloudsmith_cli/cli/commands/move.py,sha256=FqGZlGRKaK4SfVMhNEiW7xNOw0TEp9g0dj5fSU4tUjE,2850
28
28
  cloudsmith_cli/cli/commands/push.py,sha256=G0C_SEI8WHV2-Cpna0Bal7ISBYuPvq6DFXkSVDMJ8Xg,19157
29
29
  cloudsmith_cli/cli/commands/quarantine.py,sha256=i4ah9q7AsSJFlD-PKOguFOKlL4-v0WEPPWSAij2cujY,4485
30
- cloudsmith_cli/cli/commands/repos.py,sha256=YsBNVJOi3hy7a2_RPxTbHySD_zsyxgAxsfpMpeEFXyI,9284
30
+ cloudsmith_cli/cli/commands/repos.py,sha256=UIZcoMbWgaoOqs857d4a3ozvdsXFW8zaDCYyk7owW5o,9926
31
31
  cloudsmith_cli/cli/commands/resync.py,sha256=D14N5PXsYF0_y6DX65kqHj2jIXZ2QCfP_Su2eBRVZ0Q,2231
32
32
  cloudsmith_cli/cli/commands/status.py,sha256=tT4p1Swc5C7hs0yyHhjOwBdvoh0e-LzGqRaADECiecU,2090
33
33
  cloudsmith_cli/cli/commands/tags.py,sha256=n2huKp6smIBmO4VjQh-RzICRvE9oZCZIqjtTxvr9LMU,11228
34
34
  cloudsmith_cli/cli/commands/tokens.py,sha256=GFR2j3VsQez5Q8IinohSDUiB_TlMxkpfZKSviMAFLiQ,7565
35
- cloudsmith_cli/cli/commands/upstream.py,sha256=TgXKzhkNrkVqqXX1NKpkI3Uy84W0kA8v93lAIB11KOc,15652
35
+ cloudsmith_cli/cli/commands/upstream.py,sha256=WUPpMvYauXzh8MgMn9L4tHlTBi0UU_Gq4ZR_QDxTDdY,15922
36
36
  cloudsmith_cli/cli/commands/whoami.py,sha256=s9m7qucUlCtufaWeoYtIVTogRP3N5Jm7LPUxC1VZaSg,1725
37
37
  cloudsmith_cli/cli/commands/metrics/__init__.py,sha256=w-FjDvifPvTgf1nwGpTuhzk5mLkqmfvA9utrPqSUSdM,98
38
38
  cloudsmith_cli/cli/commands/metrics/command.py,sha256=-4ykfBJ8Ss6w8QoCqL0AZdhcF7ZmmahtvQ_5YTYif5c,510
@@ -40,8 +40,8 @@ cloudsmith_cli/cli/commands/metrics/entitlements.py,sha256=DROmuxR-YgJ8txe_q7yrW
40
40
  cloudsmith_cli/cli/commands/metrics/packages.py,sha256=HBpmSrDP-_VGN_NZl_SLQPYktr2yDwVTb_mCNgFH0Tc,3906
41
41
  cloudsmith_cli/cli/commands/policy/__init__.py,sha256=0LwfPbtEFbTuWE3kpvP4SI2AClXfZixAcOI6UhTtEbU,112
42
42
  cloudsmith_cli/cli/commands/policy/command.py,sha256=crZQiXhT7w19h9Z8IFFhM3NyGCTHZ8tL4vpHR430fLo,527
43
- cloudsmith_cli/cli/commands/policy/license.py,sha256=0L7fIEM45FsPX2izQqHMYFXA98O1ILBXrzF6J_HmmLE,9903
44
- cloudsmith_cli/cli/commands/policy/vulnerability.py,sha256=q9V2QppJIXqHSXW10qqQuZq3weKyUH9eRTt-kCz79PA,9781
43
+ cloudsmith_cli/cli/commands/policy/license.py,sha256=FKUdhWPlFC6Se43tSZRQhQ-JADeh_Niwo2mjyQwuFJU,10097
44
+ cloudsmith_cli/cli/commands/policy/vulnerability.py,sha256=DYLmKjebwZGvjGd6afb19EMdmG2ks5MEmNEOxEEfiCw,9976
45
45
  cloudsmith_cli/cli/commands/quota/__init__.py,sha256=FRRXCFTiSw3e0rUNpxxUiN0vznXQbHt45e0cj9zgz30,84
46
46
  cloudsmith_cli/cli/commands/quota/command.py,sha256=-oxLY33lqrW7PliafhsmnEtVdcrWUzRSxyjfto7R4MA,541
47
47
  cloudsmith_cli/cli/commands/quota/history.py,sha256=CklnmemvccVz6z1Kqt_IYtTB0ofBzFHwYk7VUAPUGxk,3696
@@ -57,18 +57,18 @@ cloudsmith_cli/cli/tests/commands/test_check.py,sha256=_CJaDQjhXnDQimzLkhBS8wL6V
57
57
  cloudsmith_cli/cli/tests/commands/test_download.py,sha256=VpD-T0GkqHzDZDGYwpN1tyCq6mgTkfdOmXQBfWdAm6E,12268
58
58
  cloudsmith_cli/cli/tests/commands/test_login.py,sha256=RlvPMaS2rTLah2dVF3Yt8gjG1HWEkD6zP_exzUvc1U0,1309
59
59
  cloudsmith_cli/cli/tests/commands/test_main.py,sha256=JmtJQ455OcqqEi0ostP8nMs0S4oXs4dkEFzPCGliqg8,947
60
- cloudsmith_cli/cli/tests/commands/test_package_commands.py,sha256=3wEyA2CLvWhMcUa8HzZLN-mmN3Bn0oYDJ5OpO_VK7kE,5669
61
- cloudsmith_cli/cli/tests/commands/test_repos.py,sha256=Uk0bIhcFI6n-3hzugeAcNxuLHqQZ-X1tSG_2rYutM0c,5851
60
+ cloudsmith_cli/cli/tests/commands/test_package_commands.py,sha256=tfB7hjivOTYOhCqYmd7IJ9dI6oNvhK2vIGCyFDbOjWI,5943
61
+ cloudsmith_cli/cli/tests/commands/test_repos.py,sha256=30sgokDrnQiEJJa6lUTDG2iryuO6OyNa0a9EVEmkjko,6726
62
62
  cloudsmith_cli/cli/tests/commands/test_tokens.py,sha256=BnTBS5ChIvgb9-HSkxOdzVIo81C6QA8xhJ7vGposow8,4931
63
- cloudsmith_cli/cli/tests/commands/test_upstream.py,sha256=D_tOKiLJ0_E-0cxBQpmtNjZXlxCmycLfT46sifRXVMc,4453
63
+ cloudsmith_cli/cli/tests/commands/test_upstream.py,sha256=Xicig-bqhknjnlSIw3DtZqlgM09T498ikE6taFC8jb0,5435
64
64
  cloudsmith_cli/cli/tests/commands/policy/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
65
- cloudsmith_cli/cli/tests/commands/policy/test_licence.py,sha256=T5EKhOS8BImHx3kVLQjbjQ5UWOACrtaDfjuECSkUOeo,5866
66
- cloudsmith_cli/cli/tests/commands/policy/test_vulnerability.py,sha256=YoqKx-lNrnBnQ7Yq1iZ-7FQqBACVUlgerqf-FJu6oZ4,5960
65
+ cloudsmith_cli/cli/tests/commands/policy/test_licence.py,sha256=NFHYk-pbxde7NB8cYYQzhRRTtLpNfYhFCdkGXn0nV8o,6504
66
+ cloudsmith_cli/cli/tests/commands/policy/test_vulnerability.py,sha256=uyreq39HYusY9k7lGnEKqFX2XgPRNA0hHEFiSoHeeDA,6660
67
67
  cloudsmith_cli/core/__init__.py,sha256=cTUzgNOgQKqQP8AKPNHgfkHpBhLggQ2V03IMitOLKiA,29
68
68
  cloudsmith_cli/core/config.py,sha256=eFA92QQBhccF0SdRtBwG7nrFuU2AK_yWzA9e0TUcNfE,3700
69
69
  cloudsmith_cli/core/download.py,sha256=WFlTpyAR_L6Z5GXBaiA3QZ4ABLO2GS42rduSBn2JcUg,15153
70
70
  cloudsmith_cli/core/keyring.py,sha256=v57SoE-5TaHsaMw7oCwM7ZuOVGPK1vAA2YsmWK35UAM,2310
71
- cloudsmith_cli/core/pagination.py,sha256=zQPSvjfAcQyRGEbX_3gh1Ni21l90-TP_UvPWwMpqLSw,2282
71
+ cloudsmith_cli/core/pagination.py,sha256=votPN7v6yGWxf2GnQ8oVoqq5SIsl8OiPJ0mEOd8eoYM,4553
72
72
  cloudsmith_cli/core/ratelimits.py,sha256=nJkLQNT5CBIk_Jy3mWH5trIaQyj8x6SEo95BwKUxNuw,2534
73
73
  cloudsmith_cli/core/rest.py,sha256=J0MLzIzw9NkJ66CdyweX48fsejKY7TbR7JOHVGyNjyY,8062
74
74
  cloudsmith_cli/core/utils.py,sha256=L3fUMKX-8XtNlXK51EOLfF4wGq45uoQMY74ZGedNu4A,2213
@@ -95,15 +95,15 @@ cloudsmith_cli/core/tests/test_init.py,sha256=CDdCI-ko09I3ltBeFNACGrfNFDNT8zhXUE
95
95
  cloudsmith_cli/core/tests/test_keyring.py,sha256=cLmZjhj21gm2fdi-l95yOxQPWuq_XVVNeY3s9QSNvYc,7076
96
96
  cloudsmith_cli/core/tests/test_rest.py,sha256=5reu5mNHCXgnkLCcDxTp8Kd82YodSoSX2pvYOj_kHOs,1360
97
97
  cloudsmith_cli/core/tests/test_version.py,sha256=k9QAjOKJ7Q5mfGSahRvtpPN0XDaGOhbbpHngqAIuM34,552
98
- cloudsmith_cli/data/VERSION,sha256=u1mRkBjudkgsI_HORCGc5MnGOTxl7w3a5A0y151BO7U,6
98
+ cloudsmith_cli/data/VERSION,sha256=25nNqvvJOfKXCRz2V3znOh-OBBeSsy2G4E6wfJVjcms,6
99
99
  cloudsmith_cli/data/config.ini,sha256=nD39yE9-GyKSxJ5Us5V_bRjAsdhDbD5HnwRNDKeMfR4,737
100
100
  cloudsmith_cli/data/credentials.ini,sha256=UTgXGXigPdlWUQxhQnalSJ18cLswQv6l26y7ZlYstCU,500
101
101
  cloudsmith_cli/templates/__init__.py,sha256=00xHj3iW0vXmI5rzjbryJllE1VHhg6Dxf7uqo9dIyvo,53
102
102
  cloudsmith_cli/templates/auth_error.html,sha256=qBdZ0TE88IFaVk0NIpSPZudDDf0PxAJnnqAyPz5KODo,1290
103
103
  cloudsmith_cli/templates/auth_success.html,sha256=UA629tjTJmIQ_y9eJ-a5Wfp0ilo8cgSsUqjHiCzEhq0,1056
104
- cloudsmith_cli-1.9.2.dist-info/licenses/LICENSE,sha256=eEz1wEWbBZFlc_n_P_55i4CCYgWgHYVJpQjnc6qbXOQ,11344
105
- cloudsmith_cli-1.9.2.dist-info/METADATA,sha256=kygqX2OAYbFIT43VnFx2ykO5ekkfnQzN88FeW6z5Nwc,15738
106
- cloudsmith_cli-1.9.2.dist-info/WHEEL,sha256=JNWh1Fm1UdwIQV075glCn4MVuCRs0sotJIq-J6rbxCU,109
107
- cloudsmith_cli-1.9.2.dist-info/entry_points.txt,sha256=lQfpZ8eDB4ye9iK_TRpGnABwkcUgKIS-sGlCjbI1j9s,69
108
- cloudsmith_cli-1.9.2.dist-info/top_level.txt,sha256=9P2AQ4lqblgMVHk2VHuvZKH92H0o19w-qhr_x-5ifIQ,15
109
- cloudsmith_cli-1.9.2.dist-info/RECORD,,
104
+ cloudsmith_cli-1.9.4.dist-info/licenses/LICENSE,sha256=eEz1wEWbBZFlc_n_P_55i4CCYgWgHYVJpQjnc6qbXOQ,11344
105
+ cloudsmith_cli-1.9.4.dist-info/METADATA,sha256=55JCO3KnPnJR2bxpPDSALeE0K1S4_lQpK3Y3hGPwJDM,15738
106
+ cloudsmith_cli-1.9.4.dist-info/WHEEL,sha256=JNWh1Fm1UdwIQV075glCn4MVuCRs0sotJIq-J6rbxCU,109
107
+ cloudsmith_cli-1.9.4.dist-info/entry_points.txt,sha256=lQfpZ8eDB4ye9iK_TRpGnABwkcUgKIS-sGlCjbI1j9s,69
108
+ cloudsmith_cli-1.9.4.dist-info/top_level.txt,sha256=9P2AQ4lqblgMVHk2VHuvZKH92H0o19w-qhr_x-5ifIQ,15
109
+ cloudsmith_cli-1.9.4.dist-info/RECORD,,