qgis-plugin-analyzer 1.5.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.
Files changed (37) hide show
  1. analyzer/cli/__init__.py +14 -0
  2. analyzer/cli/app.py +147 -0
  3. analyzer/cli/base.py +93 -0
  4. analyzer/cli/commands/__init__.py +19 -0
  5. analyzer/cli/commands/analyze.py +47 -0
  6. analyzer/cli/commands/fix.py +58 -0
  7. analyzer/cli/commands/init.py +41 -0
  8. analyzer/cli/commands/list_rules.py +41 -0
  9. analyzer/cli/commands/security.py +46 -0
  10. analyzer/cli/commands/summary.py +52 -0
  11. analyzer/cli/commands/version.py +41 -0
  12. analyzer/cli.py +4 -184
  13. analyzer/commands.py +7 -7
  14. analyzer/engine.py +421 -238
  15. analyzer/fixer.py +206 -130
  16. analyzer/reporters/markdown_reporter.py +48 -15
  17. analyzer/reporters/summary_reporter.py +193 -80
  18. analyzer/scanner.py +218 -138
  19. analyzer/transformers.py +29 -8
  20. analyzer/utils/__init__.py +2 -0
  21. analyzer/utils/path_utils.py +53 -1
  22. analyzer/validators.py +90 -55
  23. analyzer/visitors/__init__.py +19 -0
  24. analyzer/visitors/base.py +75 -0
  25. analyzer/visitors/composite_visitor.py +73 -0
  26. analyzer/visitors/imports_visitor.py +85 -0
  27. analyzer/visitors/metrics_visitor.py +158 -0
  28. analyzer/visitors/security_visitor.py +52 -0
  29. analyzer/visitors/standards_visitor.py +284 -0
  30. {qgis_plugin_analyzer-1.5.0.dist-info → qgis_plugin_analyzer-1.6.0.dist-info}/METADATA +16 -7
  31. qgis_plugin_analyzer-1.6.0.dist-info/RECORD +52 -0
  32. analyzer/visitors.py +0 -455
  33. qgis_plugin_analyzer-1.5.0.dist-info/RECORD +0 -35
  34. {qgis_plugin_analyzer-1.5.0.dist-info → qgis_plugin_analyzer-1.6.0.dist-info}/WHEEL +0 -0
  35. {qgis_plugin_analyzer-1.5.0.dist-info → qgis_plugin_analyzer-1.6.0.dist-info}/entry_points.txt +0 -0
  36. {qgis_plugin_analyzer-1.5.0.dist-info → qgis_plugin_analyzer-1.6.0.dist-info}/licenses/LICENSE +0 -0
  37. {qgis_plugin_analyzer-1.5.0.dist-info → qgis_plugin_analyzer-1.6.0.dist-info}/top_level.txt +0 -0
analyzer/cli.py CHANGED
@@ -19,195 +19,15 @@
19
19
  # ***************************************************************************/
20
20
 
21
21
 
22
- import argparse
23
- import pathlib
24
22
  import sys
25
23
 
26
- from . import __version__
27
- from .commands import (
28
- handle_analyze,
29
- handle_fix,
30
- handle_init,
31
- handle_list_rules,
32
- handle_security,
33
- handle_summary,
34
- )
35
- from .utils import logger, setup_logger
36
-
37
-
38
- def _setup_argument_parser() -> argparse.ArgumentParser:
39
- """Sets up and returns the argument parser with all subcommands.
40
-
41
- Returns:
42
- A configured ArgumentParser instance.
43
- """
44
- parser = argparse.ArgumentParser(
45
- description="QGIS Plugin Analyzer - A guardian for your PyQGIS code"
46
- )
47
- parser.add_argument("-v", "--version", action="version", version=f"%(prog)s {__version__}")
48
- subparsers = parser.add_subparsers(dest="command", help="Command to execute")
49
-
50
- # Analyze Command
51
- analyze_parser = subparsers.add_parser("analyze", help="Analyze an existing QGIS plugin")
52
- analyze_parser.add_argument("project_path", help="Path to the QGIS project to analyze")
53
- analyze_parser.add_argument(
54
- "-o",
55
- "--output",
56
- help="Output directory for reports",
57
- default="./analysis_results",
58
- )
59
- analyze_parser.add_argument(
60
- "-r",
61
- "--report",
62
- action="store_true",
63
- help="Generate detailed HTML/Markdown reports",
64
- )
65
- analyze_parser.add_argument(
66
- "-p",
67
- "--profile",
68
- help="Configuration profile from pyproject.toml",
69
- default="default",
70
- )
71
-
72
- # Security Command
73
- security_parser = subparsers.add_parser("security", help="Run a focused security scan")
74
- security_parser.add_argument("project_path", help="Path to the QGIS project to scan")
75
- security_parser.add_argument(
76
- "-o",
77
- "--output",
78
- help="Output directory for reports",
79
- default="./analysis_results",
80
- )
81
- security_parser.add_argument(
82
- "-p",
83
- "--profile",
84
- help="Configuration profile from pyproject.toml",
85
- default="default",
86
- )
87
- security_parser.add_argument(
88
- "--deep",
89
- action="store_true",
90
- help="Run more intensive (but slower) security checks",
91
- )
92
-
93
- # Fix Command
94
- fix_parser = subparsers.add_parser("fix", help="Auto-fix common QGIS plugin issues")
95
- fix_parser.add_argument("path", type=str, help="Path to the QGIS plugin directory")
96
- fix_parser.add_argument(
97
- "--dry-run",
98
- action="store_true",
99
- default=True,
100
- help="Show proposed changes without applying (default: True)",
101
- )
102
- fix_parser.add_argument("--apply", action="store_true", help="Apply fixes (disables dry-run)")
103
- fix_parser.add_argument(
104
- "--auto-approve",
105
- action="store_true",
106
- help="Apply all fixes without confirmation",
107
- )
108
- fix_parser.add_argument(
109
- "-p",
110
- "--profile",
111
- help="Configuration profile from pyproject.toml",
112
- default="default",
113
- )
114
- fix_parser.add_argument(
115
- "--rules",
116
- type=str,
117
- help="Comma-separated list of rule IDs to fix",
118
- )
119
-
120
- # List Rules Command
121
- subparsers.add_parser("list-rules", help="List all available QGIS audit rules")
122
-
123
- # Version Command
124
- subparsers.add_parser("version", help="Show the current version of the analyzer")
125
-
126
- # Init Command
127
- subparsers.add_parser("init", help="Initialize a new .analyzerignore with defaults")
128
-
129
- # Summary Command
130
- summary_parser = subparsers.add_parser(
131
- "summary", help="Show a quick terminal summary of analysis results"
132
- )
133
- summary_parser.add_argument(
134
- "-i",
135
- "--input",
136
- help="Path to the research JSON file",
137
- default="analysis_results/project_context.json",
138
- )
139
- summary_parser.add_argument(
140
- "-b",
141
- "--by",
142
- choices=["total", "modules", "functions", "classes"],
143
- default="total",
144
- help="Granularity of the summary (default: total)",
145
- )
146
-
147
- return parser
24
+ from .cli import CLIApp
148
25
 
