cloudsmith-cli 1.9.4__tar.gz → 1.10.1__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.
Files changed (120) hide show
  1. {cloudsmith_cli-1.9.4/cloudsmith_cli.egg-info → cloudsmith_cli-1.10.1}/PKG-INFO +4 -3
  2. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/README.md +1 -0
  3. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/cli/commands/entitlements.py +7 -4
  4. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/cli/commands/list_.py +6 -6
  5. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/cli/commands/metrics/entitlements.py +2 -0
  6. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/cli/commands/policy/__init__.py +1 -0
  7. cloudsmith_cli-1.10.1/cloudsmith_cli/cli/commands/policy/deny.py +246 -0
  8. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/cli/commands/policy/license.py +4 -4
  9. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/cli/commands/policy/vulnerability.py +4 -4
  10. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/cli/commands/quarantine.py +2 -2
  11. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/cli/commands/repos.py +9 -9
  12. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/cli/commands/upstream.py +6 -6
  13. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/cli/decorators.py +14 -5
  14. cloudsmith_cli-1.10.1/cloudsmith_cli/cli/tests/commands/policy/test_deny.py +175 -0
  15. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/cli/tests/commands/policy/test_licence.py +2 -2
  16. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/cli/tests/commands/policy/test_vulnerability.py +6 -6
  17. cloudsmith_cli-1.10.1/cloudsmith_cli/cli/tests/commands/test_entitlements.py +20 -0
  18. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/cli/tests/commands/test_package_commands.py +2 -2
  19. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/cli/tests/commands/test_repos.py +5 -5
  20. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/cli/tests/commands/test_upstream.py +10 -10
  21. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/cli/utils.py +2 -2
  22. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/cli/validators.py +46 -10
  23. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/core/api/orgs.py +63 -0
  24. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/core/pagination.py +7 -7
  25. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/core/rest.py +1 -1
  26. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/core/tests/test_rest.py +31 -0
  27. cloudsmith_cli-1.10.1/cloudsmith_cli/data/VERSION +1 -0
  28. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1/cloudsmith_cli.egg-info}/PKG-INFO +4 -3
  29. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli.egg-info/SOURCES.txt +3 -0
  30. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli.egg-info/requires.txt +2 -2
  31. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/setup.py +2 -2
  32. cloudsmith_cli-1.9.4/cloudsmith_cli/data/VERSION +0 -1
  33. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/LICENSE +0 -0
  34. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/MANIFEST.in +0 -0
  35. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/__init__.py +0 -0
  36. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/__main__.py +0 -0
  37. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/cli/__init__.py +0 -0
  38. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/cli/command.py +0 -0
  39. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/cli/commands/__init__.py +0 -0
  40. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/cli/commands/auth.py +0 -0
  41. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/cli/commands/check.py +0 -0
  42. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/cli/commands/copy.py +0 -0
  43. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/cli/commands/delete.py +0 -0
  44. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/cli/commands/dependencies.py +0 -0
  45. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/cli/commands/docs.py +0 -0
  46. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/cli/commands/download.py +0 -0
  47. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/cli/commands/help_.py +0 -0
  48. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/cli/commands/login.py +0 -0
  49. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/cli/commands/main.py +0 -0
  50. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/cli/commands/metrics/__init__.py +0 -0
  51. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/cli/commands/metrics/command.py +0 -0
  52. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/cli/commands/metrics/packages.py +0 -0
  53. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/cli/commands/move.py +0 -0
  54. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/cli/commands/policy/command.py +0 -0
  55. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/cli/commands/push.py +0 -0
  56. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/cli/commands/quota/__init__.py +0 -0
  57. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/cli/commands/quota/command.py +0 -0
  58. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/cli/commands/quota/history.py +0 -0
  59. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/cli/commands/quota/quota.py +0 -0
  60. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/cli/commands/resync.py +0 -0
  61. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/cli/commands/status.py +0 -0
  62. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/cli/commands/tags.py +0 -0
  63. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/cli/commands/tokens.py +0 -0
  64. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/cli/commands/whoami.py +0 -0
  65. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/cli/config.py +0 -0
  66. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/cli/exceptions.py +0 -0
  67. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/cli/saml.py +0 -0
  68. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/cli/table.py +0 -0
  69. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/cli/tests/__init__.py +0 -0
  70. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/cli/tests/commands/__init__.py +0 -0
  71. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/cli/tests/commands/policy/__init__.py +0 -0
  72. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/cli/tests/commands/test_check.py +0 -0
  73. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/cli/tests/commands/test_download.py +0 -0
  74. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/cli/tests/commands/test_login.py +0 -0
  75. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/cli/tests/commands/test_main.py +0 -0
  76. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/cli/tests/commands/test_tokens.py +0 -0
  77. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/cli/tests/conftest.py +0 -0
  78. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/cli/tests/test_push.py +0 -0
  79. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/cli/tests/test_saml.py +0 -0
  80. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/cli/tests/test_utils.py +0 -0
  81. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/cli/tests/utils.py +0 -0
  82. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/cli/types.py +0 -0
  83. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/cli/webserver.py +0 -0
  84. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/core/__init__.py +0 -0
  85. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/core/api/__init__.py +0 -0
  86. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/core/api/distros.py +0 -0
  87. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/core/api/entitlements.py +0 -0
  88. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/core/api/exceptions.py +0 -0
  89. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/core/api/files.py +0 -0
  90. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/core/api/init.py +0 -0
  91. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/core/api/metrics.py +0 -0
  92. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/core/api/packages.py +0 -0
  93. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/core/api/quota.py +0 -0
  94. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/core/api/rates.py +0 -0
  95. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/core/api/repos.py +0 -0
  96. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/core/api/status.py +0 -0
  97. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/core/api/upstreams.py +0 -0
  98. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/core/api/user.py +0 -0
  99. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/core/api/version.py +0 -0
  100. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/core/config.py +0 -0
  101. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/core/download.py +0 -0
  102. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/core/keyring.py +0 -0
  103. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/core/ratelimits.py +0 -0
  104. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/core/tests/__init__.py +0 -0
  105. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/core/tests/test_download.py +0 -0
  106. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/core/tests/test_init.py +0 -0
  107. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/core/tests/test_keyring.py +0 -0
  108. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/core/tests/test_version.py +0 -0
  109. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/core/utils.py +0 -0
  110. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/core/version.py +0 -0
  111. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/data/config.ini +0 -0
  112. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/data/credentials.ini +0 -0
  113. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/templates/__init__.py +0 -0
  114. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/templates/auth_error.html +0 -0
  115. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli/templates/auth_success.html +0 -0
  116. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli.egg-info/dependency_links.txt +0 -0
  117. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli.egg-info/entry_points.txt +0 -0
  118. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli.egg-info/not-zip-safe +0 -0
  119. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/cloudsmith_cli.egg-info/top_level.txt +0 -0
  120. {cloudsmith_cli-1.9.4 → cloudsmith_cli-1.10.1}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cloudsmith-cli
