项目文件夹

文件
wehub-resource-sync c889a57b6b
Test Suites / Build CI Environment (push) Has been cancelled
Test Suites / Basic Tests (push) Has been cancelled
Test Suites / End-to-End Tests (push) Has been cancelled
Test Suites / CLI Tests (push) Has been cancelled
Test Suites / Slow End-to-End Tests (push) Has been cancelled
Test Suites / Graph Database Tests (push) Has been cancelled
Test Suites / Vector DB Tests (push) Has been cancelled
Test Suites / Temporal Graph Test (push) Has been cancelled
Test Suites / Search Test on Different DBs (push) Has been cancelled
Test Suites / Example Tests (push) Has been cancelled
Test Suites / Notebook Tests (push) Has been cancelled
Test Suites / OS and Python Tests Ubuntu (push) Has been cancelled
Test Suites / OS and Python Tests Extended (push) Has been cancelled
Test Suites / LLM Test Suite (push) Has been cancelled
Test Suites / S3 File Storage Test (push) Has been cancelled
Test Suites / Run Integration Tests (push) Has been cancelled
Test Suites / MCP Tests (push) Has been cancelled
Test Suites / Docker Compose Test (push) Has been cancelled
Test Suites / Docker CI test (push) Has been cancelled
Test Suites / Relational DB Migration Tests (push) Has been cancelled
Test Suites / Distributed Cognee Test (push) Has been cancelled
Test Suites / DB Examples Tests (push) Has been cancelled
Test Suites / Test Completion Status (push) Has been cancelled
Test Suites / Claude Code Review (push) Has been cancelled
Test Suites / basic checks (push) Has been cancelled
build | Build and Push Cognee MCP Docker Image to dockerhub / docker-build-and-push (push) Has been cancelled
Scorecard supply-chain security / Scorecard analysis (push) Has been cancelled
build | Build and Push Docker Image to dockerhub / docker-build-and-push (push) Has been cancelled
Weighted Edges Tests / Test Weighted Edges Core Functionality (3.11) (push) Has been cancelled
Weighted Edges Tests / Test Weighted Edges Core Functionality (3.12) (push) Has been cancelled
Weighted Edges Tests / Test Weighted Edges with Different Graph Databases (kuzu, kuzu) (push) Has been cancelled
Weighted Edges Tests / Test Weighted Edges with Different Graph Databases (neo4j, neo4j) (push) Has been cancelled
Weighted Edges Tests / Test Weighted Edges Examples (push) Has been cancelled
Weighted Edges Tests / Code Quality for Weighted Edges (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:02:24 +08:00

232 行
7.8 KiB
Python

import logging
from uuid import UUID, uuid4
from cognee.infrastructure.engine.models.DataPoint import DataPoint
class PersonWithIdentity(DataPoint):
name: str
metadata: dict = {"index_fields": ["name"], "identity_fields": ["name"]}
class DepartmentWithIdentity(DataPoint):
name: str
metadata: dict = {"index_fields": ["name"], "identity_fields": ["name"]}
class MultiFieldIdentity(DataPoint):
first_name: str
last_name: str
metadata: dict = {
"index_fields": ["first_name"],
"identity_fields": ["first_name", "last_name"],
}
class NoIdentityFields(DataPoint):
name: str
metadata: dict = {"index_fields": ["name"]}
class PartialIdentity(DataPoint):
name: str
age: int = 0
metadata: dict = {"index_fields": ["name"], "identity_fields": ["name", "age"]}
class TestSameValuesSameUUID:
def test_same_name_produces_same_id(self):
p1 = PersonWithIdentity(name="John")
p2 = PersonWithIdentity(name="John")
assert p1.id == p2.id
def test_deterministic_across_calls(self):
ids = [PersonWithIdentity(name="Alice").id for _ in range(10)]
assert len(set(ids)) == 1
class TestDifferentValuesDifferentUUID:
def test_different_names_produce_different_ids(self):
p1 = PersonWithIdentity(name="John")
p2 = PersonWithIdentity(name="Jane")
assert p1.id != p2.id
class TestCrossTypeSafety:
def test_same_name_different_class_different_id(self):
person = PersonWithIdentity(name="Engineering")
department = DepartmentWithIdentity(name="Engineering")
assert person.id != department.id
class TestExplicitIdOverride:
def test_explicit_id_takes_precedence(self):
explicit_id = uuid4()
p = PersonWithIdentity(id=explicit_id, name="John")
assert p.id == explicit_id
def test_explicit_id_differs_from_generated(self):
explicit_id = uuid4()
p_explicit = PersonWithIdentity(id=explicit_id, name="John")
p_generated = PersonWithIdentity(name="John")
assert p_explicit.id != p_generated.id
class TestDefaultFieldsIncludedInIdentity:
def test_default_field_included_in_identity(self):
"""Fields with defaults are available via model_dump() and produce deterministic IDs."""
p1 = PartialIdentity(name="John")
p2 = PartialIdentity(name="John")
assert p1.id == p2.id
assert p1.id.version == 5
def test_different_default_override_produces_different_id(self):
p1 = PartialIdentity(name="John", age=25)
p2 = PartialIdentity(name="John", age=30)
assert p1.id != p2.id
def test_truly_missing_field(self):
"""A class where identity_fields references a non-existent field."""
class BadIdentity(DataPoint):
name: str
metadata: dict = {
"index_fields": ["name"],
"identity_fields": ["name", "nonexistent"],
}
b1 = BadIdentity(name="John")
b2 = BadIdentity(name="John")
# nonexistent is not in model_dump(), so falls back to UUID4 - different each time
assert b1.id != b2.id
class TestNoIdentityFieldsBackwardCompat:
def test_no_identity_fields_produces_random_uuid(self):
n1 = NoIdentityFields(name="John")
n2 = NoIdentityFields(name="John")
assert n1.id != n2.id
def test_base_datapoint_no_identity_fields(self):
dp1 = DataPoint()
dp2 = DataPoint()
assert dp1.id != dp2.id
class TestMultiFieldIdentity:
def test_same_multi_fields_same_id(self):
m1 = MultiFieldIdentity(first_name="John", last_name="Doe")
m2 = MultiFieldIdentity(first_name="John", last_name="Doe")
assert m1.id == m2.id
def test_different_multi_fields_different_id(self):
m1 = MultiFieldIdentity(first_name="John", last_name="Doe")
m2 = MultiFieldIdentity(first_name="John", last_name="Smith")
assert m1.id != m2.id
def test_field_order_matters(self):
"""first_name='A', last_name='B' should differ from first_name='B', last_name='A'."""
m1 = MultiFieldIdentity(first_name="A", last_name="B")
m2 = MultiFieldIdentity(first_name="B", last_name="A")
assert m1.id != m2.id
class TestStringNormalization:
def test_case_insensitive(self):
p1 = PersonWithIdentity(name="John")
p2 = PersonWithIdentity(name="JOHN")
assert p1.id == p2.id
def test_spaces_normalized(self):
p1 = PersonWithIdentity(name="John Doe")
p2 = PersonWithIdentity(name="John_Doe")
assert p1.id == p2.id
def test_apostrophes_removed(self):
p1 = PersonWithIdentity(name="O'Brien")
p2 = PersonWithIdentity(name="OBrien")
assert p1.id == p2.id
class TestIdIsUUID5:
def test_generated_id_is_valid_uuid(self):
p = PersonWithIdentity(name="Test")
assert isinstance(p.id, UUID)
# UUID5 has version == 5
assert p.id.version == 5
def test_no_identity_id_is_uuid4(self):
n = NoIdentityFields(name="Test")
assert isinstance(n.id, UUID)
assert n.id.version == 4
class TestInheritanceWarning:
def test_subclass_dropping_identity_fields_logs_warning(self, caplog):
"""Subclass that overrides metadata without identity_fields triggers a warning."""
class Parent(DataPoint):
name: str
metadata: dict = {"index_fields": ["name"], "identity_fields": ["name"]}
class Child(Parent):
name: str
metadata: dict = {"index_fields": ["name"]} # forgot identity_fields
with caplog.at_level(logging.WARNING):
c = Child(name="Test")
assert "drops identity_fields" in caplog.text
# Should fall back to UUID4 since no identity_fields on Child
assert c.id.version == 4
class TestIdForMatchesIdentityFields:
"""id_for(...) and the identity_fields-derived instance id must be the SAME
value — they share one implementation (id_for) precisely so they cannot drift.
"""
def test_id_for_matches_single_field_instance(self):
assert PersonWithIdentity.id_for("John") == PersonWithIdentity(name="John").id
def test_id_for_matches_after_normalization(self):
assert PersonWithIdentity.id_for("John Doe") == PersonWithIdentity(name="John_Doe").id
def test_id_for_matches_multi_field_in_declaration_order(self):
assert (
MultiFieldIdentity.id_for("John", "Doe")
== MultiFieldIdentity(first_name="John", last_name="Doe").id
)
def test_id_for_namespaced_by_class(self):
# Same input, different classes -> different ids (class supplies the namespace).
assert PersonWithIdentity.id_for("Engineering") != DepartmentWithIdentity.id_for(
"Engineering"
)
class TestNormalizationMatchesGenerateNodeId:
"""The identity normalization must stay byte-for-byte aligned with the legacy
``generate_node_id`` normalization, otherwise the graph id migration can no
longer recompute historical ids from a node's stored name.
"""
def test_normalization_equivalence(self):
from uuid import NAMESPACE_OID, uuid5
from cognee.infrastructure.engine.utils.generate_node_id import generate_node_id
for raw in ["John", "John Doe", "O'Brien", "New York City", "ALL CAPS", "mixed Case's"]:
normalized = DataPoint._normalize_identity_value(raw)
# generate_node_id hashes the bare normalized value (no class prefix).
assert generate_node_id(raw) == uuid5(NAMESPACE_OID, normalized)
class TestTypeFieldPreserved:
def test_type_is_class_name(self):
p = PersonWithIdentity(name="John")
assert p.type == "PersonWithIdentity"
def test_type_not_affected_by_identity_fields(self):
n = NoIdentityFields(name="John")
assert n.type == "NoIdentityFields"