Compare commits

...

1 Commits

Author SHA1 Message Date
claude[bot] c0b531866d fix: Allow BASIC_MEMORY_HOME env var to override file-based config
The BASIC_MEMORY_HOME environment variable was not being respected when
a config file existed, because the file-based configuration bypassed
Pydantic''s environment variable parsing.

This fix modifies ConfigManager.load_config() to explicitly check for
BASIC_MEMORY_HOME after loading from file and override the main project
path if the environment variable is set.

Fixes #219

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-authored-by: Paul Hernandez <phernandez@users.noreply.github.com>
2025-07-10 01:24:01 +00:00
2 changed files with 78 additions and 2 deletions
+8 -1
View File
@@ -180,7 +180,14 @@ class ConfigManager:
if self.config_file.exists():
try:
data = json.loads(self.config_file.read_text(encoding="utf-8"))
return BasicMemoryConfig(**data)
config = BasicMemoryConfig(**data)
# Allow BASIC_MEMORY_HOME environment variable to override the main project path
env_home = os.getenv("BASIC_MEMORY_HOME")
if env_home:
config.projects["main"] = str(Path(env_home))
return config
except Exception as e: # pragma: no cover
logger.error(f"Failed to load config: {e}")
config = BasicMemoryConfig()
+70 -1
View File
@@ -1,6 +1,7 @@
"""Test configuration management."""
from basic_memory.config import BasicMemoryConfig
import json
from basic_memory.config import BasicMemoryConfig, ConfigManager
class TestBasicMemoryConfig:
@@ -76,3 +77,71 @@ class TestBasicMemoryConfig:
# The default_factory should override with BASIC_MEMORY_HOME value
# Note: This tests the current behavior where default_factory takes precedence
assert config.projects["main"] == original_path
class TestConfigManager:
"""Test ConfigManager behavior with BASIC_MEMORY_HOME environment variable."""
def test_load_config_respects_basic_memory_home_with_existing_file(self, config_home, monkeypatch):
"""Test that ConfigManager.load_config respects BASIC_MEMORY_HOME even when config file exists."""
# Set up a custom path via environment variable
custom_path = str(config_home / "custom" / "env" / "path")
monkeypatch.setenv("BASIC_MEMORY_HOME", custom_path)
# Create a config manager with a temporary config directory
config_dir = config_home / ".basic-memory"
config_dir.mkdir(parents=True, exist_ok=True)
config_file = config_dir / "config.json"
# Create a config file with a different main project path
file_config = {
"projects": {
"main": str(config_home / "file" / "path")
},
"default_project": "main"
}
config_file.write_text(json.dumps(file_config))
# Mock the ConfigManager to use our temporary config directory
monkeypatch.setattr("basic_memory.config.ConfigManager.config_dir", config_dir)
monkeypatch.setattr("basic_memory.config.ConfigManager.config_file", config_file)
# Create ConfigManager and load config
config_manager = ConfigManager()
config_manager.config_dir = config_dir
config_manager.config_file = config_file
loaded_config = config_manager.load_config()
# The environment variable should override the file-based configuration
assert loaded_config.projects["main"] == custom_path
def test_load_config_without_basic_memory_home_uses_file_config(self, config_home, monkeypatch):
"""Test that ConfigManager.load_config uses file config when BASIC_MEMORY_HOME is not set."""
# Ensure BASIC_MEMORY_HOME is not set
monkeypatch.delenv("BASIC_MEMORY_HOME", raising=False)
# Create a config manager with a temporary config directory
config_dir = config_home / ".basic-memory"
config_dir.mkdir(parents=True, exist_ok=True)
config_file = config_dir / "config.json"
# Create a config file with a specific main project path
file_path = str(config_home / "file" / "path")
file_config = {
"projects": {
"main": file_path
},
"default_project": "main"
}
config_file.write_text(json.dumps(file_config))
# Create ConfigManager and load config
config_manager = ConfigManager()
config_manager.config_dir = config_dir
config_manager.config_file = config_file
loaded_config = config_manager.load_config()
# Should use the file-based configuration
assert loaded_config.projects["main"] == file_path