3
- Version: 1.9.4
3
+ Version: 1.10.1
4
4
  Summary: Cloudsmith Command-Line Interface (CLI)
5
5
  Home-page: https://github.com/cloudsmith-io/cloudsmith-cli
6
6
  Author: Cloudsmith Ltd
@@ -27,7 +27,7 @@ Classifier: Topic :: Utilities
27
27
  Requires-Python: >=3.9.0
28
28
  Description-Content-Type: text/markdown
29
29
  License-File: LICENSE
30
- Requires-Dist: click!=8.3.0,>=8.2.0
30
+ Requires-Dist: click!=8.3.0,>=8.1.8
31
31
  Requires-Dist: click-configfile>=0.2.3
32
32
  Requires-Dist: click-didyoumean>=0.0.3
33
33
  Requires-Dist: click-spinner>=0.1.7
@@ -36,7 +36,7 @@ Requires-Dist: keyring>=25.4.1
36
36
  Requires-Dist: requests>=2.18.4
37
37
  Requires-Dist: requests_toolbelt>=0.8.0
38
38
  Requires-Dist: semver>=2.7.9
39
- Requires-Dist: urllib3<2.0
39
+ Requires-Dist: urllib3>=2.5
40
40
  Dynamic: author
41
41
  Dynamic: author-email