149
26
 
150
27
  def main() -> None:
151
- """Main entry point for the QGIS Plugin Analyzer CLI.
152
-
153
- Orchestrates the command execution based on parsed arguments and
154
- sets up the global logging environment.
155
- """
156
- parser = _setup_argument_parser()
157
-
158
- # Legacy support / default to analyze if no command provided
159
- if len(sys.argv) > 1 and sys.argv[1] not in [
160
- "analyze",
161
- "security",
162
- "version",
163
- "fix",
164
- "list-rules",
165
- "init",
166
- "summary",
167
- "-h",
168
- "--help",
169
- ]:
170
- # If the first argument is a path (doesn't start with -), assume 'analyze'
171
- if not sys.argv[1].startswith("-"):
172
- sys.argv.insert(1, "analyze")
173
-
174
- args = parser.parse_args()
175
-
176
- # Initialize logger (default to analysis_results if not specified)
177
- output_dir = pathlib.Path(getattr(args, "output", "./analysis_results")).resolve()
178
- output_dir.mkdir(parents=True, exist_ok=True)
179
- setup_logger(output_dir)
180
-
181
- # Command Dispatcher
182
- dispatch = {
183
- "fix": lambda: handle_fix(args),
184
- "analyze": lambda: handle_analyze(args),
185
- "list-rules": lambda: handle_list_rules(),
186
- "init": lambda: handle_init(),
187
- "summary": lambda: handle_summary(args),
188
- "security": lambda: handle_security(args),
189
- "version": lambda: print(f"qgis-analyzer {__version__}"),
190
- }
191
-
192
- try:
193
- if args.command in dispatch:
194
- dispatch[args.command]()
195
- else:
196
- parser.print_help()
197
-
198
- except KeyboardInterrupt:
199
- logger.info("\n⏹️ Analysis interrupted.")
200
- sys.exit(1)
201
- except FileNotFoundError as e:
202
- logger.error(f"Error: File not found: {e}")
203
- sys.exit(1)
204
- except ValueError as e:
205
- # This handles path traversal or other validation errors
206
- logger.error(f"Error: {e}")
207
- sys.exit(1)
208
- except Exception as e:
209
- logger.critical(f"Critical Error: {e}", exc_info=True)
210
- sys.exit(1)
28
+ """Main entry point for the QGIS Plugin Analyzer CLI."""
29
+ app = CLIApp()
30
+ sys.exit(app.run())
211
31
 
212
32
 
213
33
  if __name__ == "__main__":
analyzer/commands.py CHANGED
@@ -5,6 +5,7 @@ interface definition (cli.py) from execution logic.
5
5
  """
6
6
 
7
7
  import argparse
8
+ import dataclasses
8
9
  import json
9
10
  import pathlib
10
11
  import sys
@@ -82,11 +83,9 @@ def handle_analyze(args: argparse.Namespace) -> None:
82
83
  """
83
84
  analyzer = ProjectAnalyzer(args.project_path, args.output, args.profile)
84
85
 
85
- # Override config based on CLI flag
86
- if hasattr(args, "report") and args.report:
87
- analyzer.config["generate_html"] = True
88
- else:
89
- analyzer.config["generate_html"] = False
86
+ # Override config based on CLI flag using dataclasses.replace since it's frozen
87
+ report_enabled = bool(hasattr(args, "report") and args.report)
88
+ analyzer.config = dataclasses.replace(analyzer.config, generate_html=report_enabled)
90
89
 
91
90
  success = analyzer.run()
92
91
 
@@ -147,9 +146,10 @@ def handle_security(args: argparse.Namespace) -> None:
147
146
  # Run analyzer with current profile
148
147
  analyzer = ProjectAnalyzer(str(project_path), args.output, args.profile)
149
148
 
150
- # We could potentially add a flag to 'deep' mode in the analyzer config
149
+ # We could potentially add high-level flags here
151
150
  if args.deep:
152
- analyzer.config["security_deep_scan"] = True
151
+ # Note: ProjectConfig currently doesn't have security_deep_scan,
152
+ # but if it did, we would use dataclasses.replace here too.
153
153
  print("🔍 Deep scan enabled (Entropy analysis and full secret detection)")
154
154
 
155
155
  success = analyzer.run()