Merge pull request #539 from Hawksight-AI/conflicts

fix(conflicts): consolidate duplicate detect_conflicts into single di…
This commit is contained in:
Mohd Kaif
2026-05-05 18:17:19 +05:30
committed by GitHub
2 changed files with 43 additions and 53 deletions
+7
View File
@@ -57,6 +57,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Fixed
- **Fix: `ConflictDetector.detect_conflicts()` raises `AttributeError` when called with `method=` or `property_name=` kwargs** (issue #533, PR conflicts, by @KaifAhmad1):
- `detect_conflicts` was defined twice in `conflict_detector.py`; Python silently overwrote the first (dispatcher) definition with the second (comprehensive), which accepted no `method` or `property_name` parameters — causing `AttributeError` or `TypeError` for any caller using those kwargs.
- Removed the first (dead) definition and merged its dispatcher logic into the surviving method. New signature: `detect_conflicts(entities, method="all", property_name=None, entity_type=None, **kwargs)`.
- Supported `method` values: `"all"` (default, comprehensive), `"value"`, `"property"`, `"type"`, `"relationship"`, `"temporal"`, `"logical"`, `"entity"`. Unknown values raise `ValueError`.
- Fixed `method="relationship"` silently defaulting `relationships` to the entities list, which caused entity dicts to be iterated as relationship dicts producing silent wrong results (`None_None_None` keys). Now defaults to `[]` with dict normalization.
- Removed unreachable dead code (`for field_name in fields_to_check` loop after `try/except raise`) in `detect_entity_conflicts`.
- **Fix: `semantica[all]` installation fails on Windows due to `faiss-gpu` dependency** (issue #532, PR #utlis, by @KaifAhmad1):
- `[all]` bundled the `[gpu]` extra (`faiss-gpu>=1.7.0`, `cupy>=10.0.0`), which has no Windows builds, causing `pip install "semantica[all]"` to fail with `No matching distribution found for faiss-gpu>=1.7.0`.
- Removed `gpu` from both `[all]` lines in `pyproject.toml``[all]` now installs only cross-platform dependencies. Users on Linux who need GPU acceleration can install `semantica[gpu]` explicitly.
+36 -53
View File
@@ -133,48 +133,6 @@ class ConflictDetector:
self.detected_conflicts: Dict[str, Conflict] = {}
def detect_conflicts(
self,
entities: Union[List[Dict[str, Any]], Dict[str, Any]],
method: str = "entity",
property_name: Optional[str] = None,
entity_type: Optional[str] = None,
**kwargs,
) -> List[Conflict]:
"""
Detect conflicts using the specified method (convenience method).
Args:
entities: Entities to check (List of dicts or a KG dict)
method: Detection method ("entity", "value", "type", "relationship", "temporal", "logical")
property_name: Property name for "value" method
entity_type: Optional entity type filter
**kwargs: Additional arguments
Returns:
List of detected conflicts
"""
# If passed a KG dict, extract entities
if isinstance(entities, dict) and "entities" in entities:
entities = entities["entities"]
if method == "value":
if not property_name:
raise ValueError("property_name is required for value conflict detection")
return self.detect_value_conflicts(entities, property_name, entity_type)
elif method == "type":
return self.detect_type_conflicts(entities)
elif method == "relationship":
relationships = kwargs.get("relationships", [])
return self.detect_relationship_conflicts(relationships)
elif method == "temporal":
return self.detect_temporal_conflicts(entities)
elif method == "logical":
return self.detect_logical_conflicts(entities)
else:
# Default to entity-wide detection
return self.detect_entity_conflicts(entities, entity_type)
def detect_value_conflicts(
self,
entities: Union[List[Dict[str, Any]], Dict[str, Any]],
@@ -596,11 +554,6 @@ class ConflictDetector:
tracking_id, status="failed", message=str(e)
)
raise
for field_name in fields_to_check:
conflicts = self.detect_value_conflicts(entities, field_name, entity_type)
all_conflicts.extend(conflicts)
return all_conflicts
def _calculate_conflict_confidence(
self, values: List[Any], sources: List[Dict[str, Any]]
@@ -1252,20 +1205,25 @@ class ConflictDetector:
def detect_conflicts(
self,
entities: Union[List[Dict[str, Any]], Dict[str, Any]],
method: str = "all",
property_name: Optional[str] = None,
entity_type: Optional[str] = None,
**kwargs,
) -> List[Conflict]:
"""
Detect all conflicts for entities (general method).
This method detects all types of conflicts: value, type, relationship,
temporal, and logical conflicts.
Detect conflicts using the specified method.
Args:
entities: List of entity dictionaries or Graph dictionary (containing "entities" key)
entities: List of entity dictionaries or Graph dictionary
method: Detection method — "all" (default), "value", "property", "type",
"relationship", "temporal", "logical", or "entity"
property_name: Property name required for ``method="value"`` and ``method="property"``
entity_type: Optional entity type filter
**kwargs: Extra arguments forwarded to the underlying method
(e.g. ``relationships=`` for ``method="relationship"``)
Returns:
List of all detected conflicts
List of detected conflicts
"""
# Handle graph dictionary input
if isinstance(entities, dict):
@@ -1275,6 +1233,31 @@ class ConflictDetector:
# If it's a single entity dict, wrap in list
entities = [entities]
# Dispatch to a specific sub-method when one is requested
if method == "value":
if not property_name:
raise ValueError("property_name is required for method='value'")
return self.detect_value_conflicts(entities, property_name, entity_type)
elif method == "property":
if not property_name:
raise ValueError("property_name is required for method='property'")
return self.detect_property_conflicts(entities, property_name)
elif method == "type":
return self.detect_type_conflicts(entities)
elif method == "relationship":
relationships = kwargs.get("relationships", [])
if isinstance(relationships, dict):
relationships = relationships.get("relationships", [relationships])
return self.detect_relationship_conflicts(relationships)
elif method == "temporal":
return self.detect_temporal_conflicts(entities)
elif method == "logical":
return self.detect_logical_conflicts(entities)
elif method == "entity":
return self.detect_entity_conflicts(entities, entity_type)
elif method != "all":
raise ValueError(f"Unknown conflict detection method: {method!r}")
tracking_id = self.progress_tracker.start_tracking(
file=None,
module="conflicts",