42
42
  Dynamic: classifier
@@ -105,6 +105,7 @@ The CLI currently supports the following commands (and sub-commands):
105
105
  - `packages`: Retrieve package usage for repository.
106
106
  - `move`|`mv`|`promote`: Move (promote) a package to another repo.
107
107
  - `policy`: Manage policies for an organization.
108
+ - `deny`: Manage deny policies for an organization.
108
109
  - `license`: Manage license policies for an organization.
109
110
  - `vulnerability`: Manage vulnerability policies for an organization.
110
111
  - `push`|`upload`: Push (upload) a new package to a repository.
@@ -52,6 +52,7 @@ The CLI currently supports the following commands (and sub-commands):
52
52
  - `packages`: Retrieve package usage for repository.
53
53
  - `move`|`mv`|`promote`: Move (promote) a package to another repo.
54
54
  - `policy`: Manage policies for an organization.
55
+ - `deny`: Manage deny policies for an organization.
55
56
  - `license`: Manage license policies for an organization.
56
57
  - `vulnerability`: Manage vulnerability policies for an organization.
57
58
  - `push`|`upload`: Push (upload) a new package to a repository.
@@ -6,6 +6,7 @@ from operator import itemgetter
6
6
  import click
7
7
 
8
8
  from ...core.api import entitlements 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 fmt_datetime, maybe_spinner
@@ -72,7 +73,7 @@ def list_entitlements_options(f):
72
73
  return wrapper
73
74
 
74
75
 
75
- def list_entitlements(ctx, opts, owner_repo, page, page_size, show_tokens):
76
+ def list_entitlements(ctx, opts, owner_repo, page, page_size, show_tokens, page_all):
76
77
  """
77
78
  List entitlements for a repository.
78
79
 
@@ -100,11 +101,13 @@ def list_entitlements(ctx, opts, owner_repo, page, page_size, show_tokens):
100
101
  context_msg = "Failed to get list of entitlements!"
101
102
  with handle_api_exceptions(ctx, opts=opts, context_msg=context_msg):
102
103
  with maybe_spinner(opts):
103
- entitlements_, page_info = api.list_entitlements(
104
- owner=owner,
105
- repo=repo,
104
+ entitlements_, page_info = paginate_results(
105
+ api.list_entitlements,
106
+ page_all=page_all,
106
107
  page=page,
107
108
  page_size=page_size,
109
+ owner=owner,
110
+ repo=repo,
108
111
  show_tokens=show_tokens,
109
112
  )
110
113
 
@@ -157,7 +157,7 @@ def entitlements_(*args, **kwargs): # pylint: disable=missing-docstring
157
157
  help=("Sort packages by field. Prefix with '-' for descending order."),
158
158
  )
159
159
  @click.pass_context
160
- def packages(ctx, opts, owner_repo, page, page_size, query, sort, show_all):
160
+ def packages(ctx, opts, owner_repo, page, page_size, query, sort, page_all):
161
161
  """
162
162
  List packages for a repository.
163
163
 
@@ -220,7 +220,7 @@ def packages(ctx, opts, owner_repo, page, page_size, query, sort, show_all):
220
220
  with maybe_spinner(opts):
221
221
  packages_, page_info = paginate_results(
222
222
  list_packages,
223
- show_all=show_all,
223
+ page_all=page_all,
224
224
  page=page,
225
225
  page_size=page_size,
226
226
  owner=owner,
@@ -262,9 +262,9 @@ def packages(ctx, opts, owner_repo, page, page_size, query, sort, show_all):
262
262
  list_suffix = "package%s" % ("s" if num_results != 1 else "")
263
263
  utils.pretty_print_list_info(
264
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,
265
+ page_info=None if page_all else page_info,
266
+ suffix=f"{list_suffix} retrieved" if page_all else f"{list_suffix} visible",
267
+ page_all=page_all,
268
268
  )
269
269
 
270
270
 
@@ -282,7 +282,7 @@ def packages(ctx, opts, owner_repo, page, page_size, query, sort, show_all):
282
282
  required=False,
283
283
  )
284
284
  @click.pass_context
