troubadix 24.8.1__py3-none-any.whl → 24.8.2__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.
troubadix/__version__.py CHANGED
@@ -2,4 +2,4 @@
2
2
 
3
3
  # THIS IS AN AUTOGENERATED FILE. DO NOT TOUCH!
4
4
 
5
- __version__ = "24.8.1"
5
+ __version__ = "24.8.2"
troubadix/argparser.py CHANGED
@@ -19,9 +19,9 @@
19
19
 
20
20
  import sys
21
21
  from argparse import ArgumentParser, Namespace
22
+ from collections.abc import Sequence
22
23
  from multiprocessing import cpu_count
23
24
  from pathlib import Path
24
- from typing import Iterable
25
25
 
26
26
  from pontos.terminal import Terminal
27
27
 
@@ -56,7 +56,7 @@ def check_cpu_count(number: str) -> int:
56
56
 
57
57
  def parse_args(
58
58
  terminal: Terminal,
59
- args: Iterable[str] = None,
59
+ args: Sequence[str],
60
60
  ) -> Namespace:
61
61
  """Parsing args for troubadix
62
62
 
troubadix/plugin.py CHANGED
@@ -16,9 +16,10 @@
16
16
  # along with this program. If not, see <http://www.gnu.org/licenses/>.
17
17
 
18
18
  from abc import ABC, abstractmethod
19
+ from collections.abc import Iterable, Iterator
19
20
  from dataclasses import dataclass
20
21
  from pathlib import Path
21
- from typing import Iterable, Iterator, Optional
22
+ from typing import Optional
22
23
 
23
24
  from troubadix.helper import CURRENT_ENCODING
24
25
 
@@ -50,13 +51,13 @@ class FilePluginContext:
50
51
  self,
51
52
  *,
52
53
  root: Path,
53
- nasl_file: Path = None,
54
+ nasl_file: Path,
54
55
  ) -> None:
55
56
  self.root = root
56
57
  self.nasl_file = nasl_file
57
58
 
58
- self._file_content = None
59
- self._lines = None
59
+ self._file_content: str | None = None
60
+ self._lines: list[str] | None = None
60
61
 
61
62
  @property
62
63
  def file_content(self) -> str:
@@ -67,7 +68,7 @@ class FilePluginContext:
67
68
  return self._file_content
68
69
 
69
70
  @property
70
- def lines(self) -> Iterable[str]:
71
+ def lines(self) -> list[str]:
71
72
  if not self._lines:
72
73
  self._lines = self.file_content.splitlines()
73
74
  return self._lines
@@ -82,15 +83,14 @@ class FilesPluginContext:
82
83
  class Plugin(ABC):
83
84
  """A linter plugin"""
84
85
 
85
- name: str = None
86
- description: str = None
86
+ name: str
87
87
 
88
88
  @abstractmethod
89
89
  def run(self) -> Iterator[LinterResult]:
90
90
  pass
91
91
 
92
92
  def fix(self) -> Iterator[LinterResult]:
93
- return []
93
+ return iter([])
94
94
 
95
95
 
96
96
  class FilesPlugin(Plugin):
@@ -4,93 +4,149 @@
4
4
 
5
5
  import re
6
6
  from pathlib import Path
7
- from typing import Iterable, Iterator
7
+ from typing import Iterator
8
8
 
9
9
  from troubadix.helper import is_ignore_file
10
- from troubadix.plugin import LineContentPlugin, LinterError, LinterResult
11
-
12
- _IGNORE_FILES = (
13
- "sw_telnet_os_detection.nasl",
14
- "gb_hp_comware_platform_detect_snmp.nasl",
15
- "gb_hirschmann_telnet_detect.nasl",
10
+ from troubadix.helper.patterns import (
11
+ ScriptTag,
12
+ SpecialScriptTag,
13
+ get_script_tag_pattern,
14
+ get_special_script_tag_pattern,
15
+ )
16
+ from troubadix.plugin import (
17
+ FileContentPlugin,
18
+ LinterError,
19
+ LinterResult,
16
20
  )
17
21
 
18
- _FULL_IGNORE_FILES = (
19
- "test_version_func_inc.nasl",
20
- "policy_control_template.nasl",
21
- "template.nasl",
22
- "test_ipv6_packet_forgery.nasl",
22
+ _IGNORE_FILES = ()
23
+
24
+
25
+ SPDX_OR_COPYRIGHT_PATTERN = re.compile(
26
+ r"(SPDX-FileCopyrightText:|Copyright \(C\))\s*(?P<year>\d{4})"
23
27
  )
24
28
 
25
29
 
26
- class CheckCopyrightYear(LineContentPlugin):
30
+ def _generate_header_lines(file_content: str):
31
+ for line in file_content.splitlines():
32
+ if line.startswith("#"):
33
+ yield line
34
+ else:
35
+ break
36
+
37
+
38
+ class CheckCopyrightYear(FileContentPlugin):
27
39
  """This steps checks if a VT contains a Copyright statement containing a
