qualys-cli 0.3.0__tar.gz → 0.3.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.
- {qualys_cli-0.3.0 → qualys_cli-0.3.1}/CHANGELOG.md +9 -0
- {qualys_cli-0.3.0 → qualys_cli-0.3.1}/PKG-INFO +1 -1
- {qualys_cli-0.3.0 → qualys_cli-0.3.1}/pyproject.toml +1 -1
- qualys_cli-0.3.1/src/qualys_cli/__init__.py +1 -0
- {qualys_cli-0.3.0 → qualys_cli-0.3.1}/src/qualys_cli/_docs/usage.html +2 -2
- {qualys_cli-0.3.0 → qualys_cli-0.3.1}/src/qualys_cli/extras.py +17 -11
- qualys_cli-0.3.1/tests/test_completion.py +61 -0
- qualys_cli-0.3.0/src/qualys_cli/__init__.py +0 -1
- {qualys_cli-0.3.0 → qualys_cli-0.3.1}/.gitignore +0 -0
- {qualys_cli-0.3.0 → qualys_cli-0.3.1}/LICENSE +0 -0
- {qualys_cli-0.3.0 → qualys_cli-0.3.1}/README.md +0 -0
- {qualys_cli-0.3.0 → qualys_cli-0.3.1}/src/qualys_cli/__main__.py +0 -0
- {qualys_cli-0.3.0 → qualys_cli-0.3.1}/src/qualys_cli/audit.py +0 -0
- {qualys_cli-0.3.0 → qualys_cli-0.3.1}/src/qualys_cli/auth.py +0 -0
- {qualys_cli-0.3.0 → qualys_cli-0.3.1}/src/qualys_cli/cache.py +0 -0
- {qualys_cli-0.3.0 → qualys_cli-0.3.1}/src/qualys_cli/cli.py +0 -0
- {qualys_cli-0.3.0 → qualys_cli-0.3.1}/src/qualys_cli/client.py +0 -0
- {qualys_cli-0.3.0 → qualys_cli-0.3.1}/src/qualys_cli/commands/__init__.py +0 -0
- {qualys_cli-0.3.0 → qualys_cli-0.3.1}/src/qualys_cli/commands/asset.py +0 -0
- {qualys_cli-0.3.0 → qualys_cli-0.3.1}/src/qualys_cli/commands/ca.py +0 -0
- {qualys_cli-0.3.0 → qualys_cli-0.3.1}/src/qualys_cli/commands/cs.py +0 -0
- {qualys_cli-0.3.0 → qualys_cli-0.3.1}/src/qualys_cli/commands/csam.py +0 -0
- {qualys_cli-0.3.0 → qualys_cli-0.3.1}/src/qualys_cli/commands/edr.py +0 -0
- {qualys_cli-0.3.0 → qualys_cli-0.3.1}/src/qualys_cli/commands/etm.py +0 -0
- {qualys_cli-0.3.0 → qualys_cli-0.3.1}/src/qualys_cli/commands/fim.py +0 -0
- {qualys_cli-0.3.0 → qualys_cli-0.3.1}/src/qualys_cli/commands/pc.py +0 -0
- {qualys_cli-0.3.0 → qualys_cli-0.3.1}/src/qualys_cli/commands/pm.py +0 -0
- {qualys_cli-0.3.0 → qualys_cli-0.3.1}/src/qualys_cli/commands/scanauth.py +0 -0
- {qualys_cli-0.3.0 → qualys_cli-0.3.1}/src/qualys_cli/commands/sub.py +0 -0
- {qualys_cli-0.3.0 → qualys_cli-0.3.1}/src/qualys_cli/commands/tc.py +0 -0
- {qualys_cli-0.3.0 → qualys_cli-0.3.1}/src/qualys_cli/commands/user.py +0 -0
- {qualys_cli-0.3.0 → qualys_cli-0.3.1}/src/qualys_cli/commands/vm.py +0 -0
- {qualys_cli-0.3.0 → qualys_cli-0.3.1}/src/qualys_cli/commands/was.py +0 -0
- {qualys_cli-0.3.0 → qualys_cli-0.3.1}/src/qualys_cli/config.py +0 -0
- {qualys_cli-0.3.0 → qualys_cli-0.3.1}/src/qualys_cli/detection_stats.py +0 -0
- {qualys_cli-0.3.0 → qualys_cli-0.3.1}/src/qualys_cli/flair.py +0 -0
- {qualys_cli-0.3.0 → qualys_cli-0.3.1}/src/qualys_cli/formatters.py +0 -0
- {qualys_cli-0.3.0 → qualys_cli-0.3.1}/src/qualys_cli/history.py +0 -0
- {qualys_cli-0.3.0 → qualys_cli-0.3.1}/src/qualys_cli/http_server.py +0 -0
- {qualys_cli-0.3.0 → qualys_cli-0.3.1}/src/qualys_cli/mcp_server.py +0 -0
- {qualys_cli-0.3.0 → qualys_cli-0.3.1}/src/qualys_cli/metrics.py +0 -0
- {qualys_cli-0.3.0 → qualys_cli-0.3.1}/src/qualys_cli/platforms.py +0 -0
- {qualys_cli-0.3.0 → qualys_cli-0.3.1}/src/qualys_cli/queries.py +0 -0
- {qualys_cli-0.3.0 → qualys_cli-0.3.1}/tests/__init__.py +0 -0
- {qualys_cli-0.3.0 → qualys_cli-0.3.1}/tests/conftest.py +0 -0
- {qualys_cli-0.3.0 → qualys_cli-0.3.1}/tests/test_agent_mode.py +0 -0
- {qualys_cli-0.3.0 → qualys_cli-0.3.1}/tests/test_all_commands_smoke.py +0 -0
- {qualys_cli-0.3.0 → qualys_cli-0.3.1}/tests/test_asset.py +0 -0
- {qualys_cli-0.3.0 → qualys_cli-0.3.1}/tests/test_asset_tags.py +0 -0
- {qualys_cli-0.3.0 → qualys_cli-0.3.1}/tests/test_audit.py +0 -0
- {qualys_cli-0.3.0 → qualys_cli-0.3.1}/tests/test_ca.py +0 -0
- {qualys_cli-0.3.0 → qualys_cli-0.3.1}/tests/test_client.py +0 -0
- {qualys_cli-0.3.0 → qualys_cli-0.3.1}/tests/test_csam.py +0 -0
- {qualys_cli-0.3.0 → qualys_cli-0.3.1}/tests/test_detection_stats.py +0 -0
- {qualys_cli-0.3.0 → qualys_cli-0.3.1}/tests/test_detection_stats_cmd.py +0 -0
- {qualys_cli-0.3.0 → qualys_cli-0.3.1}/tests/test_error_handling.py +0 -0
- {qualys_cli-0.3.0 → qualys_cli-0.3.1}/tests/test_etm.py +0 -0
- {qualys_cli-0.3.0 → qualys_cli-0.3.1}/tests/test_features.py +0 -0
- {qualys_cli-0.3.0 → qualys_cli-0.3.1}/tests/test_fim_edr.py +0 -0
- {qualys_cli-0.3.0 → qualys_cli-0.3.1}/tests/test_flair.py +0 -0
- {qualys_cli-0.3.0 → qualys_cli-0.3.1}/tests/test_formatters.py +0 -0
- {qualys_cli-0.3.0 → qualys_cli-0.3.1}/tests/test_global_flags.py +0 -0
- {qualys_cli-0.3.0 → qualys_cli-0.3.1}/tests/test_help.py +0 -0
- {qualys_cli-0.3.0 → qualys_cli-0.3.1}/tests/test_high_fixes.py +0 -0
- {qualys_cli-0.3.0 → qualys_cli-0.3.1}/tests/test_isolation.py +0 -0
- {qualys_cli-0.3.0 → qualys_cli-0.3.1}/tests/test_kcs_mitigation.py +0 -0
- {qualys_cli-0.3.0 → qualys_cli-0.3.1}/tests/test_kev.py +0 -0
- {qualys_cli-0.3.0 → qualys_cli-0.3.1}/tests/test_main.py +0 -0
- {qualys_cli-0.3.0 → qualys_cli-0.3.1}/tests/test_mcp_live.py +0 -0
- {qualys_cli-0.3.0 → qualys_cli-0.3.1}/tests/test_med_fixes.py +0 -0
- {qualys_cli-0.3.0 → qualys_cli-0.3.1}/tests/test_pc.py +0 -0
- {qualys_cli-0.3.0 → qualys_cli-0.3.1}/tests/test_pm.py +0 -0
- {qualys_cli-0.3.0 → qualys_cli-0.3.1}/tests/test_resiliency.py +0 -0
- {qualys_cli-0.3.0 → qualys_cli-0.3.1}/tests/test_review_fixes.py +0 -0
- {qualys_cli-0.3.0 → qualys_cli-0.3.1}/tests/test_scanauth.py +0 -0
- {qualys_cli-0.3.0 → qualys_cli-0.3.1}/tests/test_security_fixes.py +0 -0
- {qualys_cli-0.3.0 → qualys_cli-0.3.1}/tests/test_sub.py +0 -0
- {qualys_cli-0.3.0 → qualys_cli-0.3.1}/tests/test_tc.py +0 -0
- {qualys_cli-0.3.0 → qualys_cli-0.3.1}/tests/test_user.py +0 -0
- {qualys_cli-0.3.0 → qualys_cli-0.3.1}/tests/test_vm.py +0 -0
- {qualys_cli-0.3.0 → qualys_cli-0.3.1}/tests/test_was.py +0 -0
|
@@ -6,6 +6,15 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [0.3.1] — 2026-11-04
|
|
10
|
+
|
|
11
|
+
### Fixed
|
|
12
|
+
- `qualys-cli completion <shell>` printed only a "Tip:" line instead of the
|
|
13
|
+
completion script, so shell tab completion could not be set up. It asked
|
|
14
|
+
Typer for the script with Click's env-var format (`zsh_source`) instead of
|
|
15
|
+
Typer's (`source_zsh`); the script is now generated in-process. Workaround
|
|
16
|
+
for 0.3.0: `_QUALYS_CLI_COMPLETE=source_zsh qualys-cli > <fpath-dir>/_qualys-cli`.
|
|
17
|
+
|
|
9
18
|
## [0.3.0] — 2026-11-03
|
|
10
19
|
|
|
11
20
|
### Added
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: qualys-cli
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.1
|
|
4
4
|
Summary: Unified command-line interface for the Qualys Cloud Platform REST APIs (VM, PC, PM, ETM, WAS, TotalCloud, Cloud Agent, Container Security, CSAM, Subscription, Asset, and User management).
|
|
5
5
|
Project-URL: Homepage, https://www.qualys.com
|
|
6
6
|
Author-email: Qualys <support@qualys.com>
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "qualys-cli"
|
|
7
|
-
version = "0.3.
|
|
7
|
+
version = "0.3.1"
|
|
8
8
|
description = "Unified command-line interface for the Qualys Cloud Platform REST APIs (VM, PC, PM, ETM, WAS, TotalCloud, Cloud Agent, Container Security, CSAM, Subscription, Asset, and User management)."
|
|
9
9
|
readme = { file = "README.md", content-type = "text/markdown" }
|
|
10
10
|
license = { file = "LICENSE" }
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.3.1"
|
|
@@ -612,7 +612,7 @@ body.filtering.no-match section.module{display:none}
|
|
|
612
612
|
<aside class="sidebar" aria-label="Documentation navigation">
|
|
613
613
|
<div class="side-header">
|
|
614
614
|
<img src="https://ik.imagekit.io/qualys/image/logo/qualys.svg" alt="Qualys">
|
|
615
|
-
<span class="ver">v0.3.
|
|
615
|
+
<span class="ver">v0.3.1</span>
|
|
616
616
|
</div>
|
|
617
617
|
<div class="side-search">
|
|
618
618
|
<input type="search" id="filter" placeholder="Search commands…"
|
|
@@ -696,7 +696,7 @@ body.filtering.no-match section.module{display:none}
|
|
|
696
696
|
<div class="hero-stats">
|
|
697
697
|
<div class="hero-stat"><span class="n">28</span><span class="l">Modules</span></div>
|
|
698
698
|
<div class="hero-stat"><span class="n">271</span><span class="l">Commands</span></div>
|
|
699
|
-
<div class="hero-stat"><span class="n">v0.3.
|
|
699
|
+
<div class="hero-stat"><span class="n">v0.3.1</span><span class="l">Version</span></div>
|
|
700
700
|
<div class="hero-stat"><span class="n">3.12+</span><span class="l">Python</span></div>
|
|
701
701
|
<div class="hero-stat"><span class="n">MIT</span><span class="l">License</span></div>
|
|
702
702
|
</div>
|
|
@@ -603,23 +603,29 @@ completion_app = typer.Typer(invoke_without_command=False, help="Print a shell-c
|
|
|
603
603
|
def completion(
|
|
604
604
|
shell: str = typer.Argument("bash", help="bash | zsh | fish | powershell"),
|
|
605
605
|
) -> None:
|
|
606
|
-
"""Print the completion script for *shell* to stdout — eval / source it.
|
|
606
|
+
"""Print the completion script for *shell* to stdout — eval / source it.
|
|
607
|
+
|
|
608
|
+
zsh: qualys-cli completion zsh > ~/.oh-my-zsh/custom/completions/_qualys-cli
|
|
609
|
+
bash: eval "$(qualys-cli completion bash)"
|
|
610
|
+
"""
|
|
611
|
+
# Defined in typer._completion_shared; typer.completion only re-exports it
|
|
612
|
+
# implicitly, which strict mypy (no_implicit_reexport) rejects.
|
|
613
|
+
from typer._completion_shared import get_completion_script
|
|
614
|
+
|
|
607
615
|
shell = shell.lower()
|
|
608
616
|
valid = {"bash", "zsh", "fish", "powershell"}
|
|
609
617
|
if shell not in valid:
|
|
610
618
|
_err.print(f"[bold red]Unsupported shell:[/bold red] {shell}. Choose one of {sorted(valid)}.")
|
|
611
619
|
raise typer.Exit(2)
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
sys.stdout.write(
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
"[dim]Tip: install the script by piping it into a file in your shell's "
|
|
620
|
-
"completions directory. See: https://typer.tiangolo.com/tutorial/options-autocompletion/[/dim]"
|
|
620
|
+
# Generated in-process. The previous implementation re-ran `qualys-cli`
|
|
621
|
+
# with _QUALYS_CLI_COMPLETE=<shell>_source — Click's env format — but
|
|
622
|
+
# Typer expects source_<shell>; it answered "Shell source not supported",
|
|
623
|
+
# so no script was ever printed and tab completion could not be set up.
|
|
624
|
+
sys.stdout.write(
|
|
625
|
+
get_completion_script(
|
|
626
|
+
prog_name="qualys-cli", complete_var="_QUALYS_CLI_COMPLETE", shell=shell,
|
|
621
627
|
)
|
|
622
|
-
|
|
628
|
+
)
|
|
623
629
|
|
|
624
630
|
|
|
625
631
|
# ---------------------------------------------------------------------------
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"""Shell tab-completion: script generation and the completion engine it calls."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import pytest
|
|
6
|
+
from typer.testing import CliRunner
|
|
7
|
+
|
|
8
|
+
from qualys_cli.cli import app
|
|
9
|
+
|
|
10
|
+
runner = CliRunner()
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@pytest.mark.parametrize(
|
|
14
|
+
("shell", "marker"),
|
|
15
|
+
[
|
|
16
|
+
("zsh", "#compdef qualys-cli"),
|
|
17
|
+
("bash", "complete -o"),
|
|
18
|
+
("fish", "complete --command qualys-cli"),
|
|
19
|
+
("powershell", "Register-ArgumentCompleter"),
|
|
20
|
+
],
|
|
21
|
+
)
|
|
22
|
+
def test_completion_prints_script(shell: str, marker: str) -> None:
|
|
23
|
+
result = runner.invoke(app, ["completion", shell])
|
|
24
|
+
assert result.exit_code == 0, result.output
|
|
25
|
+
assert marker in result.stdout
|
|
26
|
+
# The script must call back into the CLI with the matching env var.
|
|
27
|
+
assert "_QUALYS_CLI_COMPLETE" in result.stdout
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def test_completion_rejects_unknown_shell() -> None:
|
|
31
|
+
result = runner.invoke(app, ["completion", "tcsh"])
|
|
32
|
+
assert result.exit_code == 2
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def _complete(line: str) -> str:
|
|
36
|
+
result = runner.invoke(
|
|
37
|
+
app,
|
|
38
|
+
[],
|
|
39
|
+
prog_name="qualys-cli",
|
|
40
|
+
env={"_QUALYS_CLI_COMPLETE": "complete_zsh", "_TYPER_COMPLETE_ARGS": line},
|
|
41
|
+
)
|
|
42
|
+
assert result.exit_code == 0, result.output
|
|
43
|
+
return result.stdout
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def test_completion_engine_lists_modules() -> None:
|
|
47
|
+
out = _complete("qualys-cli ")
|
|
48
|
+
for module in ("vm", "pc", "cs", "etm", "pm", "ca", "was", "csam"):
|
|
49
|
+
assert f'"{module}":' in out
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def test_completion_engine_lists_module_resources() -> None:
|
|
53
|
+
out = _complete("qualys-cli cs ")
|
|
54
|
+
for resource in ("image", "k8s-resource", "secret-detector", "qid-list", "tag"):
|
|
55
|
+
assert f'"{resource}":' in out
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def test_completion_engine_lists_resource_actions() -> None:
|
|
59
|
+
out = _complete("qualys-cli etm finding ")
|
|
60
|
+
for action in ("list", "get", "count"):
|
|
61
|
+
assert f'"{action}":' in out
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.3.0"
|
|
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
|
|
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
|