285
- def repos(ctx, opts, owner_repo, page, page_size, show_all):
285
+ def repos(ctx, opts, owner_repo, page, page_size, page_all):
286
286
  """
287
287
  List repositories for a namespace (owner).
288
288
 
@@ -123,7 +123,9 @@ def usage(ctx, opts, owner_repo, tokens, start, finish):
123
123
  owner = owner_repo[0]
124
124
  repo = None
125
125
 
126
+ data = None
126
127
  context_msg = "Failed to get list of metrics!"
128
+ data = {}
127
129
  with handle_api_exceptions(ctx, opts=opts, context_msg=context_msg):
128
130
  with maybe_spinner(opts):
129
131
  if owner and repo:
@@ -1,2 +1,3 @@
1
+ from .deny import deny_policy as policy_deny
1
2
  from .license import licence as policy_license
2
3
  from .vulnerability import vulnerability as policy_vulnerability
@@ -0,0 +1,246 @@
1
+ """Commands for deny policies."""
2
+
3
+ import click
4
+
5
+ from ....core.api import orgs
6
+ from ....core.pagination import paginate_results
7
+ from ... import command, decorators, utils
8
+ from ...exceptions import handle_api_exceptions
9
+ from ...utils import fmt_datetime, maybe_spinner
10
+ from .command import policy
11
+
12
+
13
+ def print_deny_policies(policies):
14
+ """Print deny policies as a table."""
15
+ headers = [
16
+ "Name",
17
+ "Description",
18
+ "Package Query",
19
+ "Enabled",
20
+ "Created",
21
+ "Updated",
22
+ "Identifier",
23
+ ]
24
+
25
+ rows = [
26
+ [
27
+ click.style(policy["name"], fg="cyan"),
28
+ click.style(policy["description"], fg="yellow"),
29
+ click.style(policy.get("package_query_string", ""), fg="yellow"),
30
+ click.style(
31
+ "Yes" if policy.get("enabled") else "No",
32
+ fg="green" if policy.get("enabled") else "red",
33
+ ),
34
+ click.style(fmt_datetime(policy["created_at"]), fg="blue"),
35
+ click.style(fmt_datetime(policy["updated_at"]), fg="blue"),
36
+ click.style(policy["slug_perm"], fg="green"),
37
+ ]
38
+ for policy in policies
39
+ ]
40
+
41
+ click.echo()
42
+ utils.pretty_print_table(headers, rows)
43
+ click.echo()
44
+
45
+
46
+ @policy.group(cls=command.AliasGroup, name="deny", aliases=[])
47
+ @decorators.common_cli_config_options
48
+ @decorators.common_cli_output_options
49
+ @decorators.common_api_auth_options
50
+ @decorators.initialise_api
51
+ @click.pass_context
52
+ def deny_policy(*args, **kwargs):
53
+ """Manage deny policies for an organization."""
54
+
55
+
56
+ @deny_policy.command(name="list", aliases=["ls"])
57
+ @decorators.common_cli_config_options
58
+ @decorators.common_cli_list_options
59
+ @decorators.common_cli_output_options
60
+ @decorators.common_api_auth_options
61
+ @decorators.initialise_api
62
+ @click.argument("owner")
63
+ @click.pass_context
64
+ def list_deny_policies(ctx, opts, owner, page, page_size, page_all):
65
+ """List deny policies for an organization."""
66
+ use_stderr = opts.output != "pretty"
67
+ click.echo("Getting deny policies ... ", nl=False, err=use_stderr)
68
+
69
+ context_msg = "Failed to get deny policies!"
70
+ with handle_api_exceptions(ctx, opts=opts, context_msg=context_msg):
71
+ with maybe_spinner(opts):
72
+ data, page_info = paginate_results(
73
+ orgs.list_deny_policies, page_all, page, page_size, owner=owner
74
+ )
75
+
76
+ click.secho("OK", fg="green", err=use_stderr)
77
+
78
+ if utils.maybe_print_as_json(opts, data, page_info):
79
+ return
80
+
81
+ print_deny_policies(data)
82
+
83
+ click.echo()
84
+
85
+ num_results = len(data)
86
+ list_suffix = "deny polic%s" % ("y" if num_results == 1 else "ies")
87
+ utils.pretty_print_list_info(
88
+ num_results=num_results,
89
+ page_info=None if page_all else page_info,
90
+ suffix=list_suffix,
91
+ page_all=page_all,
92
+ )
93
+
94
+
95
+ @deny_policy.command(name="create", aliases=["new"])
96
+ @decorators.common_cli_config_options
97
+ @decorators.common_cli_output_options
98
+ @decorators.common_api_auth_options
99
+ @decorators.initialise_api
100
+ @click.argument("owner")
101
+ @click.argument("policy_config_file", type=click.File("rb"))
102
+ @click.pass_context
103
+ def create_deny_policy(ctx, opts, owner, policy_config_file):
104
+ """Create a deny policy for an organization."""
105
+ import json
106
+
107
+ use_stderr = opts.output != "pretty"
108
+ policy_config = json.load(policy_config_file)
109
+
110
+ policy_name = policy_config.get("name")
111
+ if not policy_name:
112
+ raise click.BadParameter(
113
+ "Name is required for creating a deny policy.", param="name"
114
+ )
115
+
116
+ click.secho(
117
+ "Creating %(name)s deny policy for the %(owner)s namespace ..."
118
+ % {
119
+ "name": click.style(policy_name, bold=True),
120
+ "owner": click.style(owner, bold=True),
121
+ },
122
+ nl=False,
123
+ err=use_stderr,
124
+ )
125
+
126
+ context_msg = "Failed to create the deny policy!"
127
+ with handle_api_exceptions(ctx, opts=opts, context_msg=context_msg):
128
+ with maybe_spinner(opts):
129
+ data = orgs.create_deny_policy(owner=owner, policy_config=policy_config)
130
+
131
+ click.secho("OK", fg="green", err=use_stderr)
132
+
133
+ if utils.maybe_print_as_json(opts, [data]):
134
+ return
135
+
136
+ print_deny_policies([data])
137
+
138
+
139
+ @deny_policy.command(name="get")
140
+ @decorators.common_cli_config_options
141
+ @decorators.common_cli_output_options
142
+ @decorators.common_api_auth_options
143
+ @decorators.initialise_api
144
+ @click.argument("owner")
145
+ @click.argument("identifier")
146
+ @click.pass_context
147
+ def get_deny_policy(ctx, opts, owner, identifier):
148
+ """Get a deny policy for an organization."""
149
+ use_stderr = opts.output != "pretty"
150
+ click.echo("Getting deny policy ... ", nl=False, err=use_stderr)
151
+
152
+ context_msg = "Failed to get deny policy!"
153
+ with handle_api_exceptions(ctx, opts=opts, context_msg=context_msg):
154
+ with maybe_spinner(opts):
155
+ data = orgs.get_deny_policy(owner=owner, slug_perm=identifier)
156
+
157
+ click.secho("OK", fg="green", err=use_stderr)
158
+
159
+ if utils.maybe_print_as_json(opts, [data]):
160
+ return
161
+
162
+ print_deny_policies([data])
163
+
164
+
165
+ @deny_policy.command(name="update", aliases=["set"])
166
+ @decorators.common_cli_config_options
167
+ @decorators.common_cli_output_options
168
+ @decorators.common_api_auth_options
169
+ @decorators.initialise_api
170
+ @click.argument("owner")
171
+ @click.argument("identifier")
172
+ @click.argument("policy_config_file", type=click.File("rb"))
173
+ @click.pass_context
174
+ def update_deny_policy(ctx, opts, owner, identifier, policy_config_file):
175
+ """Update a deny policy for an organization."""
176
+ import json
177
+
178
+ use_stderr = opts.output != "pretty"
179
+ policy_config = json.load(policy_config_file)
180
+
181
+ click.secho(
182
+ "Updating %(identifier)s deny policy in the %(owner)s namespace ..."
183
+ % {
184
+ "identifier": click.style(identifier, bold=True),
185
+ "owner": click.style(owner, bold=True),
186
+ },
187
+ nl=False,
188
+ err=use_stderr,
189
+ )
190
+
191
+ context_msg = "Failed to update the deny policy!"
192
+ with handle_api_exceptions(ctx, opts=opts, context_msg=context_msg):
193
+ with maybe_spinner(opts):
194
+ data = orgs.update_deny_policy(
195
+ owner=owner, slug_perm=identifier, policy_config=policy_config
196
+ )
197
+
198
+ click.secho("OK", fg="green", err=use_stderr)
199
+
200
+ if utils.maybe_print_as_json(opts, [data]):
201
+ return
202
+
203
+ print_deny_policies([data])
204
+
205
+
206
+ @deny_policy.command(name="delete", aliases=["rm"])
207
+ @decorators.common_cli_config_options
208
+ @decorators.common_cli_output_options
209
+ @decorators.common_api_auth_options
210
+ @decorators.initialise_api
211
+ @click.argument("owner")
212
+ @click.argument("identifier")
213
+ @click.option(
214
+ "-y",
215
+ "--yes",
216
+ default=False,
217
+ is_flag=True,
218
+ help="Assume yes as default answer to questions (this is dangerous!)",
219
+ )
220
+ @click.pass_context
221
+ def delete_deny_policy(ctx, opts, owner, identifier, yes):
222
+ """Delete a deny policy for an organization."""
223
+ delete_args = {
224
+ "namespace": click.style(owner, bold=True),
225
+ "identifier": click.style(identifier, bold=True),
226
+ }
227
+
228
+ prompt = (
229
+ "delete the %(identifier)s deny policy from the %(namespace)s namespace"
230
+ % delete_args
231
+ )
232
+
233
+ if not utils.confirm_operation(prompt, assume_yes=yes):
234
+ return
235
+
236
+ click.secho(
237
+ "Deleting %(identifier)s from the %(namespace)s namespace ... " % delete_args,
238
+ nl=False,
239
+ )
240
+
241
+ context_msg = "Failed to delete the deny policy!"
242
+ with handle_api_exceptions(ctx, opts=opts, context_msg=context_msg):
243
+ with maybe_spinner(opts):
244
+ orgs.delete_deny_policy(owner=owner, slug_perm=identifier)
245
+
246
+ click.secho("OK", fg="green")
@@ -82,7 +82,7 @@ def licence(*args, **kwargs):
82
82
  "owner", metavar="OWNER", callback=validators.validate_owner, required=True
83
83
  )
84
84
  @click.pass_context
85
- def ls(ctx, opts, owner, page, page_size, show_all):
85
+ def ls(ctx, opts, owner, page, page_size, page_all):
86
86
  """
