|
13 | 13 | Reporting functions for codeaudit |
14 | 14 | """ |
15 | 15 |
|
16 | | -import datetime |
17 | | -import html |
18 | | -import os |
19 | 16 | import re |
20 | | -import sys |
21 | | -from importlib.resources import files |
| 17 | +import os |
22 | 18 | from pathlib import Path |
| 19 | +import sys |
23 | 20 |
|
24 | 21 | import pandas as pd |
| 22 | +import html |
| 23 | +import datetime |
25 | 24 |
|
26 | | -from codeaudit import __version__ |
27 | | -from codeaudit.altairplots import multi_bar_chart |
28 | | -from codeaudit.api_helpers import _collect_issue_lines |
29 | | -from codeaudit.checkmodules import ( |
30 | | - check_module_vulnerability, |
31 | | - get_all_modules, |
32 | | - get_imported_modules, |
33 | | - get_imported_modules_by_file, |
34 | | -) |
| 25 | +from codeaudit.security_checks import perform_validations, ast_security_checks |
35 | 26 | from codeaudit.filehelpfunctions import ( |
36 | | - collect_python_source_files, |
37 | 27 | get_filename_from_path, |
| 28 | + collect_python_source_files, |
| 29 | + read_in_source_file, |
38 | 30 | has_python_files, |
39 | 31 | is_ast_parsable, |
40 | | - read_in_source_file, |
41 | 32 | ) |
42 | | -from codeaudit.htmlhelpfunctions import dict_list_to_html_table, json_to_html |
43 | | -from codeaudit.privacy_lint import data_egress_scan, has_privacy_findings |
44 | | -from codeaudit.pypi_package_scan import get_package_source, get_pypi_download_info |
45 | | -from codeaudit.security_checks import ast_security_checks, perform_validations |
46 | | -from codeaudit.suppression import filter_sast_results |
| 33 | +from codeaudit.altairplots import multi_bar_chart |
47 | 34 | from codeaudit.totals import ( |
48 | 35 | get_statistics, |
49 | 36 | overview_count, |
50 | 37 | overview_per_file, |
51 | 38 | total_modules, |
52 | 39 | ) |
| 40 | +from codeaudit.checkmodules import ( |
| 41 | + get_imported_modules, |
| 42 | + check_module_vulnerability, |
| 43 | + get_all_modules, |
| 44 | + get_imported_modules_by_file, |
| 45 | +) |
| 46 | +from codeaudit.htmlhelpfunctions import json_to_html, dict_list_to_html_table |
| 47 | +from codeaudit import __version__ |
| 48 | +from codeaudit.pypi_package_scan import get_pypi_download_info, get_package_source |
| 49 | +from codeaudit.privacy_lint import data_egress_scan, has_privacy_findings |
| 50 | +from codeaudit.suppression import filter_sast_results |
| 51 | +from codeaudit.api_helpers import _collect_issue_lines |
| 52 | + |
| 53 | +from importlib.resources import files |
53 | 54 |
|
54 | 55 | PYTHON_CODE_AUDIT_TEXT = '<a href="https://github.com/nocomplexity/codeaudit" target="_blank"><b>Python Code Audit</b></a>' |
55 | 56 | DISCLAIMER_TEXT = ( |
@@ -427,35 +428,44 @@ def secrets_report(spy_output): |
427 | 428 | def pylint_reporting(result): |
428 | 429 | """ |
429 | 430 | Creates a pandas DataFrame of privacy findings with columns: |
430 | | - 'lineno' and 'code'. |
431 | | - HTML-escaped and newlines converted to <br> for safe display. |
| 431 | + 'line', 'found', and 'code'. |
| 432 | +
|
| 433 | + - Escapes HTML for safe rendering |
| 434 | + - Converts newlines to <br> |
| 435 | + - Wraps code in <pre><code> block |
| 436 | + - Optimized for performance (fewer lookups, reusable template) |
432 | 437 | """ |
433 | 438 | rows = [] |
| 439 | + append_row = rows.append # local reference (faster in loops) |
| 440 | + |
| 441 | + # Predefine template (faster than rebuilding strings each loop) |
| 442 | + template = '<pre><code class="language-python">{}</code></pre>' |
| 443 | + |
| 444 | + # Safely get dict |
| 445 | + file_checks = result.get("file_privacy_check") or {} |
| 446 | + |
| 447 | + for item in file_checks.values(): |
| 448 | + entries = item.get("privacy_check_result", []) |
| 449 | + for entry in entries: |
| 450 | + code = entry.get("code", "") |
| 451 | + lineno = entry.get("lineno") |
| 452 | + matched = entry.get("matched") |
| 453 | + |
| 454 | + # Escape HTML and replace newlines (done once per entry) |
| 455 | + escaped_code = html.escape(code).replace("\n", "<br>") |
| 456 | + |
| 457 | + # Format HTML block (faster than f-string in tight loops) |
| 458 | + code_html = template.format(escaped_code) |
| 459 | + |
| 460 | + append_row( |
| 461 | + { |
| 462 | + "line": lineno, |
| 463 | + "found": matched, |
| 464 | + "code": code_html, |
| 465 | + } |
| 466 | + ) |
434 | 467 |
|
435 | | - # Check that file_privacy_check exists and is not empty |
436 | | - if result.get("file_privacy_check"): |
437 | | - for item in result["file_privacy_check"].values(): |
438 | | - for entry in item.get("privacy_check_result", []): |
439 | | - # Escape HTML special characters |
440 | | - escaped_code = html.escape(entry["code"]) |
441 | | - # Convert newlines to <br> and wrap in <pre><code> |
442 | | - code_html = f'<pre><code class="language-python">{escaped_code.replace("\n", "<br>")}</code></pre>' |
443 | | - # Add a row to the list |
444 | | - rows.append( |
445 | | - { |
446 | | - "lineno": entry["lineno"], |
447 | | - "matched": entry["matched"], |
448 | | - "code": code_html, |
449 | | - } |
450 | | - ) |
451 | | - |
452 | | - # Convert to pandas DataFrame |
453 | | - df = pd.DataFrame(rows, columns=["lineno", "matched", "code"]) |
454 | | - df = df.rename( |
455 | | - columns={"lineno": "line", "matched": "found"} |
456 | | - ) # rename to UI frienly names |
457 | | - |
458 | | - return df |
| 468 | + return pd.DataFrame(rows, columns=["line", "found", "code"]) |
459 | 469 |
|
460 | 470 |
|
461 | 471 | def single_file_report(filename, scan_output): |
|
0 commit comments