From 18e0aa2f6c30c3bb89b21b35b75c1d577f4569e6 Mon Sep 17 00:00:00 2001 From: hajdul88 <52442977+hajdul88@users.noreply.github.com> Date: Tue, 3 Dec 2024 14:20:29 +0100 Subject: [PATCH 1/3] fix: deletes get_graph_from_model test of the faulty old implementation --- .../graph/get_graph_from_model_test.py | 89 ------------------- 1 file changed, 89 deletions(-) delete mode 100644 cognee/tests/unit/interfaces/graph/get_graph_from_model_test.py diff --git a/cognee/tests/unit/interfaces/graph/get_graph_from_model_test.py b/cognee/tests/unit/interfaces/graph/get_graph_from_model_test.py deleted file mode 100644 index e56a2dff..00000000 --- a/cognee/tests/unit/interfaces/graph/get_graph_from_model_test.py +++ /dev/null @@ -1,89 +0,0 @@ -from cognee.modules.graph.utils import get_graph_from_model -from cognee.tests.unit.interfaces.graph.util import run_test_against_ground_truth - -CAR_SEDAN_EDGE = ( - "car1", - "sedan", - "is_type", - { - "source_node_id": "car1", - "target_node_id": "sedan", - "relationship_name": "is_type", - }, -) - - -BORIS_CAR_EDGE_GROUND_TRUTH = ( - "boris", - "car1", - "owns_car", - { - "source_node_id": "boris", - "target_node_id": "car1", - "relationship_name": "owns_car", - "metadata": {"type": "list"}, - }, -) - -CAR_TYPE_GROUND_TRUTH = {"id": "sedan"} - -CAR_GROUND_TRUTH = { - "id": "car1", - "brand": "Toyota", - "model": "Camry", - "year": 2020, - "color": "Blue", -} - -PERSON_GROUND_TRUTH = { - "id": "boris", - "name": "Boris", - "age": 30, - "driving_license": { - "issued_by": "PU Vrsac", - "issued_on": "2025-11-06", - "number": "1234567890", - "expires_on": "2025-11-06", - }, -} - - -def test_extracted_car_type(boris): - nodes, _ = get_graph_from_model(boris) - assert len(nodes) == 3 - car_type = nodes[0] - run_test_against_ground_truth("car_type", car_type, CAR_TYPE_GROUND_TRUTH) - - -def test_extracted_car(boris): - nodes, _ = get_graph_from_model(boris) - assert len(nodes) == 3 - car = nodes[1] - run_test_against_ground_truth("car", car, CAR_GROUND_TRUTH) - - -def test_extracted_person(boris): - nodes, _ = get_graph_from_model(boris) - assert len(nodes) == 3 - person = nodes[2] - run_test_against_ground_truth("person", person, PERSON_GROUND_TRUTH) - - -def test_extracted_car_sedan_edge(boris): - _, edges = get_graph_from_model(boris) - edge = edges[0] - - assert CAR_SEDAN_EDGE[:3] == edge[:3], f"{CAR_SEDAN_EDGE[:3] = } != {edge[:3] = }" - for key, ground_truth in CAR_SEDAN_EDGE[3].items(): - assert ground_truth == edge[3][key], f"{ground_truth = } != {edge[3][key] = }" - - -def test_extracted_boris_car_edge(boris): - _, edges = get_graph_from_model(boris) - edge = edges[1] - - assert ( - BORIS_CAR_EDGE_GROUND_TRUTH[:3] == edge[:3] - ), f"{BORIS_CAR_EDGE_GROUND_TRUTH[:3] = } != {edge[:3] = }" - for key, ground_truth in BORIS_CAR_EDGE_GROUND_TRUTH[3].items(): - assert ground_truth == edge[3][key], f"{ground_truth = } != {edge[3][key] = }" From 688c3dfdb7094340269b5a221ca374d67b5778d2 Mon Sep 17 00:00:00 2001 From: hajdul88 <52442977+hajdul88@users.noreply.github.com> Date: Tue, 3 Dec 2024 14:33:46 +0100 Subject: [PATCH 2/3] Fix: deletes test that were implemented the faulty get_model_from_graph method --- .../get_graph_from_model_generative_test.py | 37 ------------------- ...del_instance_from_graph_generative_test.py | 33 ----------------- .../get_model_instance_from_graph_test.py | 35 ------------------ 3 files changed, 105 deletions(-) delete mode 100644 cognee/tests/unit/interfaces/graph/get_graph_from_model_generative_test.py delete mode 100644 cognee/tests/unit/interfaces/graph/get_model_instance_from_graph_generative_test.py delete mode 100644 cognee/tests/unit/interfaces/graph/get_model_instance_from_graph_test.py diff --git a/cognee/tests/unit/interfaces/graph/get_graph_from_model_generative_test.py b/cognee/tests/unit/interfaces/graph/get_graph_from_model_generative_test.py deleted file mode 100644 index dec751f8..00000000 --- a/cognee/tests/unit/interfaces/graph/get_graph_from_model_generative_test.py +++ /dev/null @@ -1,37 +0,0 @@ -import warnings - -import pytest - -from cognee.modules.graph.utils import get_graph_from_model -from cognee.tests.unit.interfaces.graph.util import ( - PERSON_NAMES, - count_society, - create_organization_recursive, -) - - -@pytest.mark.parametrize("recursive_depth", [1, 2, 3]) -def test_society_nodes_and_edges(recursive_depth): - import sys - - if sys.version_info[0] == 3 and sys.version_info[1] >= 11: - society = create_organization_recursive( - "society", "Society", PERSON_NAMES, recursive_depth - ) - - n_organizations, n_persons = count_society(society) - society_counts_total = n_organizations + n_persons - - nodes, edges = get_graph_from_model(society) - - assert ( - len(nodes) == society_counts_total - ), f"{society_counts_total = } != {len(nodes) = }, not all DataPoint instances were found" - - assert len(edges) == ( - len(nodes) - 1 - ), f"{(len(nodes) - 1) = } != {len(edges) = }, there have to be n_nodes - 1 edges, as each node has exactly one parent node, except for the root node" - else: - warnings.warn( - "The recursive pydantic data structure cannot be reconstructed from the graph because the 'inner' pydantic class is not defined. Hence this test is skipped. This problem is solved in Python 3.11" - ) diff --git a/cognee/tests/unit/interfaces/graph/get_model_instance_from_graph_generative_test.py b/cognee/tests/unit/interfaces/graph/get_model_instance_from_graph_generative_test.py deleted file mode 100644 index dd5e1946..00000000 --- a/cognee/tests/unit/interfaces/graph/get_model_instance_from_graph_generative_test.py +++ /dev/null @@ -1,33 +0,0 @@ -import warnings - -import pytest - -from cognee.modules.graph.utils import ( - get_graph_from_model, - get_model_instance_from_graph, -) -from cognee.tests.unit.interfaces.graph.util import ( - PERSON_NAMES, - create_organization_recursive, - show_first_difference, -) - - -@pytest.mark.parametrize("recursive_depth", [1, 2, 3]) -def test_society_nodes_and_edges(recursive_depth): - import sys - - if sys.version_info[0] == 3 and sys.version_info[1] >= 11: - society = create_organization_recursive( - "society", "Society", PERSON_NAMES, recursive_depth - ) - nodes, edges = get_graph_from_model(society) - parsed_society = get_model_instance_from_graph(nodes, edges, "society") - - assert str(society) == (str(parsed_society)), show_first_difference( - str(society), str(parsed_society), "society", "parsed_society" - ) - else: - warnings.warn( - "The recursive pydantic data structure cannot be reconstructed from the graph because the 'inner' pydantic class is not defined. Hence this test is skipped. This problem is solved in Python 3.11" - ) diff --git a/cognee/tests/unit/interfaces/graph/get_model_instance_from_graph_test.py b/cognee/tests/unit/interfaces/graph/get_model_instance_from_graph_test.py deleted file mode 100644 index f1aa7736..00000000 --- a/cognee/tests/unit/interfaces/graph/get_model_instance_from_graph_test.py +++ /dev/null @@ -1,35 +0,0 @@ -from cognee.modules.graph.utils import ( - get_graph_from_model, - get_model_instance_from_graph, -) -from cognee.tests.unit.interfaces.graph.util import run_test_against_ground_truth - -PARSED_PERSON_GROUND_TRUTH = { - "id": "boris", - "name": "Boris", - "age": 30, - "driving_license": { - "issued_by": "PU Vrsac", - "issued_on": "2025-11-06", - "number": "1234567890", - "expires_on": "2025-11-06", - }, -} - -CAR_GROUND_TRUTH = { - "id": "car1", - "brand": "Toyota", - "model": "Camry", - "year": 2020, - "color": "Blue", -} - - -def test_parsed_person(boris): - nodes, edges = get_graph_from_model(boris) - parsed_person = get_model_instance_from_graph(nodes, edges, "boris") - - run_test_against_ground_truth( - "parsed_person", parsed_person, PARSED_PERSON_GROUND_TRUTH - ) - run_test_against_ground_truth("car", parsed_person.owns_car[0], CAR_GROUND_TRUTH) From 57f319fb32c1b271684358cd13706c41f0da33d8 Mon Sep 17 00:00:00 2001 From: hajdul88 <52442977+hajdul88@users.noreply.github.com> Date: Tue, 3 Dec 2024 14:44:49 +0100 Subject: [PATCH 3/3] fix: deletes dummy data of faulty tests --- .../tests/unit/interfaces/graph/conftest.py | 68 -------- cognee/tests/unit/interfaces/graph/util.py | 150 ------------------ 2 files changed, 218 deletions(-) delete mode 100644 cognee/tests/unit/interfaces/graph/conftest.py delete mode 100644 cognee/tests/unit/interfaces/graph/util.py diff --git a/cognee/tests/unit/interfaces/graph/conftest.py b/cognee/tests/unit/interfaces/graph/conftest.py deleted file mode 100644 index 45f977bd..00000000 --- a/cognee/tests/unit/interfaces/graph/conftest.py +++ /dev/null @@ -1,68 +0,0 @@ -from enum import Enum -from typing import Optional - -import pytest - -from cognee.infrastructure.engine import DataPoint - - -class CarTypeName(Enum): - Pickup = "Pickup" - Sedan = "Sedan" - SUV = "SUV" - Coupe = "Coupe" - Convertible = "Convertible" - Hatchback = "Hatchback" - Wagon = "Wagon" - Minivan = "Minivan" - Van = "Van" - - -class CarType(DataPoint): - id: str - name: CarTypeName - _metadata: dict = dict(index_fields=["name"]) - - -class Car(DataPoint): - id: str - brand: str - model: str - year: int - color: str - is_type: CarType - - -class Person(DataPoint): - id: str - name: str - age: int - owns_car: list[Car] - driving_license: Optional[dict] - _metadata: dict = dict(index_fields=["name"]) - - -@pytest.fixture(scope="function") -def boris(): - boris = Person( - id="boris", - name="Boris", - age=30, - owns_car=[ - Car( - id="car1", - brand="Toyota", - model="Camry", - year=2020, - color="Blue", - is_type=CarType(id="sedan", name=CarTypeName.Sedan), - ) - ], - driving_license={ - "issued_by": "PU Vrsac", - "issued_on": "2025-11-06", - "number": "1234567890", - "expires_on": "2025-11-06", - }, - ) - return boris diff --git a/cognee/tests/unit/interfaces/graph/util.py b/cognee/tests/unit/interfaces/graph/util.py deleted file mode 100644 index a20bdb3e..00000000 --- a/cognee/tests/unit/interfaces/graph/util.py +++ /dev/null @@ -1,150 +0,0 @@ -import random -import string -from datetime import datetime, timezone -from typing import Any, Dict, Optional - -from cognee.infrastructure.engine import DataPoint - - -def run_test_against_ground_truth( - test_target_item_name: str, test_target_item: Any, ground_truth_dict: Dict[str, Any] -): - """Validates test target item attributes against ground truth values. - - Args: - test_target_item_name: Name of the item being tested (for error messages) - test_target_item: Object whose attributes are being validated - ground_truth_dict: Dictionary containing expected values - - Raises: - AssertionError: If any attribute doesn't match ground truth or if update timestamp is too old - """ - for key, ground_truth in ground_truth_dict.items(): - if isinstance(ground_truth, dict): - for key2, ground_truth2 in ground_truth.items(): - assert ( - ground_truth2 == getattr(test_target_item, key)[key2] - ), f"{test_target_item_name}/{key = }/{key2 = }: {ground_truth2 = } != {getattr(test_target_item, key)[key2] = }" - elif isinstance(ground_truth, list): - raise NotImplementedError("Currently not implemented for 'list'") - else: - assert ground_truth == getattr( - test_target_item, key - ), f"{test_target_item_name}/{key = }: {ground_truth = } != {getattr(test_target_item, key) = }" - time_delta = datetime.now(timezone.utc) - getattr(test_target_item, "updated_at") - - assert time_delta.total_seconds() < 60, f"{ time_delta.total_seconds() = }" - - -class Organization(DataPoint): - id: str - name: str - members: Optional[list["SocietyPerson"]] - - -class SocietyPerson(DataPoint): - id: str - name: str - memberships: Optional[list[Organization]] - - -SocietyPerson.model_rebuild() -Organization.model_rebuild() - - -ORGANIZATION_NAMES = [ - "ChessClub", - "RowingClub", - "TheatreTroupe", - "PoliticalParty", - "Charity", - "FanClub", - "FilmClub", - "NeighborhoodGroup", - "LocalCouncil", - "Band", -] -PERSON_NAMES = ["Sarah", "Anna", "John", "Sam"] - - -def create_society_person_recursive(id, name, organization_names, max_depth, depth=0): - id_suffix = "".join(random.choice(string.ascii_lowercase) for _ in range(10)) - - if depth < max_depth: - memberships = [ - create_organization_recursive( - f"{org_name}-{depth}-{id_suffix}", - org_name.lower(), - PERSON_NAMES, - max_depth, - depth + 1, - ) - for org_name in organization_names - ] - else: - memberships = None - - return SocietyPerson(id=id, name=f"{name}{depth}", memberships=memberships) - - -def create_organization_recursive(id, name, member_names, max_depth, depth=0): - id_suffix = "".join(random.choice(string.ascii_lowercase) for _ in range(10)) - - if depth < max_depth: - members = [ - create_society_person_recursive( - f"{member_name}-{depth}-{id_suffix}", - member_name.lower(), - ORGANIZATION_NAMES, - max_depth, - depth + 1, - ) - for member_name in member_names - ] - else: - members = None - - return Organization(id=id, name=f"{name}{depth}", members=members) - - -def count_society(obj): - if isinstance(obj, SocietyPerson): - if obj.memberships is not None: - organization_counts, society_person_counts = zip( - *[count_society(organization) for organization in obj.memberships] - ) - organization_count = sum(organization_counts) - society_person_count = sum(society_person_counts) + 1 - return (organization_count, society_person_count) - else: - return (0, 1) - if isinstance(obj, Organization): - if obj.members is not None: - organization_counts, society_person_counts = zip( - *[count_society(organization) for organization in obj.members] - ) - organization_count = sum(organization_counts) + 1 - society_person_count = sum(society_person_counts) - return (organization_count, society_person_count) - else: - return (1, 0) - else: - raise Exception("Not allowed") - - -def show_first_difference(str1, str2, str1_name, str2_name, context=30): - for i, (c1, c2) in enumerate(zip(str1, str2)): - if c1 != c2: - start = max(0, i - context) - end1 = min(len(str1), i + context + 1) - end2 = min(len(str2), i + context + 1) - if i > 0: - return f"identical: '{str1[start:i-1]}' | {str1_name}: '{str1[i-1:end1]}'... != {str2_name}: '{str2[i-1:end2]}'..." - else: - return f"{str1_name} and {str2_name} have no overlap in characters" - if len(str1) > len(str2): - return f"{str2_name} is identical up to the {i}th character, missing afterwards '{str1[i:i+context]}'..." - if len(str2) > len(str1): - return f"{str1_name} is identical up to the {i}th character, missing afterwards '{str2[i:i+context]}'..." - else: - return f"{str1_name} and {str2_name} are identical."