2020_JENKINS_SH_RE = re .compile (r"sh\s*(?:\(['\"]|['\"])(.+?)['\"]\)?" , re .MULTILINE | re .DOTALL )
2121_JENKINS_SCRIPT_RE = re .compile (r"script\s*\{([^}]+)\}" , re .MULTILINE | re .DOTALL )
2222
23- _SCRIPT_CALL_RE = re .compile (
24- r"(?:bash|sh|python|python3|node|npm|yarn|pnpm|make|go|cargo|dotnet|mvn|gradle|pytest|ruff|mypy|black|isort|flake8)\s+([^\s;&|]+)"
23+ _SCRIPT_CALL_TOOLS = frozenset (
24+ {
25+ "bash" ,
26+ "sh" ,
27+ "python" ,
28+ "python3" ,
29+ "node" ,
30+ "npm" ,
31+ "yarn" ,
32+ "pnpm" ,
33+ "make" ,
34+ "go" ,
35+ "cargo" ,
36+ "dotnet" ,
37+ "mvn" ,
38+ "gradle" ,
39+ "pytest" ,
40+ "ruff" ,
41+ "mypy" ,
42+ "black" ,
43+ "isort" ,
44+ "flake8" ,
45+ }
2546)
47+ _SCRIPT_CALL_RE = re .compile (r"(?:" + "|" .join (sorted (_SCRIPT_CALL_TOOLS , key = len , reverse = True )) + r")\s+([^\s;&|]+)" )
2648_PKG_MANAGER_SUBCOMMANDS = frozenset (
2749 {
2850 "run" ,
@@ -162,6 +184,27 @@ def _extract_jenkins_refs(content: str) -> set[str]:
162184 return refs
163185
164186
187+ def _parse_tox_deps (deps : str , refs : set [str ]) -> None :
188+ for line in deps .splitlines ():
189+ line = line .strip ()
190+ if not line or line .startswith ("#" ) or line .startswith ("-r" ):
191+ continue
192+ refs .add (line .split ()[0 ] if line .split () else line )
193+
194+
195+ def _parse_tox_commands (commands : str , refs : set [str ]) -> None :
196+ for line in commands .splitlines ():
197+ line = line .strip ()
198+ if not line or line .startswith ("#" ):
199+ continue
200+ for p in line .split ():
201+ p = p .strip ("'\" " )
202+ p = re .sub (r"\{[^}]+\}" , "" , p )
203+ if p and not p .startswith ("-" ):
204+ refs .add (p )
205+ refs .update (_extract_script_refs (line ))
206+
207+
165208def _extract_tox_refs (content : str ) -> set [str ]:
166209 refs : set [str ] = set ()
167210 parser = configparser .ConfigParser ()
@@ -173,28 +216,8 @@ def _extract_tox_refs(content: str) -> set[str]:
173216 for section in parser .sections ():
174217 if not section .lower ().startswith ("testenv" ):
175218 continue
176-
177- deps = parser .get (section , "deps" , fallback = "" )
178- commands = parser .get (section , "commands" , fallback = "" )
179-
180- for line in deps .splitlines ():
181- line = line .strip ()
182- if not line or line .startswith ("#" ) or line .startswith ("-r" ):
183- continue
184- refs .add (line .split ()[0 ] if line .split () else line )
185-
186- for line in commands .splitlines ():
187- line = line .strip ()
188- if not line or line .startswith ("#" ):
189- continue
190- parts = line .split ()
191- for p in parts :
192- p = p .strip ("'\" " )
193- p = re .sub (r"\{[^}]+\}" , "" , p )
194- if not p or p .startswith ("-" ):
195- continue
196- refs .add (p )
197- refs .update (_extract_script_refs (line ))
219+ _parse_tox_deps (parser .get (section , "deps" , fallback = "" ), refs )
220+ _parse_tox_commands (parser .get (section , "commands" , fallback = "" ), refs )
198221
199222 return refs
200223
0 commit comments