troubadix 25.3.3__py3-none-any.whl → 25.3.5__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 +1 -1
- troubadix/plugins/__init__.py +11 -23
- troubadix/standalone_plugins/dependency_graph/checks.py +20 -23
- troubadix/standalone_plugins/dependency_graph/cli.py +7 -14
- troubadix/standalone_plugins/dependency_graph/dependency_graph.py +13 -37
- troubadix/standalone_plugins/dependency_graph/models.py +15 -9
- {troubadix-25.3.3.dist-info → troubadix-25.3.5.dist-info}/METADATA +1 -1
- {troubadix-25.3.3.dist-info → troubadix-25.3.5.dist-info}/RECORD +11 -11
- {troubadix-25.3.3.dist-info → troubadix-25.3.5.dist-info}/WHEEL +1 -1
- {troubadix-25.3.3.dist-info → troubadix-25.3.5.dist-info}/LICENSE +0 -0
- {troubadix-25.3.3.dist-info → troubadix-25.3.5.dist-info}/entry_points.txt +0 -0
troubadix/__version__.py
CHANGED
troubadix/plugins/__init__.py
CHANGED
|
@@ -178,9 +178,7 @@ class StandardPlugins(Plugins):
|
|
|
178
178
|
files_plugins = _FILES_PLUGINS
|
|
179
179
|
|
|
180
180
|
if excluded_plugins:
|
|
181
|
-
self._check_unknown_plugins(
|
|
182
|
-
_FILE_PLUGINS + _FILES_PLUGINS, excluded_plugins
|
|
183
|
-
)
|
|
181
|
+
self._check_unknown_plugins(excluded_plugins)
|
|
184
182
|
|
|
185
183
|
file_plugins = self._exclude_plugins(excluded_plugins, file_plugins)
|
|
186
184
|
files_plugins = self._exclude_plugins(
|
|
@@ -188,9 +186,7 @@ class StandardPlugins(Plugins):
|
|
|
188
186
|
)
|
|
189
187
|
|
|
190
188
|
if included_plugins:
|
|
191
|
-
self._check_unknown_plugins(
|
|
192
|
-
_FILE_PLUGINS + _FILES_PLUGINS, included_plugins
|
|
193
|
-
)
|
|
189
|
+
self._check_unknown_plugins(included_plugins)
|
|
194
190
|
|
|
195
191
|
file_plugins = self._include_plugins(included_plugins, file_plugins)
|
|
196
192
|
files_plugins = self._include_plugins(
|
|
@@ -220,33 +216,25 @@ class StandardPlugins(Plugins):
|
|
|
220
216
|
]
|
|
221
217
|
|
|
222
218
|
@staticmethod
|
|
223
|
-
def _check_unknown_plugins(
|
|
224
|
-
if len(found_plugins) == len(selected_plugins):
|
|
225
|
-
return
|
|
226
|
-
|
|
219
|
+
def _check_unknown_plugins(selected_plugins: list[str]):
|
|
227
220
|
all_plugin_names = {
|
|
228
221
|
name
|
|
229
222
|
for plugin in _FILE_PLUGINS + _FILES_PLUGINS
|
|
230
223
|
for name in (plugin.name, plugin.__name__)
|
|
231
224
|
}
|
|
232
|
-
found_plugin_names = {
|
|
233
|
-
name
|
|
234
|
-
for plugin in found_plugins
|
|
235
|
-
for name in (plugin.name, plugin.__name__)
|
|
236
|
-
}
|
|
237
225
|
|
|
238
|
-
unknown_plugins = set(selected_plugins).difference(
|
|
226
|
+
unknown_plugins = set(selected_plugins).difference(all_plugin_names)
|
|
239
227
|
|
|
240
228
|
if not unknown_plugins:
|
|
241
229
|
return
|
|
242
230
|
|
|
243
|
-
|
|
244
|
-
for plugin in sorted(unknown_plugins):
|
|
245
|
-
message = f"'{plugin}'"
|
|
231
|
+
def build_message(plugin: str):
|
|
246
232
|
match = difflib.get_close_matches(plugin, all_plugin_names, n=1)
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
233
|
+
return (
|
|
234
|
+
f"'{plugin}' (Did you mean '{match[0]}'?)"
|
|
235
|
+
if match
|
|
236
|
+
else f"'{plugin}'"
|
|
237
|
+
)
|
|
251
238
|
|
|
239
|
+
messages = [build_message(plugin) for plugin in sorted(unknown_plugins)]
|
|
252
240
|
raise ValueError(f"Unknown plugins: {', '.join(messages)}")
|
|
@@ -17,12 +17,10 @@ def check_duplicates(scripts: list[Script]) -> Result:
|
|
|
17
17
|
for script in scripts:
|
|
18
18
|
counter = Counter(dep.name for dep in script.dependencies)
|
|
19
19
|
duplicates = [dep for dep, count in counter.items() if count > 1]
|
|
20
|
-
|
|
21
20
|
if duplicates:
|
|
22
|
-
|
|
23
|
-
warnings.append(msg)
|
|
21
|
+
warnings.append(f"in {script.name}: {', '.join(duplicates)}")
|
|
24
22
|
|
|
25
|
-
return Result(name="
|
|
23
|
+
return Result(name="duplicate dependency", warnings=warnings)
|
|
26
24
|
|
|
27
25
|
|
|
28
26
|
def check_missing_dependencies(
|
|
@@ -34,20 +32,22 @@ def check_missing_dependencies(
|
|
|
34
32
|
logs the scripts dependending on the missing script
|
|
35
33
|
"""
|
|
36
34
|
errors = []
|
|
37
|
-
|
|
35
|
+
dependency_names = {
|
|
38
36
|
dep.name for script in scripts for dep in script.dependencies
|
|
39
37
|
}
|
|
40
38
|
script_names = {script.name for script in scripts}
|
|
41
|
-
missing_dependencies =
|
|
39
|
+
missing_dependencies = dependency_names - script_names
|
|
42
40
|
|
|
43
41
|
for missing in missing_dependencies:
|
|
44
42
|
depending_scripts = graph.predecessors(missing)
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
43
|
+
errors.append(
|
|
44
|
+
f"{missing}:"
|
|
45
|
+
+ "".join(
|
|
46
|
+
f"\n - used by: {script}" for script in depending_scripts
|
|
47
|
+
)
|
|
48
|
+
)
|
|
49
49
|
|
|
50
|
-
return Result(name="
|
|
50
|
+
return Result(name="missing dependency", errors=errors)
|
|
51
51
|
|
|
52
52
|
|
|
53
53
|
def check_cycles(graph) -> Result:
|
|
@@ -59,8 +59,8 @@ def check_cycles(graph) -> Result:
|
|
|
59
59
|
|
|
60
60
|
cycles = nx.simple_cycles(graph)
|
|
61
61
|
|
|
62
|
-
errors = [
|
|
63
|
-
return Result(name="
|
|
62
|
+
errors = [str(cycle) for cycle in cycles]
|
|
63
|
+
return Result(name="cyclic dependency", errors=errors)
|
|
64
64
|
|
|
65
65
|
|
|
66
66
|
def cross_feed_dependencies(
|
|
@@ -86,22 +86,19 @@ def check_cross_feed_dependencies(graph) -> Result:
|
|
|
86
86
|
and if they are correctly contained within a is_enterprise_feed check.
|
|
87
87
|
"""
|
|
88
88
|
gated_cfd = cross_feed_dependencies(graph, is_enterprise_checked=True)
|
|
89
|
-
|
|
90
|
-
f"
|
|
91
|
-
f"depends on {dependency}(enterprise feed)"
|
|
89
|
+
infos = [
|
|
90
|
+
f"{dependent}(community feed) depends on {dependency}(enterprise feed)"
|
|
92
91
|
for dependent, dependency in gated_cfd
|
|
93
92
|
]
|
|
94
93
|
|
|
95
94
|
ungated_cfd = cross_feed_dependencies(graph, is_enterprise_checked=False)
|
|
96
95
|
errors = [
|
|
97
|
-
f"
|
|
98
|
-
f"depends on {dependency}(enterprise feed)
|
|
96
|
+
f"incorrect feed check in {dependent}(community feed) "
|
|
97
|
+
f"which depends on {dependency}(enterprise feed)"
|
|
99
98
|
for dependent, dependency in ungated_cfd
|
|
100
99
|
]
|
|
101
100
|
|
|
102
|
-
return Result(
|
|
103
|
-
name="check_cross_feed_dependencies", warnings=warnings, errors=errors
|
|
104
|
-
)
|
|
101
|
+
return Result(name="cross-feed dependency", infos=infos, errors=errors)
|
|
105
102
|
|
|
106
103
|
|
|
107
104
|
def check_category_order(graph) -> Result:
|
|
@@ -116,7 +113,7 @@ def check_category_order(graph) -> Result:
|
|
|
116
113
|
f"{dependent} depends on {dependency} which has a lower category order"
|
|
117
114
|
for dependent, dependency in problematic_edges
|
|
118
115
|
]
|
|
119
|
-
return Result(name="
|
|
116
|
+
return Result(name="category order", errors=errors)
|
|
120
117
|
|
|
121
118
|
|
|
122
119
|
def check_deprecated_dependencies(graph) -> Result:
|
|
@@ -125,4 +122,4 @@ def check_deprecated_dependencies(graph) -> Result:
|
|
|
125
122
|
for dependent, dependency in graph.edges()
|
|
126
123
|
if graph.nodes[dependency].get("deprecated", False)
|
|
127
124
|
]
|
|
128
|
-
return Result(name="
|
|
125
|
+
return Result(name="deprecated dependency", errors=errors)
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
|
|
5
5
|
import os
|
|
6
|
-
from argparse import ArgumentParser,
|
|
6
|
+
from argparse import ArgumentParser, Namespace
|
|
7
7
|
from pathlib import Path
|
|
8
8
|
|
|
9
9
|
from troubadix.argparser import directory_type_existing
|
|
@@ -11,13 +11,6 @@ from troubadix.argparser import directory_type_existing
|
|
|
11
11
|
from .models import Feed
|
|
12
12
|
|
|
13
13
|
|
|
14
|
-
def feed_type(value: str) -> Feed:
|
|
15
|
-
try:
|
|
16
|
-
return Feed[value.upper()]
|
|
17
|
-
except KeyError:
|
|
18
|
-
raise ArgumentTypeError(f"Invalid Feed value: '{value}'")
|
|
19
|
-
|
|
20
|
-
|
|
21
14
|
def parse_args() -> Namespace:
|
|
22
15
|
parser = ArgumentParser(
|
|
23
16
|
description="Tool for analysing the dependencies in the NASL repository.",
|
|
@@ -31,18 +24,18 @@ def parse_args() -> Namespace:
|
|
|
31
24
|
parser.add_argument(
|
|
32
25
|
"-f",
|
|
33
26
|
"--feed",
|
|
34
|
-
type=
|
|
27
|
+
type=Feed,
|
|
35
28
|
choices=Feed,
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
help="feed",
|
|
29
|
+
default=Feed.COMMON,
|
|
30
|
+
help="Feed selection",
|
|
39
31
|
)
|
|
40
32
|
parser.add_argument(
|
|
41
33
|
"--log",
|
|
34
|
+
type=str.upper,
|
|
42
35
|
default="WARNING",
|
|
43
|
-
|
|
36
|
+
choices=["INFO", "WARNING", "ERROR"],
|
|
37
|
+
help="Set the logging level (default: WARNING)",
|
|
44
38
|
)
|
|
45
|
-
parser.add_argument("-v", "--verbose", action="count", default=0)
|
|
46
39
|
|
|
47
40
|
args = parser.parse_args()
|
|
48
41
|
|
|
@@ -5,7 +5,6 @@
|
|
|
5
5
|
import logging
|
|
6
6
|
import re
|
|
7
7
|
import sys
|
|
8
|
-
from functools import reduce
|
|
9
8
|
from pathlib import Path
|
|
10
9
|
|
|
11
10
|
import networkx as nx
|
|
@@ -47,46 +46,23 @@ ENTERPRISE_FEED_CHECK_PATTERN = re.compile(
|
|
|
47
46
|
|
|
48
47
|
|
|
49
48
|
class Reporter:
|
|
50
|
-
def __init__(self
|
|
51
|
-
self.
|
|
49
|
+
def __init__(self) -> None:
|
|
50
|
+
self.logger = logging.getLogger(__name__)
|
|
52
51
|
|
|
53
52
|
def report(self, results: list[Result]):
|
|
54
53
|
for result in results:
|
|
55
|
-
|
|
56
|
-
self.
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
if self.verbosity >= 2:
|
|
62
|
-
self.print_divider("=")
|
|
63
|
-
|
|
64
|
-
def print_divider(self, char="-", length=40):
|
|
65
|
-
print(char * length)
|
|
66
|
-
|
|
67
|
-
def print_statistic(self, result: Result):
|
|
68
|
-
print(
|
|
69
|
-
f"{result.name} - warnings: {len(result.warnings)}, errors: {len(result.errors)}"
|
|
70
|
-
)
|
|
71
|
-
|
|
72
|
-
def print_warnings(self, result: Result):
|
|
73
|
-
for warning in result.warnings:
|
|
74
|
-
print(f"warning: {warning}")
|
|
54
|
+
for error in result.errors:
|
|
55
|
+
self.logger.error(f"{result.name}: {error}")
|
|
56
|
+
for warning in result.warnings:
|
|
57
|
+
self.logger.warning(f"{result.name}: {warning}")
|
|
58
|
+
for info in result.infos:
|
|
59
|
+
self.logger.info(f"{result.name}: {info}")
|
|
75
60
|
|
|
76
|
-
def print_errors(self, result: Result):
|
|
77
|
-
for error in result.errors:
|
|
78
|
-
print(f"error: {error}")
|
|
79
61
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
feed
|
|
83
|
-
|
|
84
|
-
if feed & Feed.COMMON:
|
|
85
|
-
scripts.extend(get_scripts(root / "common"))
|
|
86
|
-
if feed & Feed.FEED_21_04:
|
|
87
|
-
scripts.extend(get_scripts(root / "21.04"))
|
|
88
|
-
if feed & Feed.FEED_22_04:
|
|
89
|
-
scripts.extend(get_scripts(root / "22.04"))
|
|
62
|
+
def get_feed(root: Path, feed: Feed) -> list[Script]:
|
|
63
|
+
scripts = get_scripts(root / "common") # Always include common
|
|
64
|
+
if feed != Feed.COMMON: # Add version-specific scripts if not just common
|
|
65
|
+
scripts.extend(get_scripts(root / feed.value))
|
|
90
66
|
|
|
91
67
|
return scripts
|
|
92
68
|
|
|
@@ -197,7 +173,7 @@ def main():
|
|
|
197
173
|
check_category_order(graph),
|
|
198
174
|
check_deprecated_dependencies(graph),
|
|
199
175
|
]
|
|
200
|
-
reporter = Reporter(
|
|
176
|
+
reporter = Reporter()
|
|
201
177
|
reporter.report(results)
|
|
202
178
|
|
|
203
179
|
if any(result.errors for result in results):
|
|
@@ -2,18 +2,19 @@
|
|
|
2
2
|
# SPDX-FileCopyrightText: 2025 Greenbone AG
|
|
3
3
|
|
|
4
4
|
from dataclasses import dataclass, field
|
|
5
|
-
from enum import
|
|
5
|
+
from enum import Enum
|
|
6
6
|
|
|
7
7
|
|
|
8
|
-
class Feed(
|
|
9
|
-
COMMON =
|
|
10
|
-
FEED_21_04 =
|
|
11
|
-
FEED_22_04 =
|
|
12
|
-
FULL = COMMON | FEED_21_04 | FEED_22_04
|
|
8
|
+
class Feed(str, Enum):
|
|
9
|
+
COMMON = "common"
|
|
10
|
+
FEED_21_04 = "21.04"
|
|
11
|
+
FEED_22_04 = "22.04"
|
|
13
12
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
13
|
+
|
|
14
|
+
class OutputLevel(Enum):
|
|
15
|
+
ERROR = 1
|
|
16
|
+
WARNING = 2
|
|
17
|
+
INFO = 3
|
|
17
18
|
|
|
18
19
|
|
|
19
20
|
@dataclass
|
|
@@ -35,6 +36,11 @@ class Script:
|
|
|
35
36
|
|
|
36
37
|
@dataclass
|
|
37
38
|
class Result:
|
|
39
|
+
"""Holds the results of a single check.
|
|
40
|
+
A check can report a combination of errors, warnings and infos
|
|
41
|
+
"""
|
|
42
|
+
|
|
38
43
|
name: str
|
|
39
44
|
warnings: list[str] = field(default_factory=list)
|
|
40
45
|
errors: list[str] = field(default_factory=list)
|
|
46
|
+
infos: list[str] = field(default_factory=list)
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
troubadix/__init__.py,sha256=K7sIXXDrC7YRb7BvIpdQ6ZfG_QkT0qUH_wAlHROVRfM,716
|
|
2
|
-
troubadix/__version__.py,sha256=
|
|
2
|
+
troubadix/__version__.py,sha256=7WX-neef-Lza94lX2gc3qmODm6ncbJ_M8Dmn9cEJfgg,103
|
|
3
3
|
troubadix/argparser.py,sha256=-H07Jhqh68_M4Mbjq9qJjTr3MShy_N2pxl2qHA6cfRU,7481
|
|
4
4
|
troubadix/codespell/codespell.additions,sha256=NAYnQF79kdk4YhU_h8fpjAVVkqBm778aPHPPP7FEkZY,504
|
|
5
5
|
troubadix/codespell/codespell.exclude,sha256=RS0PH7Px2NRg40UpreuXfnInaC4veaeeDxP1FNac4ms,147431
|
|
@@ -9,7 +9,7 @@ troubadix/helper/helper.py,sha256=GXapYLii2rLKwkX2ok31YoAdUSizBnyPjWz-aPP6HM8,31
|
|
|
9
9
|
troubadix/helper/linguistic_exception_handler.py,sha256=Bq7ULjDdWTKUpFNTUX6XMPdD4s4v8eIjZPyqBe8VLws,6811
|
|
10
10
|
troubadix/helper/patterns.py,sha256=_ifRnwHsPee9B0yRYSCsyFms4StWVWJq7I9YnQwToa8,9174
|
|
11
11
|
troubadix/plugin.py,sha256=3fQPj3Qe_hgwHerlYE4hbdzYMzRU557NxJ-UwtE9mOI,3525
|
|
12
|
-
troubadix/plugins/__init__.py,sha256=
|
|
12
|
+
troubadix/plugins/__init__.py,sha256=v328Yxgd8dU8g69Jpe4li-HM0iaqoT9_bOxfA7hP8jU,8445
|
|
13
13
|
troubadix/plugins/badwords.py,sha256=k1A1d2pdXzie87FGGXrykP2BgdZbY5QtmQItupHtNyw,4701
|
|
14
14
|
troubadix/plugins/copyright_text.py,sha256=jYsLWmTbT_A78XQQxQFK-5kMMHkh3xdvlh7mEF2dZGU,3583
|
|
15
15
|
troubadix/plugins/copyright_year.py,sha256=XzM9MHVzOXwNLwHpfuaWj8PUOmswr56SBVOLBdvxjd4,5478
|
|
@@ -88,18 +88,18 @@ troubadix/standalone_plugins/changed_packages/marker/marker.py,sha256=7uZXR2Ds_8
|
|
|
88
88
|
troubadix/standalone_plugins/changed_packages/package.py,sha256=Pcr2tcwiPTzD3jB0iteqA7-TajL-dl5Onh1dvC_H9xk,2743
|
|
89
89
|
troubadix/standalone_plugins/common.py,sha256=PkScV-lisNY4WyrzwjV3dK1DF26hJv5JXTcREblJ0v0,1028
|
|
90
90
|
troubadix/standalone_plugins/dependency_graph/__init__.py,sha256=SQSaQXWmpq5-5ozpqMgvnvoYTK8oj64A5kie1m_5bWQ,88
|
|
91
|
-
troubadix/standalone_plugins/dependency_graph/checks.py,sha256=
|
|
92
|
-
troubadix/standalone_plugins/dependency_graph/cli.py,sha256=
|
|
93
|
-
troubadix/standalone_plugins/dependency_graph/dependency_graph.py,sha256=
|
|
94
|
-
troubadix/standalone_plugins/dependency_graph/models.py,sha256=
|
|
91
|
+
troubadix/standalone_plugins/dependency_graph/checks.py,sha256=O4KyiVKpKxrgdmADXiduKY794nZndyy7epilbbY7JLo,4074
|
|
92
|
+
troubadix/standalone_plugins/dependency_graph/cli.py,sha256=RIyGeSm83XJ88N7Ati6z417hXkMajzzAtqdxnOg-urI,1305
|
|
93
|
+
troubadix/standalone_plugins/dependency_graph/dependency_graph.py,sha256=G_Ilm_EENpVHTw8wItknbfytVPRuTnVN1OoZEYvlTaU,5613
|
|
94
|
+
troubadix/standalone_plugins/dependency_graph/models.py,sha256=7kLrjFRdyReTRTgxte6-3KCBve4evg91AcqkX4I8VJU,1002
|
|
95
95
|
troubadix/standalone_plugins/deprecate_vts.py,sha256=mLt2DV9Y1YAEuh6c4nFweZYIOprsBzO7115dihEn4lA,7602
|
|
96
96
|
troubadix/standalone_plugins/file_extensions.py,sha256=fqswrhCcQqygIszcnobS9hFQmSpv3gDkvlufoaTckBg,2355
|
|
97
97
|
troubadix/standalone_plugins/last_modification.py,sha256=ROzwVzzYilXJ0llVt4Lv0w8b9BJKoahl6YxPDiub614,4338
|
|
98
98
|
troubadix/standalone_plugins/no_solution.py,sha256=p_-az9Igl4GH6HnhLLYbYlWIiEP64OTQLpX-z3JAshs,8760
|
|
99
99
|
troubadix/standalone_plugins/version_updated.py,sha256=6YHF0OjL5NWszQdsSh7XzlSji1e6Uaqwu_Y6m3R0mvI,4203
|
|
100
100
|
troubadix/troubadix.py,sha256=5__Jz3bYSrya4aG6RCBWxqnsDepXfwXZ3v0bjCzEFi0,6039
|
|
101
|
-
troubadix-25.3.
|
|
102
|
-
troubadix-25.3.
|
|
103
|
-
troubadix-25.3.
|
|
104
|
-
troubadix-25.3.
|
|
105
|
-
troubadix-25.3.
|
|
101
|
+
troubadix-25.3.5.dist-info/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
|
|
102
|
+
troubadix-25.3.5.dist-info/METADATA,sha256=bs9tbGZf3ZCQ7DNhvHsiW_5T20XwH0d56zD4Y4DGKKs,4462
|
|
103
|
+
troubadix-25.3.5.dist-info/WHEEL,sha256=fGIA9gx4Qxk2KDKeNJCbOEwSrmLtjWCwzBz351GyrPQ,88
|
|
104
|
+
troubadix-25.3.5.dist-info/entry_points.txt,sha256=SnhEUe4W76P-ADmO9J355gRztTyHU_PTxRewKy3-e5o,832
|
|
105
|
+
troubadix-25.3.5.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|