28
- year not matching the year defined in the creation_date statement like
29
- script_tag(name:"creation_date", value:"2017-
40
+ year not matching the year defined in the creation_date statement.
41
+
42
+ pre2008 script copyright are allowed to predate the creation_year
43
+
44
+ For scripts that contain multiple copyrights with different dates,
45
+ like gather-package-list.nasl, it is important that the newer one,
46
+ which is only valid as of a certain year, has information about
47
+ what it covers in the place where the year would normally be.
48
+ Then that line will be automatically ignored
49
+ without having to add it to the ignore list due to not matching the regex.
50
+ Example:
51
+ if creation year = 2008
52
+ ok:
53
+ # SPDX-FileCopyrightText: 2008 Tim Brown
54
+ # SPDX-FileCopyrightText: New detection methods / pattern / code since 2009 Greenbone AG
55
+ not ok / needs ignore entry:
56
+ # New NASL / detection code since 2018 Copyright (C) 2018 Greenbone AG
57
+
30
58
  """
31
59
 
32
60
  name = "check_copyright_year"
33
61
 
34
- def check_lines(
35
- self,
36
- nasl_file: Path,
37
- lines: Iterable[str],
62
+ def check_content(
63
+ self, nasl_file: Path, file_content: str
38
64
  ) -> Iterator[LinterResult]:
39
65
  if nasl_file.suffix == ".inc" or is_ignore_file(
40
- nasl_file, _FULL_IGNORE_FILES
66
+ nasl_file, _IGNORE_FILES
41
67
  ):
42
68
  return
69
+ # extract creation year from script tag
70
+ creation_date_pattern = get_script_tag_pattern(ScriptTag.CREATION_DATE)
71
+ creation_date_match = creation_date_pattern.search(file_content)
72
+ if not creation_date_match:
73
+ yield LinterError(
74
+ "Missing creation_date statement in VT",
75
+ file=nasl_file,
76
+ plugin=self.name,
77
+ )
78
+ return
79
+ creation_year = int(creation_date_match.group("value")[:4])
43
80
 
44
- creation_date = ""
45
- creation_year = ""
46
- copyrights = []
47
-
48
- for i, line in enumerate(lines, 1):
49
- if "creation_date" in line:
50
- expre = re.search(r'value\s*:\s*"(.*)"', line)
51
- if expre is not None and expre.group(1) is not None:
52
- creation_date = expre.group(1)
53
- expre = re.search(r"^([0-9]+)-", creation_date)
54
- if expre is not None and expre.group(1) is not None:
55
- creation_year = expre.group(1)
56
-
57
- copyright_match = re.search(
58
- r"((# |script_copyright.+)[Cc]opyright \([Cc]\)|"
59
- r"# SPDX-FileCopyrightText:) ([0-9]+)",
60
- line,
81
+ # extract year in value of script_copyright tag
82
+ script_copyright_pattern = get_special_script_tag_pattern(
83
+ SpecialScriptTag.COPYRIGHT
84
+ )
85
+ script_copyright_match = script_copyright_pattern.search(file_content)
86
+ if not script_copyright_match:
87
+ yield LinterError(
88
+ "Missing copyright tag in VT",
89
+ file=nasl_file,
90
+ plugin=self.name,
61
91
  )
62
- if (
63
- copyright_match is not None
64
- and copyright_match.group(3) is not None
65
- and not is_ignore_file(nasl_file, _IGNORE_FILES)
66
- ):
67
- copyrights.append((i, line, copyright_match.group(3)))
68
-
69
- if not creation_year:
92
+ return
93
+ copyright_tag_value = script_copyright_match.group("value")
94
+ copyright_tag_match = SPDX_OR_COPYRIGHT_PATTERN.search(
95
+ copyright_tag_value
96
+ )
97
+ if not copyright_tag_match:
70
98
  yield LinterError(
71
- "Missing creation_date statement in VT",
99
+ "Unable to extract year from script_copyright tag in VT",
72
100
  file=nasl_file,
73
101
  plugin=self.name,
74
102
  )
103
+ return
104
+ copyright_tag_year = int(copyright_tag_match.group("year"))
105
+
106
+ # list comprehension to collect copy right matches from header
107
+ header_lines = _generate_header_lines(file_content)
108
+ header_copyright_years = [
109
+ int(match.group("year"))
110
+ for line in header_lines
111
+ if (match := SPDX_OR_COPYRIGHT_PATTERN.search(line))
112
+ ]
75
113
 
76
- # key is the line where the copyright is found, value the year found
77
- # within that line
78
- for nr, line, copyright_year in copyrights:
79
- if copyright_year != creation_year:
114
+ if not header_copyright_years:
115
+ yield LinterError(
116
+ "VT header is missing a copyright text",
117
+ file=nasl_file,
118
+ plugin=self.name,
119
+ )
120
+
121
+ # check if the copyrights years match the creation year
122
+ # pre2008 VTs are allowed to have a copyright that predates the year of creation.
123
+ if copyright_tag_year != creation_year:
124
+ if "pre2008" in str(nasl_file):
125
+ if copyright_tag_year > creation_year:
126
+ yield LinterError(
127
+ "a pre2008 vt has a copyright tag year newer than the creation_year",
128
+ file=nasl_file,
129
+ plugin=self.name,
130
+ )
131
+ else:
132
+ yield LinterError(
133
+ "script_copyright tag does not match the creation year",
134
+ file=nasl_file,
135
+ plugin=self.name,
136
+ )
137
+ for copyright_year in header_copyright_years:
138
+ if creation_year != copyright_year:
80
139
  if "pre2008" in str(nasl_file):
81
140
  if copyright_year > creation_year:
82
141
  yield LinterError(
83
- "VT contains a Copyright year not matching "
84
- f"the creation year {creation_year} at line {nr}",
142
+ "a pre2008 vt has a copyright value in the fileheader"
143
+ " newer than the creation_year",
85
144
  file=nasl_file,
86
145
  plugin=self.name,
87
- line=nr,
88
146
  )
89
147
  else:
90
148
  yield LinterError(
91
- "VT contains a Copyright year not matching "
92
- f"the creation year {creation_year} at line {nr}",
149
+ "a copyright in the fileheader does not match the creation year",
93
150
  file=nasl_file,
94
151
  plugin=self.name,
95
- line=nr,
96
152
  )
troubadix/reporter.py CHANGED
@@ -15,8 +15,8 @@
15
15
  # You should have received a copy of the GNU General Public License
16
16
  # along with this program. If not, see <http://www.gnu.org/licenses/>.
17
17
 
18
+ from collections.abc import Iterable
18
19
  from pathlib import Path
19
- from typing import Iterable, List
20
20
 
21
21
  from pontos.terminal import Terminal
22
22
 
@@ -33,8 +33,8 @@ class Reporter:
33
33
  root: Path,
34
34
  *,
35
35
  fix: bool = False,
36
- log_file: Path = None,
37
- log_file_statistic: Path = None,
36
+ log_file: Path | None = None,
37
+ log_file_statistic: Path | None = None,
38
38
  statistic: bool = True,
39
39
  verbose: int = 0,
40
40
  ignore_warnings: bool = False,
@@ -78,7 +78,7 @@ class Reporter:
78
78
  self._log_append(f"\t\t{message}".replace("\n", "\n\t\t"))
79
79
 
80
80
  def _process_plugin_results(
81
- self, plugin_name: str, plugin_results: List[LinterResult]
81
+ self, plugin_name: str, plugin_results: Iterable[LinterResult]
82
82
  ):
83
83
  """Process the results of a plugin: Print/Log results if
84
84
  verbosity/logging fits and count the results"""
troubadix/results.py CHANGED
@@ -16,17 +16,15 @@
16
16
  # along with this program. If not, see <http://www.gnu.org/licenses/>.
17
17
 
18
18
  from collections import defaultdict
19
+ from collections.abc import Iterator
19
20
  from pathlib import Path
20
- from typing import Dict, Iterable, Iterator
21
21
 
22
22
  from troubadix.plugin import LinterResult, LinterWarning
23
23
 
24
24
 
25
25
  class Results:
26
26
  def __init__(self, ignore_warnings: bool = False) -> None:
27
- self.plugin_results: Dict[str, Iterable[LinterResult]] = defaultdict(
28
- list
29
- )
27
+ self.plugin_results: dict[str, list[LinterResult]] = defaultdict(list)
30
28
  self.has_plugin_results = False
31
29
  self._ignore_warnings = ignore_warnings
32
30
 
troubadix/runner.py CHANGED
@@ -17,9 +17,9 @@
17
17
 
18
18
  import datetime
19
19
  import signal
20
+ from collections.abc import Iterable
20
21
  from multiprocessing import Pool
21
22
  from pathlib import Path
22
- from typing import Iterable
23
23
 
24
24
  from troubadix.helper.patterns import (
25
25
  init_script_tag_patterns,
@@ -49,11 +49,11 @@ class Runner:
49
49
  reporter: Reporter,
50
50
  *,
51
51
  root: Path,
52
- excluded_plugins: Iterable[str] = None,
53
- included_plugins: Iterable[str] = None,
52
+ excluded_plugins: Iterable[str] | None = None,
53
+ included_plugins: Iterable[str] | None = None,
54
54
  fix: bool = False,
55
55
  ignore_warnings: bool = False,
56
- ) -> bool:
56
+ ) -> None:
57
57
  # plugins initialization
58
58
  self.plugins = StandardPlugins(excluded_plugins, included_plugins)
59
59
 
troubadix/troubadix.py CHANGED
@@ -18,8 +18,8 @@
18
18
  """ Main module for troubadix """
19
19
 
20
20
  import sys
21
+ from collections.abc import Iterable
21
22
  from pathlib import Path
22
- from typing import Iterable, List, Tuple
23
23
 
24
24
  from pontos.terminal import Terminal
25
25
  from pontos.terminal.terminal import ConsoleTerminal
@@ -35,7 +35,7 @@ def generate_file_list(
35
35
  dirs: Iterable[Path],
36
36
  exclude_patterns: Iterable[str],
37
37
  include_patterns: Iterable[str],
38
- ) -> List[Path]:
38
+ ) -> list[Path]:
39
39
  """Generates a files list under respect of several given arguments
40
40
 
41
41
  Arguments:
@@ -48,7 +48,7 @@ def generate_file_list(
48
48
 
49
49
  Returns
50
50
  List of Path objects"""
51
- files: List[Path] = []
51
+ files: list[Path] = []
52
52
  for directory in dirs:
53
53
  for pattern in include_patterns:
54
54
  files.extend(directory.glob(pattern))
@@ -64,10 +64,10 @@ def generate_file_list(
64
64
 
65
65
  def generate_patterns(
66
66
  terminal: ConsoleTerminal,
67
- include_patterns: List[str],
68
- exclude_patterns: List[str],
67
+ include_patterns: list[str],
68
+ exclude_patterns: list[str],
69
69
  non_recursive: bool,
70
- ) -> Tuple[List[str], List[str]]:
70
+ ) -> tuple[list[str], list[str]]:
71
71
  """Generates the include and exclude patterns
72
72
 
73
73
  Arguments:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: troubadix
3
- Version: 24.8.1
3
+ Version: 24.8.2
4
4
  Summary: A linting and QA check tool for NASL files
5
5
  Home-page: https://github.com/greenbone/troubadix
6
6
  License: GPL-3.0-or-later
@@ -1,6 +1,6 @@
1
1
  troubadix/__init__.py,sha256=K7sIXXDrC7YRb7BvIpdQ6ZfG_QkT0qUH_wAlHROVRfM,716
2
- troubadix/__version__.py,sha256=ifB9RDBM7-2V2HRMId0VsqTT6_vzgQuniDkvyk44r5A,103
3
- troubadix/argparser.py,sha256=r9IkiYkd_8BqFGUEkhpawnW5DHo4hIciHd0dptToBjk,6999
2
+ troubadix/__version__.py,sha256=A-mzx324wDkyalOPGij0nXdX-gqSaA5FP9hqVUjLc9E,103
3
+ troubadix/argparser.py,sha256=YAo8cGJt0k2GMICXrDj3Z124GrM8oRwgNm2Bn3J_gYI,7001
4
4
  troubadix/codespell/codespell.additions,sha256=9hUrzjJF4Q8T5rVLx8CQa01oICvmsjzE6sCPjVRDOEU,418
5
5
  troubadix/codespell/codespell.exclude,sha256=qALEzLglEbPwcTRwGcobM_MTJzZyJekYRdJY3ws5yeM,138030
6
6
  troubadix/codespell/codespell.ignore,sha256=-naAh453UCGeT-oGWoJ5QNuUrDGP0aRd8WrOuU6oETI,1175
@@ -8,11 +8,11 @@ troubadix/helper/__init__.py,sha256=tp2fPLzwGEA_2eiJbvuePiY6rjYSFxx7VUsCV4fSwvw,
8
8
  troubadix/helper/helper.py,sha256=GXapYLii2rLKwkX2ok31YoAdUSizBnyPjWz-aPP6HM8,3105
9
9
  troubadix/helper/linguistic_exception_handler.py,sha256=Bq7ULjDdWTKUpFNTUX6XMPdD4s4v8eIjZPyqBe8VLws,6811
10
10
  troubadix/helper/patterns.py,sha256=_ifRnwHsPee9B0yRYSCsyFms4StWVWJq7I9YnQwToa8,9174
11
- troubadix/plugin.py,sha256=JVx4Vyop3pkN5xyNK6Vk6wGyd29BXZCa24GNRk2gen4,3508
11
+ troubadix/plugin.py,sha256=3fQPj3Qe_hgwHerlYE4hbdzYMzRU557NxJ-UwtE9mOI,3525
12
12
  troubadix/plugins/__init__.py,sha256=McIt4ZDPLmFxr0WMi8FmRoV-bDLXxSP-6JbrYKR1RHc,7413
13
13
  troubadix/plugins/badwords.py,sha256=C5Vuq6rzyeQkbEsg4t9ui9K05nQAh3Xy93sqV9K7aNw,4603
14
14
  troubadix/plugins/copyright_text.py,sha256=jYsLWmTbT_A78XQQxQFK-5kMMHkh3xdvlh7mEF2dZGU,3583
15
- troubadix/plugins/copyright_year.py,sha256=n6-1hKV58Aj9iPTsaUqVxeoFUVZT3Xgc-YLdqNkM2_g,3334
15
+ troubadix/plugins/copyright_year.py,sha256=XzM9MHVzOXwNLwHpfuaWj8PUOmswr56SBVOLBdvxjd4,5478
16
16
  troubadix/plugins/creation_date.py,sha256=61vF871P2qdB0TE8g__BwgHHbs4ffxVmUmM3YAiy9GE,3357
17
17
  troubadix/plugins/cve_format.py,sha256=Ue6b9RzuQZWOdBd6y5ruqdEq2zyRb2_FSUQScnjHOUQ,3400
18
18
  troubadix/plugins/cvss_format.py,sha256=GrZfZxkxSh9OVixmBBnHQ4NzF9nN2tCK1vepz_-U60g,2309
@@ -69,9 +69,9 @@ troubadix/plugins/variable_assigned_in_if.py,sha256=NNz8iuzyQ4rSM6My4WYC1s5TABQq
69
69
  troubadix/plugins/variable_redefinition_in_foreach.py,sha256=SfaA70TkpD9dsvNbhwJEA3eLAHWvj4YwksN-qeBMowg,2470
70
70
  troubadix/plugins/vt_file_permissions.py,sha256=-8rOUD0NpRwB0Ec5oQCcVpDVAaZqsUopqpGPB1To6fY,1521
71
71
  troubadix/plugins/vt_placement.py,sha256=m9AaswV2w6Qk_EaG_KuO82OUzIAyIBpXoTW0T4Ya76Y,2800
72
- troubadix/reporter.py,sha256=wY0dml545irS8hUnOGChUjiTlX0doi29w25wW-GQofs,9267
73
- troubadix/results.py,sha256=n1zcRaMvqT6vqar-W1nbAozBWUiD8-80kliddorlJRo,2632
74
- troubadix/runner.py,sha256=qDbwBfS1HsgclGHSJNqJ-C4EOPNnN5jKbW5M5o9jAjU,5172
72
+ troubadix/reporter.py,sha256=ljZReqAHY8I4C0ROB-A7bBB5xsksG_y7bEgPFzLn_A8,9288
73
+ troubadix/results.py,sha256=PAe3n0A99XXNYeP8gLliuDFt0V9J5a7oPun_bKU4LG4,2599
74
+ troubadix/runner.py,sha256=RHyZe7YMBzJpCGBVfBUg2BMkVi13CmI9u0DVG2z4518,5195
75
75
  troubadix/standalone_plugins/__init__.py,sha256=kUR5RAFc7HCeiqdlX36dZOHkUI5wI6V_43RpEcD8b-0,22
76
76
  troubadix/standalone_plugins/allowed_rev_diff.py,sha256=5Zc8xTZlkMOPVNRdxNkosFFtwaQ6J8RiJYzaYXEuN40,4145
77
77
  troubadix/standalone_plugins/changed_cves.py,sha256=nEWwDa33QXekvpwcmnGMrdPHrJISz9p9j6lX09teDlk,2921
@@ -91,9 +91,9 @@ troubadix/standalone_plugins/file_extensions.py,sha256=3lEf73573RaTWgWZgiw8FFICK
91
91
  troubadix/standalone_plugins/last_modification.py,sha256=oYzQq7xV3YzSvi6ZtuHuupXsJwBtO93tKfbwaIeqiJI,4616
92
92
  troubadix/standalone_plugins/no_solution.py,sha256=81r20kP8otRob2NTaCea-sgVRIM6ARvhddFdibsG6Ao,8877
93
93
  troubadix/standalone_plugins/version_updated.py,sha256=dIGj81rbluyNjINn9kA1yPY2hUo6fqbNa-kg0Zi9Clc,4263
94
- troubadix/troubadix.py,sha256=L3Iacrq2uQx8wrmsD4nCFjJDeRDMRWtgSgHLWdP8gJE,6045
95
- troubadix-24.8.1.dist-info/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
96
- troubadix-24.8.1.dist-info/METADATA,sha256=quph962qeQCDehETHRvuRzv3HoLbdzATp82_wRJ9_zg,3916
97
- troubadix-24.8.1.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
98
- troubadix-24.8.1.dist-info/entry_points.txt,sha256=LplOk4nzKrS4B8Jz0SPkQLPlIDesdraCO8Vp_eoycpc,737
99
- troubadix-24.8.1.dist-info/RECORD,,
94
+ troubadix/troubadix.py,sha256=foA7Loi67cCKieN3ea4s3QOfOWOkgwQVR1H-pNXtXn0,6041
95
+ troubadix-24.8.2.dist-info/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
96
+ troubadix-24.8.2.dist-info/METADATA,sha256=IKjBeLHS1kSuOgk0STxyW7PGoxPRxR_npN9CMNvM3LE,3916
97
+ troubadix-24.8.2.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
98
+ troubadix-24.8.2.dist-info/entry_points.txt,sha256=LplOk4nzKrS4B8Jz0SPkQLPlIDesdraCO8Vp_eoycpc,737
99
+ troubadix-24.8.2.dist-info/RECORD,,