From 5d01733e3ea4d8a725fbb215940681f9a9b00e5e Mon Sep 17 00:00:00 2001 From: Poorvi Gupta Date: Tue, 14 Oct 2025 15:00:04 +0530 Subject: [PATCH 1/3] changed fcntl to portalocker to ensure compatiblity with windows --- analysis/concurrent_knowledge.py | 6 +++--- commands/project.py | 10 +++++----- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/analysis/concurrent_knowledge.py b/analysis/concurrent_knowledge.py index 4706ac9..2f99387 100644 --- a/analysis/concurrent_knowledge.py +++ b/analysis/concurrent_knowledge.py @@ -5,7 +5,7 @@ vulnerability hypotheses, allowing multiple agents to collaborate on analysis. """ -import fcntl +import portalocker import hashlib import json import threading @@ -47,7 +47,7 @@ def _acquire_lock(self, timeout: float = 10.0) -> Any: while True: try: - fcntl.flock(lock_file, fcntl.LOCK_EX | fcntl.LOCK_NB) + portalocker.lock(lock_file, portalocker.LOCK_EX | portalocker.LOCK_NB) return lock_file except OSError: if time.time() - start_time > timeout: @@ -58,7 +58,7 @@ def _acquire_lock(self, timeout: float = 10.0) -> Any: def _release_lock(self, lock_file: Any): """Release file lock.""" try: - fcntl.flock(lock_file, fcntl.LOCK_UN) + portalocker.unlock(lock_file) lock_file.close() if self.lock_path.exists(): self.lock_path.unlink() diff --git a/commands/project.py b/commands/project.py index b7e4d3c..ce18093 100644 --- a/commands/project.py +++ b/commands/project.py @@ -225,7 +225,7 @@ def get_project(self, name: str) -> dict | None: if not config_file.exists(): return None - import fcntl + import portalocker import time # Retry logic for reading JSON with file locking @@ -235,9 +235,9 @@ def get_project(self, name: str) -> dict | None: with open(config_file) as f: # Try to get a shared lock for reading try: - fcntl.flock(f.fileno(), fcntl.LOCK_SH | fcntl.LOCK_NB) + portalocker.lock(f.fileno(), portalocker.LOCK_SH | portalocker.LOCK_NB) content = f.read() - fcntl.flock(f.fileno(), fcntl.LOCK_UN) + portalocker.unlock(f.fileno()) except OSError: # If we can't get lock, just read anyway content = f.read() @@ -266,9 +266,9 @@ def get_project(self, name: str) -> dict | None: with open(config_file, 'w') as f: # Try to get exclusive lock for writing try: - fcntl.flock(f.fileno(), fcntl.LOCK_EX | fcntl.LOCK_NB) + portalocker.lock(f.fileno(), portalocker.LOCK_EX | portalocker.LOCK_NB) json.dump(config, f, indent=2) - fcntl.flock(f.fileno(), fcntl.LOCK_UN) + portalocker.unlock(f.fileno()) except OSError: # If we can't get lock, skip updating last_accessed pass From 77d47dcdd7fde0d59309dac83b59c6de352c200d Mon Sep 17 00:00:00 2001 From: Poorvi Gupta Date: Tue, 14 Oct 2025 15:27:56 +0530 Subject: [PATCH 2/3] updated requirements.txt --- requirements.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index ad220cd..a53e2fc 100644 --- a/requirements.txt +++ b/requirements.txt @@ -13,7 +13,6 @@ typer>=0.9.0 pydantic>=2.0.0 pydantic-settings>=2.0 pyyaml>=6.0 - # Async Support httpx>=0.25.0 @@ -26,3 +25,6 @@ scikit-learn>=1.3.0 # CLI Enhancement rich>=13.0.0 + +# File Locking +portalocker>=2.7.0 \ No newline at end of file From 449ece949c917becd5d071a05f28c29a99e9368e Mon Sep 17 00:00:00 2001 From: Poorvi Gupta Date: Tue, 14 Oct 2025 15:32:31 +0530 Subject: [PATCH 3/3] after linitng --- analysis/concurrent_knowledge.py | 3 ++- commands/project.py | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/analysis/concurrent_knowledge.py b/analysis/concurrent_knowledge.py index 2f99387..ee993a0 100644 --- a/analysis/concurrent_knowledge.py +++ b/analysis/concurrent_knowledge.py @@ -5,7 +5,6 @@ vulnerability hypotheses, allowing multiple agents to collaborate on analysis. """ -import portalocker import hashlib import json import threading @@ -17,6 +16,8 @@ from pathlib import Path from typing import Any +import portalocker + # ============================================================================ # Base Concurrent Store # ============================================================================ diff --git a/commands/project.py b/commands/project.py index ce18093..a0aacd6 100644 --- a/commands/project.py +++ b/commands/project.py @@ -225,8 +225,9 @@ def get_project(self, name: str) -> dict | None: if not config_file.exists(): return None - import portalocker import time + + import portalocker # Retry logic for reading JSON with file locking max_retries = 5