From adb9ddfbeb00adaf7036f01180f5da0a5bb8d7b3 Mon Sep 17 00:00:00 2001 From: HalaAli198 Date: Sat, 4 Oct 2025 02:44:06 -0700 Subject: [PATCH] Fix: Parse unquoted dependencies in setup.py with .split() pattern - Added support for multiline string dependencies using .split() - Stores file content in variable and reuses it for both patterns - Maintains backward compatibility with list-style dependencies - Handles both triple double-quotes and triple single-quotes Tested with mayan-edms==4.9.2 which uses this pattern. Before fix: 0 dependencies detected After fix: 57 dependencies correctly parsed --- sbom4python/scanner.py | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/sbom4python/scanner.py b/sbom4python/scanner.py index ad0908a..47ac146 100644 --- a/sbom4python/scanner.py +++ b/sbom4python/scanner.py @@ -689,8 +689,9 @@ def process_setup_py(self, filename): if filePath.exists() and filePath.is_file(): dependencies = [] with open(filename, "r") as setup_file: + content = setup_file.read() # Read the file into a stream and search for list if dependencies specified by install_requires - stream = setup_file.read().replace("\n", "") + stream = content.replace("\n", "") match = re.search(r"install_requires\s*=\s*\[([^\]]+)\]", stream) if match: dependency_list = match.group(1).strip() @@ -699,6 +700,23 @@ def process_setup_py(self, filename): for dep in dependency_list.split(",") if len(dep) > 0 ] + # Method 2: Handle multiline string with .split() + # Handles: install_requires = """package==1.0\npackage2>=2.0""".split() + # Also handles single quotes: install_requires = '''...'''.split() + if not dependencies: + split_match = re.search(r'install_requires\s*=\s*["\'"]{3}([^"\']+)["\'"]{3}\.split\(\)', content, re.DOTALL) + if split_match: + # Extract dependencies from the multiline string + deps_block = split_match.group(1).strip() + # Split by newlines and filter out empty lines + dependencies = [ + line.strip() + for line in deps_block.split('\n') + if line.strip() and not line.strip().startswith('#') + ] + + + if self.debug: print(dependencies) self.set_lifecycle("pre-build")