From b06fe395b32e55a7a70349e8740e5911e9442f83 Mon Sep 17 00:00:00 2001 From: gneeraj2001 Date: Fri, 29 Aug 2025 02:06:43 -0700 Subject: [PATCH 1/9] Fix path handling consistency Signed-off-by: gneeraj2001 --- cognee/base_config.py | 15 ++- .../infrastructure/databases/graph/config.py | 16 ++- .../infrastructure/databases/vector/config.py | 21 ++-- cognee/root_dir.py | 28 +++++ cognee/tests/test_path_config.py | 114 ++++++++++++++++++ 5 files changed, 182 insertions(+), 12 deletions(-) create mode 100644 cognee/tests/test_path_config.py diff --git a/cognee/base_config.py b/cognee/base_config.py index aa0b14008..d80e6197f 100644 --- a/cognee/base_config.py +++ b/cognee/base_config.py @@ -1,15 +1,28 @@ 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(cls, values): + # Require absolute paths for root directories + values.data_root_directory = ensure_absolute_path( + values.data_root_directory, allow_relative=False + ) + values.system_root_directory = ensure_absolute_path( + values.system_root_directory, allow_relative=False + ) + return values + 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") diff --git a/cognee/infrastructure/databases/graph/config.py b/cognee/infrastructure/databases/graph/config.py index cdc001863..60c193d91 100644 --- a/cognee/infrastructure/databases/graph/config.py +++ b/cognee/infrastructure/databases/graph/config.py @@ -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,22 @@ 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: + # Convert relative paths to absolute using system_root_directory as base + values.graph_file_path = ensure_absolute_path( + values.graph_file_path, + base_path=base_config.system_root_directory, + allow_relative=True + ) + 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) diff --git a/cognee/infrastructure/databases/vector/config.py b/cognee/infrastructure/databases/vector/config.py index 07a3d1e05..ed846a54b 100644 --- a/cognee/infrastructure/databases/vector/config.py +++ b/cognee/infrastructure/databases/vector/config.py @@ -4,6 +4,7 @@ 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,12 +12,10 @@ 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_url: The URL of the vector database. Can be relative to system_root_directory. - vector_db_port: The port for the vector database. - vector_db_key: The key for accessing the vector database. - vector_db_provider: The provider for the vector database. @@ -30,10 +29,18 @@ 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 values.vector_db_url: + # Convert relative paths to absolute using system_root_directory as base + values.vector_db_url = ensure_absolute_path( + values.vector_db_url, + base_path=base_config.system_root_directory, + allow_relative=True, + ) + 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") diff --git a/cognee/root_dir.py b/cognee/root_dir.py index 2e21d5ce3..73afd0c12 100644 --- a/cognee/root_dir.py +++ b/cognee/root_dir.py @@ -1,4 +1,5 @@ from pathlib import Path +from typing import Optional ROOT_DIR = Path(__file__).resolve().parent @@ -6,3 +7,30 @@ 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, base_path: Optional[str] = None, allow_relative: bool = False +) -> str: + """Ensures a path is absolute, optionally converting relative paths. + + Args: + path: The path to validate/convert + base_path: Optional base path for relative paths. If None, uses ROOT_DIR + allow_relative: If False, raises error for relative paths instead of converting + + Returns: + Absolute path as string + + Raises: + ValueError: If path is relative and allow_relative is False + """ + path_obj = Path(path) + if path_obj.is_absolute(): + return str(path_obj.resolve()) + + if not allow_relative: + raise ValueError(f"Path must be absolute. Got relative path: {path}") + + base = Path(base_path) if base_path else ROOT_DIR + return str((base / path).resolve()) diff --git a/cognee/tests/test_path_config.py b/cognee/tests/test_path_config.py new file mode 100644 index 000000000..ff1905c5e --- /dev/null +++ b/cognee/tests/test_path_config.py @@ -0,0 +1,114 @@ +import os +from pathlib import Path + +def ensure_absolute_path(path: str, base_path: str = None, allow_relative: bool = False) -> str: + """Ensures a path is absolute, optionally converting relative paths.""" + if path is None: + raise ValueError("Path cannot be None") + + path_obj = Path(path) + if path_obj.is_absolute(): + return str(path_obj.resolve()) + + if not allow_relative: + raise ValueError(f"Path must be absolute. Got relative path: {path}") + + if base_path is None: + raise ValueError("base_path must be provided when converting relative paths") + + base = Path(base_path) + if not base.is_absolute(): + raise ValueError("base_path must be absolute when converting relative paths") + + return str((base / path).resolve()) + +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, allow_relative=False) + assert result == str(Path(abs_path).resolve()) + + # Test with relative path (should fail) + rel_path = "relative/path" + try: + ensure_absolute_path(rel_path, allow_relative=False) + assert False, "Should fail with relative path when allow_relative=False" + except ValueError as e: + assert "must be absolute" in str(e) + + # Test with None path + try: + ensure_absolute_path(None) + assert False, "Should fail with None path" + except ValueError as e: + assert "cannot be None" in str(e) + +def test_database_relative_paths(): + """Test relative path handling for vector and graph databases""" + system_root = "C:/system/root" if os.name == 'nt' else "/system/root" + + # Test with absolute path + abs_path = "C:/data/vector.db" if os.name == 'nt' else "/data/vector.db" + result = ensure_absolute_path(abs_path, base_path=system_root, allow_relative=True) + assert result == str(Path(abs_path).resolve()) + + # Test with relative path (should convert to absolute) + rel_path = "data/vector.db" + result = ensure_absolute_path(rel_path, base_path=system_root, allow_relative=True) + expected = str((Path(system_root) / rel_path).resolve()) + assert result == expected + + # Test with relative base_path (should fail) + try: + ensure_absolute_path(rel_path, base_path="relative/base", allow_relative=True) + assert False, "Should fail when base_path is relative" + except ValueError as e: + assert "base_path must be absolute" in str(e) + + # Test without base_path for relative path + try: + ensure_absolute_path(rel_path, allow_relative=True) + assert False, "Should fail when base_path is not provided for relative path" + except ValueError as e: + assert "base_path must be provided" in str(e) + +def test_path_consistency(): + """Test that paths are handled consistently across configurations""" + system_root = "C:/system/root" if os.name == 'nt' else "/system/root" + + # Root directories must be absolute + data_root = "C:/data/root" if os.name == 'nt' else "/data/root" + assert ensure_absolute_path(data_root, allow_relative=False) == str(Path(data_root).resolve()) + + # Database paths can be relative but must resolve against system_root + db_paths = [ + # Vector DB paths + "vector.db", # Simple relative + "data/vector.db", # Nested relative + "../vector.db", # Parent relative + "./vector.db", # Current dir relative + # Graph DB paths + "graph.db", # Simple relative + "data/graph/db", # Nested relative + "../graph.db", # Parent relative + "./graph.db", # Current dir relative + # With different extensions + "data/vector.lancedb", # Vector DB with extension + "data/graph/kuzu", # Graph DB with extension + ] + + for rel_path in db_paths: + result = ensure_absolute_path(rel_path, base_path=system_root, allow_relative=True) + expected = str((Path(system_root) / rel_path).resolve()) + assert result == expected, f"Failed to resolve {rel_path} correctly" + +if __name__ == "__main__": + print("Running path configuration tests...") + test_root_dir_absolute_paths() + print("✓ Root directory absolute path tests passed") + test_database_relative_paths() + print("✓ Database relative path tests passed") + test_path_consistency() + print("✓ Path consistency tests passed") + print("All tests passed successfully!") From aa3d704adc6baa143309fc66fb0edc1450b0085a Mon Sep 17 00:00:00 2001 From: Neeraj Gopalakrishnan <91423180+gneeraj2001@users.noreply.github.com> Date: Fri, 29 Aug 2025 02:31:58 -0700 Subject: [PATCH 2/9] Update cognee/base_config.py Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- cognee/base_config.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/cognee/base_config.py b/cognee/base_config.py index d80e6197f..b3258dba9 100644 --- a/cognee/base_config.py +++ b/cognee/base_config.py @@ -13,15 +13,15 @@ class BaseConfig(BaseSettings): monitoring_tool: object = Observer.LANGFUSE @pydantic.model_validator(mode="after") - def validate_paths(cls, values): + def validate_paths(self): # Require absolute paths for root directories - values.data_root_directory = ensure_absolute_path( - values.data_root_directory, allow_relative=False + self.data_root_directory = ensure_absolute_path( + self.data_root_directory, allow_relative=False ) - values.system_root_directory = ensure_absolute_path( - values.system_root_directory, allow_relative=False + self.system_root_directory = ensure_absolute_path( + self.system_root_directory, allow_relative=False ) - return values + return self langfuse_public_key: Optional[str] = os.getenv("LANGFUSE_PUBLIC_KEY") langfuse_secret_key: Optional[str] = os.getenv("LANGFUSE_SECRET_KEY") From 6e262d5eb3902c6839f071f78784f37c32f6934a Mon Sep 17 00:00:00 2001 From: Neeraj Gopalakrishnan <91423180+gneeraj2001@users.noreply.github.com> Date: Fri, 29 Aug 2025 02:33:16 -0700 Subject: [PATCH 3/9] Update cognee/tests/test_path_config.py Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- cognee/tests/test_path_config.py | 9 --------- 1 file changed, 9 deletions(-) diff --git a/cognee/tests/test_path_config.py b/cognee/tests/test_path_config.py index ff1905c5e..600f04579 100644 --- a/cognee/tests/test_path_config.py +++ b/cognee/tests/test_path_config.py @@ -103,12 +103,3 @@ def test_path_consistency(): expected = str((Path(system_root) / rel_path).resolve()) assert result == expected, f"Failed to resolve {rel_path} correctly" -if __name__ == "__main__": - print("Running path configuration tests...") - test_root_dir_absolute_paths() - print("✓ Root directory absolute path tests passed") - test_database_relative_paths() - print("✓ Database relative path tests passed") - test_path_consistency() - print("✓ Path consistency tests passed") - print("All tests passed successfully!") From 19e5980b50310dfa1f331911440b7591c1431689 Mon Sep 17 00:00:00 2001 From: Neeraj Gopalakrishnan <91423180+gneeraj2001@users.noreply.github.com> Date: Fri, 29 Aug 2025 02:35:03 -0700 Subject: [PATCH 4/9] Update cognee/tests/test_path_config.py Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- cognee/tests/test_path_config.py | 25 +++++-------------------- 1 file changed, 5 insertions(+), 20 deletions(-) diff --git a/cognee/tests/test_path_config.py b/cognee/tests/test_path_config.py index 600f04579..7a3d57e5b 100644 --- a/cognee/tests/test_path_config.py +++ b/cognee/tests/test_path_config.py @@ -1,26 +1,11 @@ import os from pathlib import Path -def ensure_absolute_path(path: str, base_path: str = None, allow_relative: bool = False) -> str: - """Ensures a path is absolute, optionally converting relative paths.""" - if path is None: - raise ValueError("Path cannot be None") - - path_obj = Path(path) - if path_obj.is_absolute(): - return str(path_obj.resolve()) - - if not allow_relative: - raise ValueError(f"Path must be absolute. Got relative path: {path}") - - if base_path is None: - raise ValueError("base_path must be provided when converting relative paths") - - base = Path(base_path) - if not base.is_absolute(): - raise ValueError("base_path must be absolute when converting relative paths") - - return str((base / path).resolve()) +from pathlib import Path +import pytest +from cognee.root_dir import ensure_absolute_path + +# …rest of your test cases using ensure_absolute_path… def test_root_dir_absolute_paths(): """Test absolute path handling in root_dir.py""" From d385d7edba37fd7b8f177bc3ebe647a1d3aa2d17 Mon Sep 17 00:00:00 2001 From: Neeraj Gopalakrishnan <91423180+gneeraj2001@users.noreply.github.com> Date: Fri, 29 Aug 2025 02:35:48 -0700 Subject: [PATCH 5/9] Update cognee/tests/test_path_config.py Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- cognee/tests/test_path_config.py | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/cognee/tests/test_path_config.py b/cognee/tests/test_path_config.py index 7a3d57e5b..65201fc70 100644 --- a/cognee/tests/test_path_config.py +++ b/cognee/tests/test_path_config.py @@ -45,19 +45,12 @@ def test_database_relative_paths(): assert result == expected # Test with relative base_path (should fail) - try: + with pytest.raises(ValueError, match="base_path must be absolute"): ensure_absolute_path(rel_path, base_path="relative/base", allow_relative=True) - assert False, "Should fail when base_path is relative" - except ValueError as e: - assert "base_path must be absolute" in str(e) # Test without base_path for relative path - try: + with pytest.raises(ValueError, match="base_path must be provided"): ensure_absolute_path(rel_path, allow_relative=True) - assert False, "Should fail when base_path is not provided for relative path" - except ValueError as e: - assert "base_path must be provided" in str(e) - def test_path_consistency(): """Test that paths are handled consistently across configurations""" system_root = "C:/system/root" if os.name == 'nt' else "/system/root" From ded92862c7b5b21147bd344f5a2d254a4bab909b Mon Sep 17 00:00:00 2001 From: Neeraj Gopalakrishnan <91423180+gneeraj2001@users.noreply.github.com> Date: Fri, 29 Aug 2025 02:38:39 -0700 Subject: [PATCH 6/9] Update cognee/root_dir.py Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- cognee/root_dir.py | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/cognee/root_dir.py b/cognee/root_dir.py index 73afd0c12..4853acd02 100644 --- a/cognee/root_dir.py +++ b/cognee/root_dir.py @@ -15,22 +15,29 @@ def ensure_absolute_path( """Ensures a path is absolute, optionally converting relative paths. Args: - path: The path to validate/convert - base_path: Optional base path for relative paths. If None, uses ROOT_DIR - allow_relative: If False, raises error for relative paths instead of converting + path: The path to validate/convert. + base_path: Required base when converting relative paths (e.g., SYSTEM_ROOT_DIRECTORY). + allow_relative: If False, raises error for relative paths instead of converting. Returns: Absolute path as string Raises: - ValueError: If path is relative and allow_relative is False + ValueError: If path is None; or path is relative and allow_relative is False; + or base_path is missing/non-absolute when converting. """ - path_obj = Path(path) + 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()) if not allow_relative: raise ValueError(f"Path must be absolute. Got relative path: {path}") - base = Path(base_path) if base_path else ROOT_DIR - return str((base / path).resolve()) + if base_path is None: + raise ValueError("base_path must be provided when converting relative paths") + base = Path(base_path).expanduser() + if not base.is_absolute(): + raise ValueError("base_path must be absolute when converting relative paths") + return str((base / path_obj).resolve()) From de939c154768e614022846d55977477f94e8b81e Mon Sep 17 00:00:00 2001 From: Neeraj Gopalakrishnan <91423180+gneeraj2001@users.noreply.github.com> Date: Fri, 29 Aug 2025 02:39:04 -0700 Subject: [PATCH 7/9] Update cognee/tests/test_path_config.py Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- cognee/tests/test_path_config.py | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/cognee/tests/test_path_config.py b/cognee/tests/test_path_config.py index 65201fc70..b90ce8cac 100644 --- a/cognee/tests/test_path_config.py +++ b/cognee/tests/test_path_config.py @@ -16,19 +16,12 @@ def test_root_dir_absolute_paths(): # Test with relative path (should fail) rel_path = "relative/path" - try: + with pytest.raises(ValueError, match="must be absolute"): ensure_absolute_path(rel_path, allow_relative=False) - assert False, "Should fail with relative path when allow_relative=False" - except ValueError as e: - assert "must be absolute" in str(e) - - # Test with None path - try: - ensure_absolute_path(None) - assert False, "Should fail with None path" - except ValueError as e: - assert "cannot be None" in str(e) + # Test with None path + with pytest.raises(ValueError, match="cannot be None"): + ensure_absolute_path(None) def test_database_relative_paths(): """Test relative path handling for vector and graph databases""" system_root = "C:/system/root" if os.name == 'nt' else "/system/root" From 74cf56e1ce6db668f4019282c722965e7925d428 Mon Sep 17 00:00:00 2001 From: Igor Ilic Date: Mon, 1 Sep 2025 16:31:10 +0200 Subject: [PATCH 8/9] fix: Return coding rules to MCP --- cognee-mcp/pyproject.toml | 2 +- cognee-mcp/src/server.py | 28 +++++++-------- cognee-mcp/uv.lock | 71 +++++++++++++++++++++++++++++++++------ 3 files changed, 75 insertions(+), 26 deletions(-) diff --git a/cognee-mcp/pyproject.toml b/cognee-mcp/pyproject.toml index a8596615b..8bde50841 100644 --- a/cognee-mcp/pyproject.toml +++ b/cognee-mcp/pyproject.toml @@ -8,7 +8,7 @@ requires-python = ">=3.10" dependencies = [ # For local cognee repo usage remove comment bellow and add absolute path to cognee. Then run `uv sync --reinstall` in the mcp folder on local cognee changes. # "cognee[postgres,codegraph,gemini,huggingface,docs,neo4j] @ file:/Users/vasilije/Projects/tiktok/cognee", - "cognee[postgres,codegraph,gemini,huggingface,docs,neo4j]==0.2.3", + "cognee[postgres,codegraph,gemini,huggingface,docs,neo4j]==0.2.4", "fastmcp>=2.10.0,<3.0.0", "mcp>=1.12.0,<2.0.0", "uv>=0.6.3,<1.0.0", diff --git a/cognee-mcp/src/server.py b/cognee-mcp/src/server.py index 5d11e0ce5..9e55b9707 100755 --- a/cognee-mcp/src/server.py +++ b/cognee-mcp/src/server.py @@ -21,16 +21,16 @@ from cognee.shared.data_models import KnowledgeGraph from cognee.modules.storage.utils import JSONEncoder -# try: -# from codingagents.coding_rule_associations import ( -# add_rule_associations, -# get_existing_rules, -# ) -# except ModuleNotFoundError: -# from .codingagents.coding_rule_associations import ( -# add_rule_associations, -# get_existing_rules, -# ) +try: + from codingagents.coding_rule_associations import ( + add_rule_associations, + get_existing_rules, + ) +except ModuleNotFoundError: + from .codingagents.coding_rule_associations import ( + add_rule_associations, + get_existing_rules, + ) mcp = FastMCP("Cognee") @@ -310,7 +310,7 @@ async def save_interaction(data: str) -> list: logger.info("Save interaction process finished.") logger.info("Generating associated rules from interaction data.") - # await add_rule_associations(data=data, rules_nodeset_name="coding_agent_rules") + await add_rule_associations(data=data, rules_nodeset_name="coding_agent_rules") logger.info("Associated rules generated from interaction data.") @@ -572,10 +572,8 @@ async def get_developer_rules() -> list: async def fetch_rules_from_cognee() -> str: """Collect all developer rules from Cognee""" with redirect_stdout(sys.stderr): - note = "This is broken in 0.2.2" - return note - # developer_rules = await get_existing_rules(rules_nodeset_name="coding_agent_rules") - # return developer_rules + developer_rules = await get_existing_rules(rules_nodeset_name="coding_agent_rules") + return developer_rules rules_text = await fetch_rules_from_cognee() diff --git a/cognee-mcp/uv.lock b/cognee-mcp/uv.lock index bfa434b4f..dd2797519 100644 --- a/cognee-mcp/uv.lock +++ b/cognee-mcp/uv.lock @@ -332,6 +332,21 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/df/73/b6e24bd22e6720ca8ee9a85a0c4a2971af8497d8f3193fa05390cbd46e09/backoff-2.2.1-py3-none-any.whl", hash = "sha256:63579f9a0628e06278f7e47b7d7d5b6ce20dc65c5e96a6f3ca99a6adca0396e8", size = 15148, upload-time = "2022-10-05T19:19:30.546Z" }, ] +[[package]] +name = "baml-py" +version = "0.201.0" +source = { registry = "https://pypi.org/simple" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/54/54/2b0edb3d22e95ce56f36610391c11108a4ef26ba2837736a32001687ae34/baml_py-0.201.0-cp38-abi3-macosx_10_12_x86_64.whl", hash = "sha256:83228d2af2b0e845bbbb4e14f7cbd3376cec385aee01210ac522ab6076e07bec", size = 17387971, upload-time = "2025-07-03T19:29:05.844Z" }, + { url = "https://files.pythonhosted.org/packages/c9/08/1d48c28c63eadea2c04360cbb7f64968599e99cd6b8fc0ec0bd4424d3cf1/baml_py-0.201.0-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:2a9d016139e3ae5b5ce98c7b05b5fbd53d5d38f04dc810ec4d70fb17dd6c10e4", size = 16191010, upload-time = "2025-07-03T19:29:09.323Z" }, + { url = "https://files.pythonhosted.org/packages/73/1a/20b2d46501e3dd0648af339825106a6ac5eeb5d22d7e6a10cf16b9aa1cb8/baml_py-0.201.0-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b5058505b1a3c5f04fc1679aec4d730fa9bef2cbd96209b3ed50152f60b96baf", size = 19950249, upload-time = "2025-07-03T19:29:11.974Z" }, + { url = "https://files.pythonhosted.org/packages/38/24/bc871059e905159ae1913c2e3032dd6ef2f5c3d0983999d2c2f1eebb65a4/baml_py-0.201.0-cp38-abi3-manylinux_2_24_aarch64.whl", hash = "sha256:36289d548581ba4accd5eaaab3246872542dd32dc6717e537654fa0cad884071", size = 19231310, upload-time = "2025-07-03T19:29:14.857Z" }, + { url = "https://files.pythonhosted.org/packages/0e/11/4268a0b82b02c7202fe5aa0d7175712158d998c491cac723b2bac3d5d495/baml_py-0.201.0-cp38-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:5ab70e7bd6481d71edca8a33313347b29faccec78b9960138aa437522813ac9a", size = 19490012, upload-time = "2025-07-03T19:29:18.512Z" }, + { url = "https://files.pythonhosted.org/packages/31/21/c9f9aea1adba2a5978ffab11ba0948a9f3f81ec6ed3056067713260e93a1/baml_py-0.201.0-cp38-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:7efc5c693a7142c230a4f3d6700415127fee0b9f5fdbb36db63e04e27ac4c0f1", size = 20090620, upload-time = "2025-07-03T19:29:21.072Z" }, + { url = "https://files.pythonhosted.org/packages/99/cf/92123d8d753f1d1473e080c4c182139bfe3b9a6418e891cf1d96b6c33848/baml_py-0.201.0-cp38-abi3-win_amd64.whl", hash = "sha256:56499857b7a27ae61a661c8ce0dddd0fb567a45c0b826157e44048a14cf586f9", size = 17253005, upload-time = "2025-07-03T19:29:23.722Z" }, + { url = "https://files.pythonhosted.org/packages/59/88/5056aa1bc9480f758cd6e210d63bd1f9ad90b44c87f4121285906526495e/baml_py-0.201.0-cp38-abi3-win_arm64.whl", hash = "sha256:1e52dc1151db84a302b746590fe2bc484bdd794f83fa5da7216d9394c559f33a", size = 15612701, upload-time = "2025-07-03T19:29:26.712Z" }, +] + [[package]] name = "bcrypt" version = "4.3.0" @@ -590,13 +605,14 @@ wheels = [ [[package]] name = "cognee" -version = "0.2.1" +version = "0.2.4" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "aiofiles" }, { name = "aiohttp" }, { name = "aiosqlite" }, { name = "alembic" }, + { name = "baml-py" }, { name = "dlt", extra = ["sqlalchemy"] }, { name = "fastapi" }, { name = "fastapi-users", extra = ["sqlalchemy"] }, @@ -624,6 +640,7 @@ dependencies = [ { name = "pympler" }, { name = "pypdf" }, { name = "python-dotenv" }, + { name = "python-magic-bin", marker = "sys_platform == 'win32'" }, { name = "python-multipart" }, { name = "rdflib" }, { name = "s3fs", extra = ["boto3"] }, @@ -634,9 +651,9 @@ dependencies = [ { name = "tiktoken" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/41/46/e7df1faebc92fa31ef8e33faf81feb435782727a789de5532d178e047224/cognee-0.2.1.tar.gz", hash = "sha256:bf5208383fc841981641c040e5b6588e58111af4d771f9eab6552f441e6a8e6c", size = 15497626, upload-time = "2025-07-25T15:53:57.009Z" } +sdist = { url = "https://files.pythonhosted.org/packages/da/b1/99c7f0c20cae101d4777bdc17b466bab58d0b4abfbb5d62c54d3babcc3ec/cognee-0.2.4.tar.gz", hash = "sha256:e8ac1c60cabb2e1d41db4f337a4dca3c7aa0c54d605d32e6087dba1c02b3beba", size = 13955686, upload-time = "2025-08-27T14:39:05.532Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/b3/0e/b705c6eeb538dcdd8fbbb331be25fe8e0bbc1af7d76e61566ec9845b29d3/cognee-0.2.1-py3-none-any.whl", hash = "sha256:6e9d437e0c58a16233841ebf19b1a3d8b67da069460a4f08d0c0e00301b1d36d", size = 1019851, upload-time = "2025-07-25T15:53:53.488Z" }, + { url = "https://files.pythonhosted.org/packages/e8/78/24df77b88d719ba308281412ebeb17c37867333e16bd2d1da7e192c1dc5d/cognee-0.2.4-py3-none-any.whl", hash = "sha256:56ab83c18ec9d7b307dfa206fcef39bc036e893d13e5390212f730b5204e3ae1", size = 1433548, upload-time = "2025-08-27T14:38:56.986Z" }, ] [package.optional-dependencies] @@ -682,7 +699,7 @@ dev = [ [package.metadata] requires-dist = [ - { name = "cognee", extras = ["postgres", "codegraph", "gemini", "huggingface", "docs", "neo4j"], specifier = "==0.2.1" }, + { name = "cognee", extras = ["postgres", "codegraph", "gemini", "huggingface", "docs", "neo4j"], specifier = "==0.2.4" }, { name = "fastmcp", specifier = ">=2.10.0,<3.0.0" }, { name = "mcp", specifier = ">=1.12.0,<2.0.0" }, { name = "uv", specifier = ">=0.6.3,<1.0.0" }, @@ -1258,6 +1275,30 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/0c/9a/51108b68e77650a7289b5f1ceff8dc0929ab48a26d1d2015f22121a9d183/fastmcp-2.11.0-py3-none-any.whl", hash = "sha256:8709a04522e66fda407b469fbe4d3290651aa7b06097b91c097e9a973c9b9bb3", size = 256193, upload-time = "2025-08-01T21:30:09.905Z" }, ] +[[package]] +name = "fastuuid" +version = "0.12.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/19/17/13146a1e916bd2971d0a58db5e0a4ad23efdd49f78f33ac871c161f8007b/fastuuid-0.12.0.tar.gz", hash = "sha256:d0bd4e5b35aad2826403f4411937c89e7c88857b1513fe10f696544c03e9bd8e", size = 19180, upload-time = "2025-01-27T18:04:14.387Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/97/c3/9db9aee6f34e6dfd1f909d3d7432ac26e491a0471f8bb8b676c44b625b3f/fastuuid-0.12.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:22a900ef0956aacf862b460e20541fdae2d7c340594fe1bd6fdcb10d5f0791a9", size = 247356, upload-time = "2025-01-27T18:04:45.397Z" }, + { url = "https://files.pythonhosted.org/packages/14/a5/999e6e017af3d85841ce1e172d32fd27c8700804c125f496f71bfddc1a9f/fastuuid-0.12.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0302f5acf54dc75de30103025c5a95db06d6c2be36829043a0aa16fc170076bc", size = 258384, upload-time = "2025-01-27T18:04:03.562Z" }, + { url = "https://files.pythonhosted.org/packages/c4/e6/beae8411cac5b3b0b9d59ee08405eb39c3abe81dad459114363eff55c14a/fastuuid-0.12.0-cp310-cp310-manylinux_2_34_x86_64.whl", hash = "sha256:7946b4a310cfc2d597dcba658019d72a2851612a2cebb949d809c0e2474cf0a6", size = 278480, upload-time = "2025-01-27T18:04:05.663Z" }, + { url = "https://files.pythonhosted.org/packages/f1/f6/c598b9a052435716fc5a084ef17049edd35ca2c8241161269bfea4905ab4/fastuuid-0.12.0-cp310-cp310-win_amd64.whl", hash = "sha256:a1b6764dd42bf0c46c858fb5ade7b7a3d93b7a27485a7a5c184909026694cd88", size = 156799, upload-time = "2025-01-27T18:05:41.867Z" }, + { url = "https://files.pythonhosted.org/packages/d4/99/555eab31381c7912103d4c8654082611e5e82a7bb88ad5ab067e36b622d7/fastuuid-0.12.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2bced35269315d16fe0c41003f8c9d63f2ee16a59295d90922cad5e6a67d0418", size = 247249, upload-time = "2025-01-27T18:03:23.092Z" }, + { url = "https://files.pythonhosted.org/packages/6d/3b/d62ce7f2af3d50a8e787603d44809770f43a3f2ff708bf10c252bf479109/fastuuid-0.12.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:82106e4b0a24f4f2f73c88f89dadbc1533bb808900740ca5db9bbb17d3b0c824", size = 258369, upload-time = "2025-01-27T18:04:08.903Z" }, + { url = "https://files.pythonhosted.org/packages/86/23/33ec5355036745cf83ea9ca7576d2e0750ff8d268c03b4af40ed26f1a303/fastuuid-0.12.0-cp311-cp311-manylinux_2_34_x86_64.whl", hash = "sha256:4db1bc7b8caa1d7412e1bea29b016d23a8d219131cff825b933eb3428f044dca", size = 278316, upload-time = "2025-01-27T18:04:12.74Z" }, + { url = "https://files.pythonhosted.org/packages/40/91/32ce82a14650148b6979ccd1a0089fd63d92505a90fb7156d2acc3245cbd/fastuuid-0.12.0-cp311-cp311-win_amd64.whl", hash = "sha256:07afc8e674e67ac3d35a608c68f6809da5fab470fb4ef4469094fdb32ba36c51", size = 156643, upload-time = "2025-01-27T18:05:59.266Z" }, + { url = "https://files.pythonhosted.org/packages/f6/28/442e79d6219b90208cb243ac01db05d89cc4fdf8ecd563fb89476baf7122/fastuuid-0.12.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:328694a573fe9dce556b0b70c9d03776786801e028d82f0b6d9db1cb0521b4d1", size = 247372, upload-time = "2025-01-27T18:03:40.967Z" }, + { url = "https://files.pythonhosted.org/packages/40/eb/e0fd56890970ca7a9ec0d116844580988b692b1a749ac38e0c39e1dbdf23/fastuuid-0.12.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:02acaea2c955bb2035a7d8e7b3fba8bd623b03746ae278e5fa932ef54c702f9f", size = 258200, upload-time = "2025-01-27T18:04:12.138Z" }, + { url = "https://files.pythonhosted.org/packages/f5/3c/4b30e376e65597a51a3dc929461a0dec77c8aec5d41d930f482b8f43e781/fastuuid-0.12.0-cp312-cp312-manylinux_2_34_x86_64.whl", hash = "sha256:ed9f449cba8cf16cced252521aee06e633d50ec48c807683f21cc1d89e193eb0", size = 278446, upload-time = "2025-01-27T18:04:15.877Z" }, + { url = "https://files.pythonhosted.org/packages/fe/96/cc5975fd23d2197b3e29f650a7a9beddce8993eaf934fa4ac595b77bb71f/fastuuid-0.12.0-cp312-cp312-win_amd64.whl", hash = "sha256:0df2ea4c9db96fd8f4fa38d0e88e309b3e56f8fd03675a2f6958a5b082a0c1e4", size = 157185, upload-time = "2025-01-27T18:06:19.21Z" }, + { url = "https://files.pythonhosted.org/packages/a9/e8/d2bb4f19e5ee15f6f8e3192a54a897678314151aa17d0fb766d2c2cbc03d/fastuuid-0.12.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:7fe2407316a04ee8f06d3dbc7eae396d0a86591d92bafe2ca32fce23b1145786", size = 247512, upload-time = "2025-01-27T18:04:08.115Z" }, + { url = "https://files.pythonhosted.org/packages/bc/53/25e811d92fd60f5c65e098c3b68bd8f1a35e4abb6b77a153025115b680de/fastuuid-0.12.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b9b31dd488d0778c36f8279b306dc92a42f16904cba54acca71e107d65b60b0c", size = 258257, upload-time = "2025-01-27T18:03:56.408Z" }, + { url = "https://files.pythonhosted.org/packages/10/23/73618e7793ea0b619caae2accd9e93e60da38dd78dd425002d319152ef2f/fastuuid-0.12.0-cp313-cp313-manylinux_2_34_x86_64.whl", hash = "sha256:b19361ee649365eefc717ec08005972d3d1eb9ee39908022d98e3bfa9da59e37", size = 278559, upload-time = "2025-01-27T18:03:58.661Z" }, + { url = "https://files.pythonhosted.org/packages/e4/41/6317ecfc4757d5f2a604e5d3993f353ba7aee85fa75ad8b86fce6fc2fa40/fastuuid-0.12.0-cp313-cp313-win_amd64.whl", hash = "sha256:8fc66b11423e6f3e1937385f655bedd67aebe56a3dcec0cb835351cfe7d358c9", size = 157276, upload-time = "2025-01-27T18:06:39.245Z" }, +] + [[package]] name = "filelock" version = "3.18.0" @@ -2253,11 +2294,12 @@ wheels = [ [[package]] name = "litellm" -version = "1.70.4" +version = "1.76.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "aiohttp" }, { name = "click" }, + { name = "fastuuid" }, { name = "httpx" }, { name = "importlib-metadata" }, { name = "jinja2" }, @@ -2268,9 +2310,9 @@ dependencies = [ { name = "tiktoken" }, { name = "tokenizers" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/60/d7/d0d76ba896a1e8978550dcc76157d1c50910ba9ade4ef3981a34f01f4fa6/litellm-1.70.4.tar.gz", hash = "sha256:ef6749a091faaaf88313afe4111cdd95736e1e60f21ba894e74f7c5bab2870bd", size = 7813817, upload-time = "2025-05-23T00:05:24.47Z" } +sdist = { url = "https://files.pythonhosted.org/packages/f8/fd/aa87c0a598377786521bee585f4d525e846f5339b816903298bfbb9daef5/litellm-1.76.1.tar.gz", hash = "sha256:d5a3a3efda04999b60ec0d1c29c1eaaa12f89a7b29db4bda691c7fb55b4fa6ad", size = 10178100, upload-time = "2025-08-30T21:05:48.578Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/cc/8f/0b26ecb08b8282ae0fdfa2223b5df8263579c9e3c75ca96bb7fb7cbc632c/litellm-1.70.4-py3-none-any.whl", hash = "sha256:4d14d04bf5e2bd49336b4abc59193352c731ff371022e4fcf590208f41f644f7", size = 7903749, upload-time = "2025-05-23T00:05:21.017Z" }, + { url = "https://files.pythonhosted.org/packages/d9/d3/16423b6d399540eeff357f00abc85f62dc337d347a0c98ccadc448a61df5/litellm-1.76.1-py3-none-any.whl", hash = "sha256:938f05075372f26098211ea9b3cb0a6bb7b46111330226b70d42d40bd307812f", size = 8965465, upload-time = "2025-08-30T21:05:46.068Z" }, ] [[package]] @@ -3117,7 +3159,7 @@ wheels = [ [[package]] name = "openai" -version = "1.98.0" +version = "1.99.8" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio" }, @@ -3129,9 +3171,9 @@ dependencies = [ { name = "tqdm" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/d8/9d/52eadb15c92802711d6b6cf00df3a6d0d18b588f4c5ba5ff210c6419fc03/openai-1.98.0.tar.gz", hash = "sha256:3ee0fcc50ae95267fd22bd1ad095ba5402098f3df2162592e68109999f685427", size = 496695, upload-time = "2025-07-30T12:48:03.701Z" } +sdist = { url = "https://files.pythonhosted.org/packages/4b/81/288157471c43975cc849bc8779b8c7209aec6da5d7cbcd87a982912a19e5/openai-1.99.8.tar.gz", hash = "sha256:4b49845983eb4d5ffae9bae5d98bd5c0bd3a709a30f8b994fc8f316961b6d566", size = 506953, upload-time = "2025-08-11T20:19:02.312Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/a8/fe/f64631075b3d63a613c0d8ab761d5941631a470f6fa87eaaee1aa2b4ec0c/openai-1.98.0-py3-none-any.whl", hash = "sha256:b99b794ef92196829120e2df37647722104772d2a74d08305df9ced5f26eae34", size = 767713, upload-time = "2025-07-30T12:48:01.264Z" }, + { url = "https://files.pythonhosted.org/packages/36/b6/3940f037aa33e6d5aa00707fd02843a1cac06ee0e106f39cfb71d0653d23/openai-1.99.8-py3-none-any.whl", hash = "sha256:426b981079cffde6dd54868b9b84761ffa291cde77010f051b96433e1835b47d", size = 786821, upload-time = "2025-08-11T20:18:59.943Z" }, ] [[package]] @@ -4163,6 +4205,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/6c/73/9f872cb81fc5c3bb48f7227872c28975f998f3e7c2b1c16e95e6432bbb90/python_magic-0.4.27-py2.py3-none-any.whl", hash = "sha256:c212960ad306f700aa0d01e5d7a325d20548ff97eb9920dcd29513174f0294d3", size = 13840, upload-time = "2022-06-07T20:16:57.763Z" }, ] +[[package]] +name = "python-magic-bin" +version = "0.4.14" +source = { registry = "https://pypi.org/simple" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5a/5d/10b9ac745d9fd2f7151a2ab901e6bb6983dbd70e87c71111f54859d1ca2e/python_magic_bin-0.4.14-py2.py3-none-win32.whl", hash = "sha256:34a788c03adde7608028203e2dbb208f1f62225ad91518787ae26d603ae68892", size = 397784, upload-time = "2017-10-02T16:30:15.806Z" }, + { url = "https://files.pythonhosted.org/packages/07/c2/094e3d62b906d952537196603a23aec4bcd7c6126bf80eb14e6f9f4be3a2/python_magic_bin-0.4.14-py2.py3-none-win_amd64.whl", hash = "sha256:90be6206ad31071a36065a2fc169c5afb5e0355cbe6030e87641c6c62edc2b69", size = 409299, upload-time = "2017-10-02T16:30:18.545Z" }, +] + [[package]] name = "python-multipart" version = "0.0.20" From d8326a7e3aad95d090739777d126b6cf4008a784 Mon Sep 17 00:00:00 2001 From: Igor Ilic Date: Tue, 2 Sep 2025 11:21:05 +0200 Subject: [PATCH 9/9] feat: path handling has to be absolute by gneeraj2001 --- cognee/base_config.py | 8 +-- .../infrastructure/databases/graph/config.py | 6 +- .../infrastructure/databases/vector/config.py | 8 +-- cognee/root_dir.py | 24 ++------ cognee/tests/test_path_config.py | 59 +------------------ 5 files changed, 14 insertions(+), 91 deletions(-) diff --git a/cognee/base_config.py b/cognee/base_config.py index b3258dba9..940846128 100644 --- a/cognee/base_config.py +++ b/cognee/base_config.py @@ -15,12 +15,8 @@ class BaseConfig(BaseSettings): @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, allow_relative=False - ) - self.system_root_directory = ensure_absolute_path( - self.system_root_directory, allow_relative=False - ) + 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") diff --git a/cognee/infrastructure/databases/graph/config.py b/cognee/infrastructure/databases/graph/config.py index 60c193d91..d96de4520 100644 --- a/cognee/infrastructure/databases/graph/config.py +++ b/cognee/infrastructure/databases/graph/config.py @@ -60,11 +60,9 @@ class GraphConfig(BaseSettings): # Handle graph file path if values.graph_file_path: - # Convert relative paths to absolute using system_root_directory as base + # Check if absolute path is provided values.graph_file_path = ensure_absolute_path( - values.graph_file_path, - base_path=base_config.system_root_directory, - allow_relative=True + os.path.join(values.graph_file_path, values.graph_filename) ) else: # Default path diff --git a/cognee/infrastructure/databases/vector/config.py b/cognee/infrastructure/databases/vector/config.py index ed846a54b..7a20130bd 100644 --- a/cognee/infrastructure/databases/vector/config.py +++ b/cognee/infrastructure/databases/vector/config.py @@ -1,5 +1,6 @@ import os import pydantic +from pathlib import Path from functools import lru_cache from pydantic_settings import BaseSettings, SettingsConfigDict @@ -32,12 +33,11 @@ class VectorConfig(BaseSettings): def validate_paths(cls, values): base_config = get_base_config() - if values.vector_db_url: - # Convert relative paths to absolute using system_root_directory as base + # 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, - base_path=base_config.system_root_directory, - allow_relative=True, ) else: # Default path diff --git a/cognee/root_dir.py b/cognee/root_dir.py index 4853acd02..46d8fcb69 100644 --- a/cognee/root_dir.py +++ b/cognee/root_dir.py @@ -9,22 +9,14 @@ def get_absolute_path(path_from_root: str) -> str: return str(absolute_path.resolve()) -def ensure_absolute_path( - path: str, base_path: Optional[str] = None, allow_relative: bool = False -) -> str: - """Ensures a path is absolute, optionally converting relative paths. +def ensure_absolute_path(path: str) -> str: + """Ensures a path is absolute. Args: - path: The path to validate/convert. - base_path: Required base when converting relative paths (e.g., SYSTEM_ROOT_DIRECTORY). - allow_relative: If False, raises error for relative paths instead of converting. + path: The path to validate. Returns: Absolute path as string - - Raises: - ValueError: If path is None; or path is relative and allow_relative is False; - or base_path is missing/non-absolute when converting. """ if path is None: raise ValueError("Path cannot be None") @@ -32,12 +24,4 @@ def ensure_absolute_path( if path_obj.is_absolute(): return str(path_obj.resolve()) - if not allow_relative: - raise ValueError(f"Path must be absolute. Got relative path: {path}") - - if base_path is None: - raise ValueError("base_path must be provided when converting relative paths") - base = Path(base_path).expanduser() - if not base.is_absolute(): - raise ValueError("base_path must be absolute when converting relative paths") - return str((base / path_obj).resolve()) + raise ValueError(f"Path must be absolute. Got relative path: {path}") diff --git a/cognee/tests/test_path_config.py b/cognee/tests/test_path_config.py index b90ce8cac..55f641479 100644 --- a/cognee/tests/test_path_config.py +++ b/cognee/tests/test_path_config.py @@ -1,19 +1,16 @@ import os -from pathlib import Path - from pathlib import Path import pytest from cognee.root_dir import ensure_absolute_path -# …rest of your test cases using ensure_absolute_path… 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" + abs_path = "C:/absolute/path" if os.name == "nt" else "/absolute/path" result = ensure_absolute_path(abs_path, allow_relative=False) 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"): @@ -22,55 +19,3 @@ def test_root_dir_absolute_paths(): # Test with None path with pytest.raises(ValueError, match="cannot be None"): ensure_absolute_path(None) -def test_database_relative_paths(): - """Test relative path handling for vector and graph databases""" - system_root = "C:/system/root" if os.name == 'nt' else "/system/root" - - # Test with absolute path - abs_path = "C:/data/vector.db" if os.name == 'nt' else "/data/vector.db" - result = ensure_absolute_path(abs_path, base_path=system_root, allow_relative=True) - assert result == str(Path(abs_path).resolve()) - - # Test with relative path (should convert to absolute) - rel_path = "data/vector.db" - result = ensure_absolute_path(rel_path, base_path=system_root, allow_relative=True) - expected = str((Path(system_root) / rel_path).resolve()) - assert result == expected - - # Test with relative base_path (should fail) - with pytest.raises(ValueError, match="base_path must be absolute"): - ensure_absolute_path(rel_path, base_path="relative/base", allow_relative=True) - - # Test without base_path for relative path - with pytest.raises(ValueError, match="base_path must be provided"): - ensure_absolute_path(rel_path, allow_relative=True) -def test_path_consistency(): - """Test that paths are handled consistently across configurations""" - system_root = "C:/system/root" if os.name == 'nt' else "/system/root" - - # Root directories must be absolute - data_root = "C:/data/root" if os.name == 'nt' else "/data/root" - assert ensure_absolute_path(data_root, allow_relative=False) == str(Path(data_root).resolve()) - - # Database paths can be relative but must resolve against system_root - db_paths = [ - # Vector DB paths - "vector.db", # Simple relative - "data/vector.db", # Nested relative - "../vector.db", # Parent relative - "./vector.db", # Current dir relative - # Graph DB paths - "graph.db", # Simple relative - "data/graph/db", # Nested relative - "../graph.db", # Parent relative - "./graph.db", # Current dir relative - # With different extensions - "data/vector.lancedb", # Vector DB with extension - "data/graph/kuzu", # Graph DB with extension - ] - - for rel_path in db_paths: - result = ensure_absolute_path(rel_path, base_path=system_root, allow_relative=True) - expected = str((Path(system_root) / rel_path).resolve()) - assert result == expected, f"Failed to resolve {rel_path} correctly" -