87
87
  List license policies.
88
88
 
@@ -108,7 +108,7 @@ def ls(ctx, opts, owner, page, page_size, show_all):
108
108
  with handle_api_exceptions(ctx, opts=opts, context_msg=context_msg):
109
109
  with maybe_spinner(opts):
110
110
  policies, page_info = paginate_results(
111
- api.list_license_policies, show_all, page, page_size, owner=owner
111
+ api.list_license_policies, page_all, page, page_size, owner=owner
112
112
  )
113
113
 
114
114
  click.secho("OK", fg="green", err=use_stderr)
@@ -124,9 +124,9 @@ def ls(ctx, opts, owner, page, page_size, show_all):
124
124
  list_suffix = "license polic%s" % ("y" if num_results == 1 else "ies")
125
125
  utils.pretty_print_list_info(
126
126
  num_results=num_results,
127
- page_info=None if show_all else page_info,
127
+ page_info=None if page_all else page_info,
128
128
  suffix=list_suffix,
129
- show_all=show_all,
129
+ page_all=page_all,
130
130
  )
131
131
 
132
132
 
@@ -72,7 +72,7 @@ def vulnerability(*args, **kwargs):
72
72
  "owner", metavar="OWNER", callback=validators.validate_owner, required=True
73
73
  )
74
74
  @click.pass_context
