qgis-plugin-analyzer 1.4.0__py3-none-any.whl → 1.6.0__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.
- analyzer/__init__.py +2 -1
- analyzer/cli/__init__.py +14 -0
- analyzer/cli/app.py +147 -0
- analyzer/cli/base.py +93 -0
- analyzer/cli/commands/__init__.py +19 -0
- analyzer/cli/commands/analyze.py +47 -0
- analyzer/cli/commands/fix.py +58 -0
- analyzer/cli/commands/init.py +41 -0
- analyzer/cli/commands/list_rules.py +41 -0
- analyzer/cli/commands/security.py +46 -0
- analyzer/cli/commands/summary.py +52 -0
- analyzer/cli/commands/version.py +41 -0
- analyzer/cli.py +4 -281
- analyzer/commands.py +163 -0
- analyzer/engine.py +491 -245
- analyzer/fixer.py +206 -130
- analyzer/reporters/markdown_reporter.py +88 -14
- analyzer/reporters/summary_reporter.py +226 -49
- analyzer/rules/qgis_rules.py +3 -1
- analyzer/scanner.py +219 -711
- analyzer/secrets.py +84 -0
- analyzer/security_checker.py +85 -0
- analyzer/security_rules.py +127 -0
- analyzer/transformers.py +29 -8
- analyzer/utils/__init__.py +2 -0
- analyzer/utils/path_utils.py +53 -1
- analyzer/validators.py +90 -55
- analyzer/visitors/__init__.py +19 -0
- analyzer/visitors/base.py +75 -0
- analyzer/visitors/composite_visitor.py +73 -0
- analyzer/visitors/imports_visitor.py +85 -0
- analyzer/visitors/metrics_visitor.py +158 -0
- analyzer/visitors/security_visitor.py +52 -0
- analyzer/visitors/standards_visitor.py +284 -0
- {qgis_plugin_analyzer-1.4.0.dist-info → qgis_plugin_analyzer-1.6.0.dist-info}/METADATA +32 -10
- qgis_plugin_analyzer-1.6.0.dist-info/RECORD +52 -0
- {qgis_plugin_analyzer-1.4.0.dist-info → qgis_plugin_analyzer-1.6.0.dist-info}/WHEEL +1 -1
- qgis_plugin_analyzer-1.4.0.dist-info/RECORD +0 -30
- {qgis_plugin_analyzer-1.4.0.dist-info → qgis_plugin_analyzer-1.6.0.dist-info}/entry_points.txt +0 -0
- {qgis_plugin_analyzer-1.4.0.dist-info → qgis_plugin_analyzer-1.6.0.dist-info}/licenses/LICENSE +0 -0
- {qgis_plugin_analyzer-1.4.0.dist-info → qgis_plugin_analyzer-1.6.0.dist-info}/top_level.txt +0 -0
analyzer/__init__.py
CHANGED
analyzer/cli/__init__.py
ADDED
analyzer/cli/app.py
ADDED
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
"""CLI Application orchestrator."""
|
|
2
|
+
|
|
3
|
+
import argparse
|
|
4
|
+
import pathlib
|
|
5
|
+
import sys
|
|
6
|
+
from typing import Dict, List, Optional
|
|
7
|
+
|
|
8
|
+
from ..utils import logger, setup_logger
|
|
9
|
+
from .base import BaseCommand
|
|
10
|
+
from .commands import (
|
|
11
|
+
AnalyzeCommand,
|
|
12
|
+
FixCommand,
|
|
13
|
+
InitCommand,
|
|
14
|
+
ListRulesCommand,
|
|
15
|
+
SecurityCommand,
|
|
16
|
+
SummaryCommand,
|
|
17
|
+
VersionCommand,
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class CLIApp:
|
|
22
|
+
"""Main CLI application orchestrator.
|
|
23
|
+
|
|
24
|
+
Manages command registration, argument parsing, and execution.
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
def __init__(self):
|
|
28
|
+
"""Initialize the CLI application with all available commands."""
|
|
29
|
+
self.commands: Dict[str, BaseCommand] = self._discover_commands()
|
|
30
|
+
|
|
31
|
+
def _discover_commands(self) -> Dict[str, BaseCommand]:
|
|
32
|
+
"""Auto-discover and instantiate all command classes.
|
|
33
|
+
|
|
34
|
+
Returns:
|
|
35
|
+
Dictionary mapping command names to command instances.
|
|
36
|
+
"""
|
|
37
|
+
command_classes: List[type[BaseCommand]] = [
|
|
38
|
+
AnalyzeCommand,
|
|
39
|
+
SecurityCommand,
|
|
40
|
+
FixCommand,
|
|
41
|
+
ListRulesCommand,
|
|
42
|
+
InitCommand,
|
|
43
|
+
SummaryCommand,
|
|
44
|
+
VersionCommand,
|
|
45
|
+
]
|
|
46
|
+
return {cmd().name: cmd() for cmd in command_classes}
|
|
47
|
+
|
|
48
|
+
def _build_parser(self) -> argparse.ArgumentParser:
|
|
49
|
+
"""Build the argument parser with all commands.
|
|
50
|
+
|
|
51
|
+
Returns:
|
|
52
|
+
Configured ArgumentParser instance.
|
|
53
|
+
"""
|
|
54
|
+
from .. import __version__
|
|
55
|
+
|
|
56
|
+
parser = argparse.ArgumentParser(
|
|
57
|
+
description="QGIS Plugin Analyzer - A guardian for your PyQGIS code"
|
|
58
|
+
)
|
|
59
|
+
parser.add_argument("-v", "--version", action="version", version=f"%(prog)s {__version__}")
|
|
60
|
+
subparsers = parser.add_subparsers(dest="command", help="Command to execute")
|
|
61
|
+
|
|
62
|
+
# Register all commands
|
|
63
|
+
for cmd in self.commands.values():
|
|
64
|
+
cmd_parser = subparsers.add_parser(cmd.name, help=cmd.help)
|
|
65
|
+
cmd.configure_parser(cmd_parser)
|
|
66
|
+
|
|
67
|
+
return parser
|
|
68
|
+
|
|
69
|
+
def _parse_args(
|
|
70
|
+
self, parser: argparse.ArgumentParser, argv: Optional[List[str]] = None
|
|
71
|
+
) -> argparse.Namespace:
|
|
72
|
+
"""Parse command-line arguments with legacy support.
|
|
73
|
+
|
|
74
|
+
Args:
|
|
75
|
+
parser: The argument parser.
|
|
76
|
+
argv: Optional argument list (defaults to sys.argv).
|
|
77
|
+
|
|
78
|
+
Returns:
|
|
79
|
+
Parsed arguments namespace.
|
|
80
|
+
"""
|
|
81
|
+
if argv is None:
|
|
82
|
+
argv = sys.argv[1:]
|
|
83
|
+
|
|
84
|
+
# Legacy support: default to 'analyze' if first arg is a path
|
|
85
|
+
if argv and argv[0] not in self.commands and not argv[0].startswith("-"):
|
|
86
|
+
argv.insert(0, "analyze")
|
|
87
|
+
|
|
88
|
+
return parser.parse_args(argv)
|
|
89
|
+
|
|
90
|
+
def _setup_logging(self, args: argparse.Namespace) -> None:
|
|
91
|
+
"""Setup logging based on command arguments.
|
|
92
|
+
|
|
93
|
+
Args:
|
|
94
|
+
args: Parsed command-line arguments.
|
|
95
|
+
"""
|
|
96
|
+
output_dir = pathlib.Path(getattr(args, "output", "./analysis_results")).resolve()
|
|
97
|
+
output_dir.mkdir(parents=True, exist_ok=True)
|
|
98
|
+
setup_logger(output_dir)
|
|
99
|
+
|
|
100
|
+
def _execute_command(self, args: argparse.Namespace) -> int:
|
|
101
|
+
"""Execute the selected command.
|
|
102
|
+
|
|
103
|
+
Args:
|
|
104
|
+
args: Parsed command-line arguments.
|
|
105
|
+
|
|
106
|
+
Returns:
|
|
107
|
+
Exit code from command execution.
|
|
108
|
+
"""
|
|
109
|
+
if not args.command or args.command not in self.commands:
|
|
110
|
+
return 1
|
|
111
|
+
|
|
112
|
+
command = self.commands[args.command]
|
|
113
|
+
return command.execute(args)
|
|
114
|
+
|
|
115
|
+
def run(self, argv: Optional[List[str]] = None) -> int:
|
|
116
|
+
"""Run the CLI application.
|
|
117
|
+
|
|
118
|
+
Args:
|
|
119
|
+
argv: Optional argument list (defaults to sys.argv).
|
|
120
|
+
|
|
121
|
+
Returns:
|
|
122
|
+
Exit code (0 for success, non-zero for failure).
|
|
123
|
+
"""
|
|
124
|
+
parser = self._build_parser()
|
|
125
|
+
|
|
126
|
+
try:
|
|
127
|
+
args = self._parse_args(parser, argv)
|
|
128
|
+
|
|
129
|
+
if not args.command:
|
|
130
|
+
parser.print_help()
|
|
131
|
+
return 0
|
|
132
|
+
|
|
133
|
+
self._setup_logging(args)
|
|
134
|
+
return self._execute_command(args)
|
|
135
|
+
|
|
136
|
+
except KeyboardInterrupt:
|
|
137
|
+
logger.info("\n⏹️ Analysis interrupted.")
|
|
138
|
+
return 1
|
|
139
|
+
except FileNotFoundError as e:
|
|
140
|
+
logger.error(f"Error: File not found: {e}")
|
|
141
|
+
return 1
|
|
142
|
+
except ValueError as e:
|
|
143
|
+
logger.error(f"Error: {e}")
|
|
144
|
+
return 1
|
|
145
|
+
except Exception as e:
|
|
146
|
+
logger.critical(f"Critical Error: {e}", exc_info=True)
|
|
147
|
+
return 1
|
analyzer/cli/base.py
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
"""Base command class for CLI commands."""
|
|
2
|
+
|
|
3
|
+
import argparse
|
|
4
|
+
import pathlib
|
|
5
|
+
from abc import ABC, abstractmethod
|
|
6
|
+
from typing import Optional
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class BaseCommand(ABC):
|
|
10
|
+
"""Abstract base class for CLI commands.
|
|
11
|
+
|
|
12
|
+
Each command encapsulates its own argument configuration and execution logic.
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
@property
|
|
16
|
+
@abstractmethod
|
|
17
|
+
def name(self) -> str:
|
|
18
|
+
"""Command name as it appears in the CLI.
|
|
19
|
+
|
|
20
|
+
Returns:
|
|
21
|
+
The command name string.
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
@property
|
|
25
|
+
@abstractmethod
|
|
26
|
+
def help(self) -> str:
|
|
27
|
+
"""Help text for the command.
|
|
28
|
+
|
|
29
|
+
Returns:
|
|
30
|
+
A brief description of what the command does.
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
@abstractmethod
|
|
34
|
+
def configure_parser(self, parser: argparse.ArgumentParser) -> None:
|
|
35
|
+
"""Configure command-specific arguments.
|
|
36
|
+
|
|
37
|
+
Args:
|
|
38
|
+
parser: The argument parser for this command.
|
|
39
|
+
"""
|
|
40
|
+
|
|
41
|
+
@abstractmethod
|
|
42
|
+
def execute(self, args: argparse.Namespace) -> int:
|
|
43
|
+
"""Execute the command.
|
|
44
|
+
|
|
45
|
+
Args:
|
|
46
|
+
args: Parsed command-line arguments.
|
|
47
|
+
|
|
48
|
+
Returns:
|
|
49
|
+
Exit code (0 for success, non-zero for failure).
|
|
50
|
+
"""
|
|
51
|
+
|
|
52
|
+
def add_common_args(
|
|
53
|
+
self,
|
|
54
|
+
parser: argparse.ArgumentParser,
|
|
55
|
+
include_output: bool = True,
|
|
56
|
+
include_profile: bool = True,
|
|
57
|
+
) -> None:
|
|
58
|
+
"""Add common arguments shared across multiple commands.
|
|
59
|
+
|
|
60
|
+
Args:
|
|
61
|
+
parser: The argument parser to add arguments to.
|
|
62
|
+
include_output: Whether to include the --output argument.
|
|
63
|
+
include_profile: Whether to include the --profile argument.
|
|
64
|
+
"""
|
|
65
|
+
if include_output:
|
|
66
|
+
parser.add_argument(
|
|
67
|
+
"-o",
|
|
68
|
+
"--output",
|
|
69
|
+
help="Output directory for reports",
|
|
70
|
+
default="./analysis_results",
|
|
71
|
+
)
|
|
72
|
+
if include_profile:
|
|
73
|
+
parser.add_argument(
|
|
74
|
+
"-p",
|
|
75
|
+
"--profile",
|
|
76
|
+
help="Configuration profile from pyproject.toml",
|
|
77
|
+
default="default",
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
def setup_output_dir(self, args: argparse.Namespace) -> Optional[pathlib.Path]:
|
|
81
|
+
"""Setup and return the output directory if present in args.
|
|
82
|
+
|
|
83
|
+
Args:
|
|
84
|
+
args: Parsed command-line arguments.
|
|
85
|
+
|
|
86
|
+
Returns:
|
|
87
|
+
The resolved output directory path, or None if not applicable.
|
|
88
|
+
"""
|
|
89
|
+
if hasattr(args, "output"):
|
|
90
|
+
output_dir = pathlib.Path(args.output).resolve()
|
|
91
|
+
output_dir.mkdir(parents=True, exist_ok=True)
|
|
92
|
+
return output_dir
|
|
93
|
+
return None
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"""CLI commands package."""
|
|
2
|
+
|
|
3
|
+
from .analyze import AnalyzeCommand
|
|
4
|
+
from .fix import FixCommand
|
|
5
|
+
from .init import InitCommand
|
|
6
|
+
from .list_rules import ListRulesCommand
|
|
7
|
+
from .security import SecurityCommand
|
|
8
|
+
from .summary import SummaryCommand
|
|
9
|
+
from .version import VersionCommand
|
|
10
|
+
|
|
11
|
+
__all__ = [
|
|
12
|
+
"AnalyzeCommand",
|
|
13
|
+
"SecurityCommand",
|
|
14
|
+
"FixCommand",
|
|
15
|
+
"ListRulesCommand",
|
|
16
|
+
"InitCommand",
|
|
17
|
+
"SummaryCommand",
|
|
18
|
+
"VersionCommand",
|
|
19
|
+
]
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"""Analyze command implementation."""
|
|
2
|
+
|
|
3
|
+
import argparse
|
|
4
|
+
|
|
5
|
+
from ...commands import handle_analyze
|
|
6
|
+
from ..base import BaseCommand
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class AnalyzeCommand(BaseCommand):
|
|
10
|
+
"""Command to analyze an existing QGIS plugin."""
|
|
11
|
+
|
|
12
|
+
@property
|
|
13
|
+
def name(self) -> str:
|
|
14
|
+
"""Command name."""
|
|
15
|
+
return "analyze"
|
|
16
|
+
|
|
17
|
+
@property
|
|
18
|
+
def help(self) -> str:
|
|
19
|
+
"""Command help text."""
|
|
20
|
+
return "Analyze an existing QGIS plugin"
|
|
21
|
+
|
|
22
|
+
def configure_parser(self, parser: argparse.ArgumentParser) -> None:
|
|
23
|
+
"""Configure analyze command arguments.
|
|
24
|
+
|
|
25
|
+
Args:
|
|
26
|
+
parser: The argument parser for this command.
|
|
27
|
+
"""
|
|
28
|
+
parser.add_argument("project_path", help="Path to the QGIS project to analyze")
|
|
29
|
+
self.add_common_args(parser)
|
|
30
|
+
parser.add_argument(
|
|
31
|
+
"-r",
|
|
32
|
+
"--report",
|
|
33
|
+
action="store_true",
|
|
34
|
+
help="Generate detailed HTML/Markdown reports",
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
def execute(self, args: argparse.Namespace) -> int:
|
|
38
|
+
"""Execute the analyze command.
|
|
39
|
+
|
|
40
|
+
Args:
|
|
41
|
+
args: Parsed command-line arguments.
|
|
42
|
+
|
|
43
|
+
Returns:
|
|
44
|
+
Exit code (0 for success).
|
|
45
|
+
"""
|
|
46
|
+
handle_analyze(args)
|
|
47
|
+
return 0
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"""Fix command implementation."""
|
|
2
|
+
|
|
3
|
+
import argparse
|
|
4
|
+
|
|
5
|
+
from ...commands import handle_fix
|
|
6
|
+
from ..base import BaseCommand
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class FixCommand(BaseCommand):
|
|
10
|
+
"""Command to auto-fix common QGIS plugin issues."""
|
|
11
|
+
|
|
12
|
+
@property
|
|
13
|
+
def name(self) -> str:
|
|
14
|
+
"""Command name."""
|
|
15
|
+
return "fix"
|
|
16
|
+
|
|
17
|
+
@property
|
|
18
|
+
def help(self) -> str:
|
|
19
|
+
"""Command help text."""
|
|
20
|
+
return "Auto-fix common QGIS plugin issues"
|
|
21
|
+
|
|
22
|
+
def configure_parser(self, parser: argparse.ArgumentParser) -> None:
|
|
23
|
+
"""Configure fix command arguments.
|
|
24
|
+
|
|
25
|
+
Args:
|
|
26
|
+
parser: The argument parser for this command.
|
|
27
|
+
"""
|
|
28
|
+
parser.add_argument("path", type=str, help="Path to the QGIS plugin directory")
|
|
29
|
+
parser.add_argument(
|
|
30
|
+
"--dry-run",
|
|
31
|
+
action="store_true",
|
|
32
|
+
default=True,
|
|
33
|
+
help="Show proposed changes without applying (default: True)",
|
|
34
|
+
)
|
|
35
|
+
parser.add_argument("--apply", action="store_true", help="Apply fixes (disables dry-run)")
|
|
36
|
+
parser.add_argument(
|
|
37
|
+
"--auto-approve",
|
|
38
|
+
action="store_true",
|
|
39
|
+
help="Apply all fixes without confirmation",
|
|
40
|
+
)
|
|
41
|
+
self.add_common_args(parser, include_output=False)
|
|
42
|
+
parser.add_argument(
|
|
43
|
+
"--rules",
|
|
44
|
+
type=str,
|
|
45
|
+
help="Comma-separated list of rule IDs to fix",
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
def execute(self, args: argparse.Namespace) -> int:
|
|
49
|
+
"""Execute the fix command.
|
|
50
|
+
|
|
51
|
+
Args:
|
|
52
|
+
args: Parsed command-line arguments.
|
|
53
|
+
|
|
54
|
+
Returns:
|
|
55
|
+
Exit code (0 for success).
|
|
56
|
+
"""
|
|
57
|
+
handle_fix(args)
|
|
58
|
+
return 0
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"""Init command implementation."""
|
|
2
|
+
|
|
3
|
+
import argparse
|
|
4
|
+
|
|
5
|
+
from ...commands import handle_init
|
|
6
|
+
from ..base import BaseCommand
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class InitCommand(BaseCommand):
|
|
10
|
+
"""Command to initialize a new .analyzerignore with defaults."""
|
|
11
|
+
|
|
12
|
+
@property
|
|
13
|
+
def name(self) -> str:
|
|
14
|
+
"""Command name."""
|
|
15
|
+
return "init"
|
|
16
|
+
|
|
17
|
+
@property
|
|
18
|
+
def help(self) -> str:
|
|
19
|
+
"""Command help text."""
|
|
20
|
+
return "Initialize a new .analyzerignore with defaults"
|
|
21
|
+
|
|
22
|
+
def configure_parser(self, parser: argparse.ArgumentParser) -> None:
|
|
23
|
+
"""Configure init command arguments.
|
|
24
|
+
|
|
25
|
+
Args:
|
|
26
|
+
parser: The argument parser for this command.
|
|
27
|
+
"""
|
|
28
|
+
# No additional arguments needed
|
|
29
|
+
pass
|
|
30
|
+
|
|
31
|
+
def execute(self, args: argparse.Namespace) -> int:
|
|
32
|
+
"""Execute the init command.
|
|
33
|
+
|
|
34
|
+
Args:
|
|
35
|
+
args: Parsed command-line arguments.
|
|
36
|
+
|
|
37
|
+
Returns:
|
|
38
|
+
Exit code (0 for success).
|
|
39
|
+
"""
|
|
40
|
+
handle_init()
|
|
41
|
+
return 0
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"""List rules command implementation."""
|
|
2
|
+
|
|
3
|
+
import argparse
|
|
4
|
+
|
|
5
|
+
from ...commands import handle_list_rules
|
|
6
|
+
from ..base import BaseCommand
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class ListRulesCommand(BaseCommand):
|
|
10
|
+
"""Command to list all available QGIS audit rules."""
|
|
11
|
+
|
|
12
|
+
@property
|
|
13
|
+
def name(self) -> str:
|
|
14
|
+
"""Command name."""
|
|
15
|
+
return "list-rules"
|
|
16
|
+
|
|
17
|
+
@property
|
|
18
|
+
def help(self) -> str:
|
|
19
|
+
"""Command help text."""
|
|
20
|
+
return "List all available QGIS audit rules"
|
|
21
|
+
|
|
22
|
+
def configure_parser(self, parser: argparse.ArgumentParser) -> None:
|
|
23
|
+
"""Configure list-rules command arguments.
|
|
24
|
+
|
|
25
|
+
Args:
|
|
26
|
+
parser: The argument parser for this command.
|
|
27
|
+
"""
|
|
28
|
+
# No additional arguments needed
|
|
29
|
+
pass
|
|
30
|
+
|
|
31
|
+
def execute(self, args: argparse.Namespace) -> int:
|
|
32
|
+
"""Execute the list-rules command.
|
|
33
|
+
|
|
34
|
+
Args:
|
|
35
|
+
args: Parsed command-line arguments.
|
|
36
|
+
|
|
37
|
+
Returns:
|
|
38
|
+
Exit code (0 for success).
|
|
39
|
+
"""
|
|
40
|
+
handle_list_rules()
|
|
41
|
+
return 0
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"""Security command implementation."""
|
|
2
|
+
|
|
3
|
+
import argparse
|
|
4
|
+
|
|
5
|
+
from ...commands import handle_security
|
|
6
|
+
from ..base import BaseCommand
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class SecurityCommand(BaseCommand):
|
|
10
|
+
"""Command to run a focused security scan."""
|
|
11
|
+
|
|
12
|
+
@property
|
|
13
|
+
def name(self) -> str:
|
|
14
|
+
"""Command name."""
|
|
15
|
+
return "security"
|
|
16
|
+
|
|
17
|
+
@property
|
|
18
|
+
def help(self) -> str:
|
|
19
|
+
"""Command help text."""
|
|
20
|
+
return "Run a focused security scan"
|
|
21
|
+
|
|
22
|
+
def configure_parser(self, parser: argparse.ArgumentParser) -> None:
|
|
23
|
+
"""Configure security command arguments.
|
|
24
|
+
|
|
25
|
+
Args:
|
|
26
|
+
parser: The argument parser for this command.
|
|
27
|
+
"""
|
|
28
|
+
parser.add_argument("project_path", help="Path to the QGIS project to scan")
|
|
29
|
+
self.add_common_args(parser)
|
|
30
|
+
parser.add_argument(
|
|
31
|
+
"--deep",
|
|
32
|
+
action="store_true",
|
|
33
|
+
help="Run more intensive (but slower) security checks",
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
def execute(self, args: argparse.Namespace) -> int:
|
|
37
|
+
"""Execute the security command.
|
|
38
|
+
|
|
39
|
+
Args:
|
|
40
|
+
args: Parsed command-line arguments.
|
|
41
|
+
|
|
42
|
+
Returns:
|
|
43
|
+
Exit code (0 for success).
|
|
44
|
+
"""
|
|
45
|
+
handle_security(args)
|
|
46
|
+
return 0
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"""Summary command implementation."""
|
|
2
|
+
|
|
3
|
+
import argparse
|
|
4
|
+
|
|
5
|
+
from ...commands import handle_summary
|
|
6
|
+
from ..base import BaseCommand
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class SummaryCommand(BaseCommand):
|
|
10
|
+
"""Command to show a quick terminal summary of analysis results."""
|
|
11
|
+
|
|
12
|
+
@property
|
|
13
|
+
def name(self) -> str:
|
|
14
|
+
"""Command name."""
|
|
15
|
+
return "summary"
|
|
16
|
+
|
|
17
|
+
@property
|
|
18
|
+
def help(self) -> str:
|
|
19
|
+
"""Command help text."""
|
|
20
|
+
return "Show a quick terminal summary of analysis results"
|
|
21
|
+
|
|
22
|
+
def configure_parser(self, parser: argparse.ArgumentParser) -> None:
|
|
23
|
+
"""Configure summary command arguments.
|
|
24
|
+
|
|
25
|
+
Args:
|
|
26
|
+
parser: The argument parser for this command.
|
|
27
|
+
"""
|
|
28
|
+
parser.add_argument(
|
|
29
|
+
"-i",
|
|
30
|
+
"--input",
|
|
31
|
+
help="Path to the research JSON file",
|
|
32
|
+
default="analysis_results/project_context.json",
|
|
33
|
+
)
|
|
34
|
+
parser.add_argument(
|
|
35
|
+
"-b",
|
|
36
|
+
"--by",
|
|
37
|
+
choices=["total", "modules", "functions", "classes"],
|
|
38
|
+
default="total",
|
|
39
|
+
help="Granularity of the summary (default: total)",
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
def execute(self, args: argparse.Namespace) -> int:
|
|
43
|
+
"""Execute the summary command.
|
|
44
|
+
|
|
45
|
+
Args:
|
|
46
|
+
args: Parsed command-line arguments.
|
|
47
|
+
|
|
48
|
+
Returns:
|
|
49
|
+
Exit code (0 for success).
|
|
50
|
+
"""
|
|
51
|
+
handle_summary(args)
|
|
52
|
+
return 0
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"""Version command implementation."""
|
|
2
|
+
|
|
3
|
+
import argparse
|
|
4
|
+
|
|
5
|
+
from ... import __version__
|
|
6
|
+
from ..base import BaseCommand
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class VersionCommand(BaseCommand):
|
|
10
|
+
"""Command to show the current version of the analyzer."""
|
|
11
|
+
|
|
12
|
+
@property
|
|
13
|
+
def name(self) -> str:
|
|
14
|
+
"""Command name."""
|
|
15
|
+
return "version"
|
|
16
|
+
|
|
17
|
+
@property
|
|
18
|
+
def help(self) -> str:
|
|
19
|
+
"""Command help text."""
|
|
20
|
+
return "Show the current version of the analyzer"
|
|
21
|
+
|
|
22
|
+
def configure_parser(self, parser: argparse.ArgumentParser) -> None:
|
|
23
|
+
"""Configure version command arguments.
|
|
24
|
+
|
|
25
|
+
Args:
|
|
26
|
+
parser: The argument parser for this command.
|
|
27
|
+
"""
|
|
28
|
+
# No additional arguments needed
|
|
29
|
+
pass
|
|
30
|
+
|
|
31
|
+
def execute(self, args: argparse.Namespace) -> int:
|
|
32
|
+
"""Execute the version command.
|
|
33
|
+
|
|
34
|
+
Args:
|
|
35
|
+
args: Parsed command-line arguments.
|
|
36
|
+
|
|
37
|
+
Returns:
|
|
38
|
+
Exit code (0 for success).
|
|
39
|
+
"""
|
|
40
|
+
print(f"qgis-analyzer {__version__}")
|
|
41
|
+
return 0
|