33import shutil
44from abc import ABC , abstractmethod
55from pathlib import Path
6- from typing import Any , Literal
6+ from typing import Any , Literal , Self
77
88import requests
99import typer
@@ -21,6 +21,7 @@ class SASTRequirement(ABC):
2121 def __init__ (
2222 self ,
2323 name : str ,
24+ depends_on : list [Self ] | None = None ,
2425 instruction : str | None = None ,
2526 url : str | None = None ,
2627 doc : bool = False ,
@@ -29,12 +30,14 @@ def __init__(
2930
3031 Args:
3132 name: The name of the requirement.
33+ depends_on: A list of other requirements that must be fulfilled first.
3234 instruction: A short instruction on how to download the requirement.
3335 url: A URL for more detailed instructions.
34- doc: A flag indicating if the instruction is available in the documentaton .
36+ doc: A flag indicating if the instruction is available in the documentation .
3537
3638 """
3739 self .name = name
40+ self .depends_on = depends_on
3841 self .instruction = instruction
3942 self .url = url
4043 self .doc = doc
@@ -44,6 +47,12 @@ def is_fulfilled(self, **kwargs: Any) -> bool:
4447 """Check if the requirement is met."""
4548 pass
4649
50+ def dependencies_fulfilled (self ) -> bool :
51+ """Check if all dependencies for this requirement are fulfilled."""
52+ if not self .depends_on :
53+ return True
54+ return all (dependency .is_fulfilled () for dependency in self .depends_on )
55+
4756 def __repr__ (self ) -> str :
4857 """Return a developer-friendly string representation of the requirement."""
4958 return f"{ self .__class__ .__name__ } ({ self .name } )"
@@ -55,6 +64,7 @@ class DownloadableRequirement(SASTRequirement):
5564 def __init__ (
5665 self ,
5766 name : str ,
67+ depends_on : list [SASTRequirement ] | None = None ,
5868 instruction : str | None = None ,
5969 url : str | None = None ,
6070 doc : bool = False ,
@@ -65,13 +75,16 @@ def __init__(
6575
6676 Args:
6777 name: The name of the requirement.
78+ depends_on: A list of other requirements that must be fulfilled first.
6879 instruction: A short instruction on how to download the requirement.
6980 url: A URL for more detailed instructions.
70- doc: A flag indicating if the instruction is available in the documentaton .
81+ doc: A flag indicating if the instruction is available in the documentation .
7182
7283 """
7384 instruction = f"cstools download { name } "
74- super ().__init__ (name , instruction , url , doc )
85+ super ().__init__ (
86+ name = name , depends_on = depends_on , instruction = instruction , url = url , doc = doc
87+ )
7588
7689 @abstractmethod
7790 def download (self , ** kwargs : Any ) -> None :
@@ -85,6 +98,7 @@ class Config(SASTRequirement):
8598 def __init__ (
8699 self ,
87100 name : str ,
101+ depends_on : list [SASTRequirement ] | None = None ,
88102 instruction : str | None = None ,
89103 url : str | None = None ,
90104 doc : bool = False ,
@@ -93,12 +107,15 @@ def __init__(
93107
94108 Args:
95109 name: The name of the requirement.
110+ depends_on: A list of other requirements that must be fulfilled first.
96111 instruction: A short instruction on how to download the requirement.
97112 url: A URL for more detailed instructions.
98- doc: A flag indicating if the instruction is available in the documentaton .
113+ doc: A flag indicating if the instruction is available in the documentation .
99114
100115 """
101- super ().__init__ (name , instruction , url , doc )
116+ super ().__init__ (
117+ name = name , depends_on = depends_on , instruction = instruction , url = url , doc = doc
118+ )
102119
103120 def is_fulfilled (self , sast_name : str , ** kwargs : Any ) -> bool :
104121 """Check if the configuration file exists for the given SAST tool."""
@@ -111,6 +128,7 @@ class Binary(SASTRequirement):
111128 def __init__ (
112129 self ,
113130 name : str ,
131+ depends_on : list [SASTRequirement ] | None = None ,
114132 instruction : str | None = None ,
115133 url : str | None = None ,
116134 doc : bool = False ,
@@ -119,12 +137,15 @@ def __init__(
119137
120138 Args:
121139 name: The name of the requirement.
140+ depends_on: A list of other requirements that must be fulfilled first.
122141 instruction: A short instruction on how to download the requirement.
123142 url: A URL for more detailed instructions.
124- doc: A flag indicating if the instruction is available in the documentaton .
143+ doc: A flag indicating if the instruction is available in the documentation .
125144
126145 """
127- super ().__init__ (name , instruction , url , doc )
146+ super ().__init__ (
147+ name = name , depends_on = depends_on , instruction = instruction , url = url , doc = doc
148+ )
128149
129150 def is_fulfilled (self , ** kwargs : Any ) -> bool :
130151 """Check if the binary is available in the system's PATH."""
@@ -140,6 +161,7 @@ def __init__(
140161 repo_url : str ,
141162 license : str ,
142163 license_url : str ,
164+ depends_on : list [SASTRequirement ] | None = None ,
143165 instruction : str | None = None ,
144166 url : str | None = None ,
145167 doc : bool = False ,
@@ -151,12 +173,15 @@ def __init__(
151173 repo_url: The URL of the Git repository to clone.
152174 license: The license of the repository.
153175 license_url: A URL for the repository's license.
176+ depends_on: A list of other requirements that must be fulfilled first.
154177 instruction: A short instruction on how to download the requirement.
155178 url: A URL for more detailed instructions.
156- doc: A flag indicating if the instruction is available in the documentaton .
179+ doc: A flag indicating if the instruction is available in the documentation .
157180
158181 """
159- super ().__init__ (name , instruction , url , doc )
182+ super ().__init__ (
183+ name = name , depends_on = depends_on , instruction = instruction , url = url , doc = doc
184+ )
160185 self .repo_url = repo_url
161186 self .license = license
162187 self .license_url = license_url
@@ -206,6 +231,7 @@ def __init__(
206231 file_url : str ,
207232 license : str ,
208233 license_url : str ,
234+ depends_on : list [SASTRequirement ] | None = None ,
209235 instruction : str | None = None ,
210236 url : str | None = None ,
211237 doc : bool = False ,
@@ -218,12 +244,15 @@ def __init__(
218244 file_url: The URL to download the file from.
219245 license: The license of the file.
220246 license_url: A URL for the file's license.
247+ depends_on: A list of other requirements that must be fulfilled first.
221248 instruction: A short instruction on how to download the requirement.
222249 url: A URL for more detailed instructions.
223- doc: A flag indicating if the instruction is available in the documentaton .
250+ doc: A flag indicating if the instruction is available in the documentation .
224251
225252 """
226- super ().__init__ (name , instruction , url , doc )
253+ super ().__init__ (
254+ name = name , depends_on = depends_on , instruction = instruction , url = url , doc = doc
255+ )
227256 self .parent_dir = parent_dir
228257 self .file_url = file_url
229258 self .license = license
0 commit comments