75
- def ls(ctx, opts, owner, page, page_size, show_all):
75
+ def ls(ctx, opts, owner, page, page_size, page_all):
76
76
  """
77
77
  List vulnerability policies.
78
78
 
@@ -98,7 +98,7 @@ def ls(ctx, opts, owner, page, page_size, show_all):
98
98
  with handle_api_exceptions(ctx, opts=opts, context_msg=context_msg):
99
99
  with maybe_spinner(opts):
100
100
  policies, page_info = paginate_results(
101
- api.list_vulnerability_policies, show_all, page, page_size, owner=owner
101
+ api.list_vulnerability_policies, page_all, page, page_size, owner=owner
102
102
  )
103
103
 
104
104
  click.secho("OK", fg="green", err=use_stderr)
@@ -114,9 +114,9 @@ def ls(ctx, opts, owner, page, page_size, show_all):
114
114
  list_suffix = "vulnerability polic%s" % ("y" if num_results == 1 else "ies")
115
115
  utils.pretty_print_list_info(
116
116
  num_results=num_results,
117
- page_info=None if show_all else page_info,
117
+ page_info=None if page_all else page_info,
118
118
  suffix=list_suffix,
119
- show_all=show_all,
119
+ page_all=page_all,
120
120
  )
121
121
 
122
122
 
@@ -51,7 +51,7 @@ def quarantine(ctx, opts): # pylint: disable=unused-argument
51
51
  """
