Fix path handling consistency (#1327)

<!-- .github/pull_request_template.md -->

## Description
Fix path handling consistency by Gneeraj2001

## DCO Affirmation
I affirm that all code in every commit of this pull request conforms to
the terms of the Topoteretes Developer Certificate of Origin.
This commit is contained in:
Vasilije 2025-09-02 15:17:38 +02:00 committed by GitHub
commit 616075d6c4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 75 additions and 13 deletions

View file

@ -79,7 +79,9 @@ More on [use-cases](https://docs.cognee.ai/use-cases) and [evals](https://github
## Get Started
Get started quickly with a Google Colab <a href="https://colab.research.google.com/drive/1jHbWVypDgCLwjE71GSXhRL3YxYhCZzG1?usp=sharing">notebook</a> , <a href="https://deepnote.com/workspace/cognee-382213d0-0444-4c89-8265-13770e333c02/project/cognee-demo-78ffacb9-5832-4611-bb1a-560386068b30/notebook/Notebook-1-75b24cda566d4c24ab348f7150792601?utm_source=share-modal&utm_medium=product-shared-content&utm_campaign=notebook&utm_content=78ffacb9-5832-4611-bb1a-560386068b30">Deepnote notebook</a> or <a href="https://github.com/topoteretes/cognee-starter">starter repo</a>
Get started quickly with a Google Colab <a href="https://colab.research.google.com/drive/1jHbWVypDgCLwjE71GSXhRL3YxYhCZzG1?usp=sharing">notebook</a> , <a href="https://deepnote.com/workspace/cognee-382213d0-0444-4c89-8265-13770e333c02/project/cognee-demo-78ffacb9-5832-4611-bb1a-560386068b30/notebook/Notebook-1-75b24cda566d4c24ab348f7150792601?utm_source=share-modal&utm_medium=product-shared-content&utm_campaign=notebook&utm_content=78ffacb9-5832-4611-bb1a-560386068b30">Deepnote notebook</a> or <a href="https://github.com/topoteretes/cognee/tree/main/cognee-starter-kit">starter repo</a>
## Contributing

View file

@ -1,15 +1,24 @@
import os
from typing import Optional
from functools import lru_cache
from cognee.root_dir import get_absolute_path
from cognee.root_dir import get_absolute_path, ensure_absolute_path
from cognee.modules.observability.observers import Observer
from pydantic_settings import BaseSettings, SettingsConfigDict
import pydantic
class BaseConfig(BaseSettings):
data_root_directory: str = get_absolute_path(".data_storage")
system_root_directory: str = get_absolute_path(".cognee_system")
monitoring_tool: object = Observer.LANGFUSE
@pydantic.model_validator(mode="after")
def validate_paths(self):
# Require absolute paths for root directories
self.data_root_directory = ensure_absolute_path(self.data_root_directory)
self.system_root_directory = ensure_absolute_path(self.system_root_directory)
return self
langfuse_public_key: Optional[str] = os.getenv("LANGFUSE_PUBLIC_KEY")
langfuse_secret_key: Optional[str] = os.getenv("LANGFUSE_SECRET_KEY")
langfuse_host: Optional[str] = os.getenv("LANGFUSE_HOST")

View file

@ -6,6 +6,7 @@ from pydantic_settings import BaseSettings, SettingsConfigDict
import pydantic
from pydantic import Field
from cognee.base_config import get_base_config
from cognee.root_dir import ensure_absolute_path
from cognee.shared.data_models import KnowledgeGraph
@ -51,15 +52,20 @@ class GraphConfig(BaseSettings):
@pydantic.model_validator(mode="after")
def fill_derived(cls, values):
provider = values.graph_database_provider.lower()
base_config = get_base_config()
# Set default filename if no filename is provided
if not values.graph_filename:
values.graph_filename = f"cognee_graph_{provider}"
# Set file path based on graph database provider if no file path is provided
if not values.graph_file_path:
base_config = get_base_config()
# Handle graph file path
if values.graph_file_path:
# Check if absolute path is provided
values.graph_file_path = ensure_absolute_path(
os.path.join(values.graph_file_path, values.graph_filename)
)
else:
# Default path
databases_directory_path = os.path.join(base_config.system_root_directory, "databases")
values.graph_file_path = os.path.join(databases_directory_path, values.graph_filename)

View file

@ -1,9 +1,11 @@
import os
import pydantic
from pathlib import Path
from functools import lru_cache
from pydantic_settings import BaseSettings, SettingsConfigDict
from cognee.base_config import get_base_config
from cognee.root_dir import ensure_absolute_path
class VectorConfig(BaseSettings):
@ -11,11 +13,9 @@ class VectorConfig(BaseSettings):
Manage the configuration settings for the vector database.
Public methods:
- to_dict: Convert the configuration to a dictionary.
Instance variables:
- vector_db_url: The URL of the vector database.
- vector_db_port: The port for the vector database.
- vector_db_key: The key for accessing the vector database.
@ -30,10 +30,17 @@ class VectorConfig(BaseSettings):
model_config = SettingsConfigDict(env_file=".env", extra="allow")
@pydantic.model_validator(mode="after")
def fill_derived(cls, values):
# Set file path based on graph database provider if no file path is provided
if not values.vector_db_url:
base_config = get_base_config()
def validate_paths(cls, values):
base_config = get_base_config()
# If vector_db_url is provided and is not a path skip checking if path is absolute (as it can also be a url)
if values.vector_db_url and Path(values.vector_db_url).exists():
# Relative path to absolute
values.vector_db_url = ensure_absolute_path(
values.vector_db_url,
)
else:
# Default path
databases_directory_path = os.path.join(base_config.system_root_directory, "databases")
values.vector_db_url = os.path.join(databases_directory_path, "cognee.lancedb")

View file

@ -1,4 +1,5 @@
from pathlib import Path
from typing import Optional
ROOT_DIR = Path(__file__).resolve().parent
@ -6,3 +7,21 @@ ROOT_DIR = Path(__file__).resolve().parent
def get_absolute_path(path_from_root: str) -> str:
absolute_path = ROOT_DIR / path_from_root
return str(absolute_path.resolve())
def ensure_absolute_path(path: str) -> str:
"""Ensures a path is absolute.
Args:
path: The path to validate.
Returns:
Absolute path as string
"""
if path is None:
raise ValueError("Path cannot be None")
path_obj = Path(path).expanduser()
if path_obj.is_absolute():
return str(path_obj.resolve())
raise ValueError(f"Path must be absolute. Got relative path: {path}")

View file

@ -4,8 +4,9 @@ import pytest
from unittest.mock import patch, mock_open
from io import BytesIO
from uuid import uuid4
from pathlib import Path
from cognee.root_dir import ensure_absolute_path
from cognee.infrastructure.files.utils.get_file_content_hash import get_file_content_hash
from cognee.shared.utils import get_anonymous_id
@ -52,3 +53,21 @@ async def test_get_file_content_hash_stream():
expected_hash = hashlib.md5(b"test_data").hexdigest()
result = await get_file_content_hash(stream)
assert result == expected_hash
@pytest.mark.asyncio
async def test_root_dir_absolute_paths():
"""Test absolute path handling in root_dir.py"""
# Test with absolute path
abs_path = "C:/absolute/path" if os.name == "nt" else "/absolute/path"
result = ensure_absolute_path(abs_path)
assert result == str(Path(abs_path).resolve())
# Test with relative path (should fail)
rel_path = "relative/path"
with pytest.raises(ValueError, match="must be absolute"):
ensure_absolute_path(rel_path)
# Test with None path
with pytest.raises(ValueError, match="cannot be None"):
ensure_absolute_path(None)