52
52
 
53
53
 
54
- def add_quarantine(ctx, opts, owner_repo_package, page, page_size):
54
+ def add_quarantine(ctx, opts, owner_repo_package, page, page_size, page_all):
55
55
  """
56
56
  Add a package to quarantine.
57
57
 
@@ -98,7 +98,7 @@ def add(*args, **kwargs): # pylint: disable=missing-docstring
98
98
  return add_quarantine(*args, **kwargs)
99
99
 
100
100
 
101
- def remove_quarantine(ctx, opts, owner_repo_package, page, page_size):
101
+ def remove_quarantine(ctx, opts, owner_repo_package, page, page_size, page_all):
102
102
  """
103
103
  Remove a package from quarantine.
104
104
 
@@ -13,7 +13,7 @@ from ..utils import maybe_spinner
13
13
  from .main import main
14
14
 
15
15
 
16
- def print_repositories(opts, data, page_info=None, show_list_info=True, show_all=False):
16
+ def print_repositories(opts, data, page_info=None, show_list_info=True, page_all=False):
17
17
  """Print repositories as a table or output in another format."""
18
18
  headers = [
19
19
  "Name",
@@ -56,9 +56,9 @@ def print_repositories(opts, data, page_info=None, show_list_info=True, show_all
56
56
  list_suffix = "repositor%s" % ("ies" if num_results != 1 else "y")
57
57
  utils.pretty_print_list_info(
58
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,
59
+ page_info=None if page_all else page_info,
60
+ suffix=f"{list_suffix} retrieved" if page_all else f"{list_suffix} visible",
61
+ page_all=page_all,
62
62
  )
63
63
 
64
64
 
@@ -90,7 +90,7 @@ def repositories(ctx, opts): # pylink: disable=unused-argument
90
90
  required=False,
91
91
  )
92
92
  @click.pass_context
93
- def get(ctx, opts, owner_repo, page, page_size, show_all):
93
+ def get(ctx, opts, owner_repo, page, page_size, page_all):
94
94
  """
95
95
  List repositories for a namespace (owner).
96
96
 
@@ -119,9 +119,9 @@ def get(ctx, opts, owner_repo, page, page_size, show_all):
119
119
  owner = None
120
120
  repo = None
121
121
 
122
- if show_all and repo:
122
+ if page_all and repo:
123
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."
124
+ "The --page-all option cannot be used when specifying a single repository (OWNER/REPO). Omit the repository slug or remove --page-all."
125
125
  )
126
126
 
127
127
  click.echo("Getting list of repositories ... ", nl=False, err=use_stderr)
@@ -130,7 +130,7 @@ def get(ctx, opts, owner_repo, page, page_size, show_all):
130
130
  with handle_api_exceptions(ctx, opts=opts, context_msg=context_msg):
131
131
  with maybe_spinner(opts):
132
132
  repos_, page_info = paginate_results(
133
- api.list_repos, show_all, page, page_size, owner=owner, repo=repo
133
+ api.list_repos, page_all, page, page_size, owner=owner, repo=repo
134
134
  )
135
135
 
136
136
  click.secho("OK", fg="green", err=use_stderr)
@@ -143,7 +143,7 @@ def get(ctx, opts, owner_repo, page, page_size, show_all):
143
143
  data=repos_,
144
144
  show_list_info=True,
145
145
  page_info=page_info,
146
- show_all=show_all,
146
+ page_all=page_all,
147
147
  )
148
148
 
149
149
 
@@ -38,7 +38,7 @@ UPSTREAM_FORMATS = [
38
38
  ]
39
39
 
40
40
 
41
- def print_upstreams(upstreams, upstream_fmt, page_info=None, show_all=False):
41
+ def print_upstreams(upstreams, upstream_fmt, page_info=None, page_all=False):
42
42
  """Print upstreams as a table or output in another format."""
43
43
 
44
44
  def build_row(u):
@@ -120,9 +120,9 @@ def print_upstreams(upstreams, upstream_fmt, page_info=None, show_all=False):
120
120
  list_suffix = "upstream%s" % ("" if num_results == 1 else "s")
121
121
  utils.pretty_print_list_info(
122
122
  num_results=num_results,
123
- page_info=None if show_all else page_info,
123
+ page_info=None if page_all else page_info,
124
124
  suffix=list_suffix,
125
- show_all=show_all,
125
+ page_all=page_all,
126
126
  )
127
127
 
128
128
 
@@ -170,7 +170,7 @@ def build_upstream_list_command(upstream_fmt):
170
170
  "owner_repo", metavar="OWNER/REPO", callback=validators.validate_owner_repo
171
171
  )
172
172
  @click.pass_context
173
- def func(ctx, opts, owner_repo, page, page_size, show_all):
173
+ def func(ctx, opts, owner_repo, page, page_size, page_all):
174
174
  owner, repo = owner_repo
175
175
 
176
176
  # Use stderr for messages if the output is something else (e.g. # JSON)
@@ -184,7 +184,7 @@ def build_upstream_list_command(upstream_fmt):
184
184
  with maybe_spinner(opts):
185
185
  upstreams, page_info = paginate_results(
186
186
  api.list_upstreams,
187
- show_all,
187
+ page_all,
188
188
  page,
189
189
  page_size,
190
190
  owner=owner,
@@ -198,7 +198,7 @@ def build_upstream_list_command(upstream_fmt):
198
198
  if utils.maybe_print_as_json(opts, upstreams, page_info):
199
199
  return
200
200
 
201
- print_upstreams(upstreams, upstream_fmt, page_info, show_all)
201
+ print_upstreams(upstreams, upstream_fmt, page_info, page_all)
202
202
 
203
203
  func.__doc__ = f"""
204
204
  List {upstream_fmt} upstreams for a repository.
@@ -150,8 +150,8 @@ def common_cli_list_options(f):
150
150
  "-l",
151
151
  "--page-size",
152
152
  default=30,
153
- type=int,
154
- help="The amount of items to view per page for lists.",
153
+ type=validators.IntOrWildcard(),
154
+ help="The amount of items to view per page for lists. Use '*' to show all results.",
155
155
  callback=validators.validate_page_size,
156
156
  )
157
157
  @click.option(
@@ -163,6 +163,7 @@ def common_cli_list_options(f):
163
163
  callback=validators.validate_page,
164
164
  )
165
165
  @click.option(
166
+ "--page-all",
166
167
  "--show-all",
167
168
  default=False,
168
169
  is_flag=True,
@@ -173,10 +174,18 @@ def common_cli_list_options(f):
173
174
  def wrapper(ctx, *args, **kwargs):
174
175
  # pylint: disable=missing-docstring
175
176
  opts = config.get_or_create_options(ctx)
177
+
178
+ # Handle wildcard page_size (converts to page_all behavior)
179
+ page_size = kwargs.get("page_size")
180
+ if page_size == -1:
181
+ kwargs["page_all"] = True
182
+ # Validate that wildcard isn't used with explicit --page
183
+ validators.enforce_page_all_exclusive(ctx, wildcard_used=True)
184
+
176
185
  # 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)
186
+ page_all = kwargs.get("page_all")
187
+ if page_all:
188
+ validators.enforce_page_all_exclusive(ctx)
180
189
  kwargs["opts"] = opts
181
190
  return ctx.invoke(f, *args, **kwargs)
182
191