mirror of
https://github.com/semantica-agi/semantica.git
synced 2026-08-29 04:26:20 +00:00
Remove unreachable dead code (#1176)
* Remove unreachable dead code Delete symbols with no callers anywhere in the codebase, tests, or docs, confirmed by a repo-wide search. These are internal/private or app-layer (explorer) symbols, not part of the importable library's public API (no __all__ / package re-export), so there is no user-facing change. Removed: - poc_runner.py: parse_import_csv_row (unused nested helper) - change_management/version_storage.py: create_graph_snapshot_record - context/graph_schema.py: drop_decision_schema - explorer/dependencies.py: get_ws_manager (+ now-unused ConnectionManager import) - explorer/routes/graph.py: _extract_node_embeddings (+ stale cross-ref comment) - explorer/routes/ontology.py: ProposalState - explorer/schemas.py: ErrorResponse, TemporalSnapshotResponse, ExportResponse, StandardMessageResponse - semantic_extract/methods.py: _parse_entity_result, _parse_triplet_result - triplet_store/methods.py: _get_query_engine (+ now-unused _global_query_engine) Co-Authored-By: Vinv-AI <309466812+Vinv-AI@users.noreply.github.com> * Address review: drop now-orphaned helper and fix stale docstring - Remove _coerce_embedding_vector from explorer/routes/graph.py: its only non-recursive caller was _extract_node_embeddings (removed in this PR), so it is now dead. The live coercion logic lives in GraphSession._coerce_embedding_vector. - Update explorer/dependencies.py module docstring: it no longer injects ConnectionManager (get_ws_manager was removed); note that websocket manager access is via app.state.ws_manager. Co-Authored-By: Vinv-AI <309466812+Vinv-AI@users.noreply.github.com> * Keep public helpers with a DeprecationWarning instead of removing them create_graph_snapshot_record() and drop_decision_schema() are not underscore-prefixed, so downstream users can import them directly from their modules even though they are not re-exported from the package __init__.py. A repo search only proves there are no in-tree callers. Restore both unchanged and emit a DeprecationWarning on call, with a matching ".. deprecated::" note in each docstring pointing at the replacement. This keeps the PR non-breaking; the actual removal can happen in a future major version. The underscore-prefixed helper removals are unaffected. --------- Co-authored-by: noQbot <noQbot@users.noreply.github.com> Co-authored-by: Vinv-AI <309466812+Vinv-AI@users.noreply.github.com> Co-authored-by: noQbot <anshul@vinv.ai>
This commit is contained in:
co-authored by
noQbot
Vinv-AI
noQbot
parent
58aad80d56
commit
2f63896fb4
@@ -187,15 +187,6 @@ def poc_vuln3():
|
||||
})
|
||||
return nodes
|
||||
|
||||
# Simulate the CSV parser — mirrors export_import.py lines 131-133
|
||||
def parse_import_csv_row(row: dict) -> dict:
|
||||
"""Mirrors export_import.py CSV node ID extraction (no sanitization)."""
|
||||
node_id = row.get("id") or row.get("node_id") or row.get(":ID") or row.get("_id")
|
||||
return {
|
||||
"id": str(node_id), # ← UNSANITIZED
|
||||
"type": row.get("type", "entity"),
|
||||
}
|
||||
|
||||
# Attack payloads
|
||||
payloads = [
|
||||
# Header injection payload (chained with VULN-1)
|
||||
|
||||
@@ -31,6 +31,7 @@ import hashlib
|
||||
import json
|
||||
import sqlite3
|
||||
import threading
|
||||
import warnings
|
||||
from abc import ABC, abstractmethod
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
@@ -62,6 +63,12 @@ def create_graph_snapshot_record(
|
||||
"""
|
||||
Creates a standardized snapshot metadata record for a named graph.
|
||||
|
||||
.. deprecated::
|
||||
``create_graph_snapshot_record()`` is deprecated and will be removed in
|
||||
a future major version. It has no callers inside Semantica; build the
|
||||
record inline and checksum it with
|
||||
:func:`semantica.change_management.compute_checksum` instead.
|
||||
|
||||
Args:
|
||||
version_id: Unique identifier for this snapshot
|
||||
graph_uri: The underlying named graph URI in the triplet store
|
||||
@@ -69,6 +76,13 @@ def create_graph_snapshot_record(
|
||||
description: Purpose or context of the snapshot
|
||||
metadata: Additional tags or pipeline context
|
||||
"""
|
||||
warnings.warn(
|
||||
"create_graph_snapshot_record() is deprecated and will be removed in a "
|
||||
"future major version. Build the snapshot record inline and use "
|
||||
"semantica.change_management.compute_checksum() instead.",
|
||||
DeprecationWarning,
|
||||
stacklevel=2,
|
||||
)
|
||||
|
||||
record = {
|
||||
"label": version_id,
|
||||
|
||||
@@ -6,6 +6,7 @@ including node labels, relationship types, and indexes for graph databases.
|
||||
"""
|
||||
|
||||
import json
|
||||
import warnings
|
||||
from typing import Dict, Any, List
|
||||
|
||||
from ..graph_store import GraphStore
|
||||
@@ -460,11 +461,25 @@ def drop_decision_schema(graph_store: GraphStore) -> None:
|
||||
"""
|
||||
Drop decision tracking schema (for cleanup/testing).
|
||||
|
||||
.. deprecated::
|
||||
``drop_decision_schema()`` is deprecated and will be removed in a future
|
||||
major version. It has no callers inside Semantica; issue the DROP
|
||||
CONSTRAINT / DROP INDEX / DETACH DELETE statements directly against your
|
||||
:class:`~semantica.graph_store.GraphStore` instead.
|
||||
|
||||
Args:
|
||||
graph_store: Graph database instance
|
||||
"""
|
||||
logger = get_logger(__name__)
|
||||
|
||||
warnings.warn(
|
||||
"drop_decision_schema() is deprecated and will be removed in a future "
|
||||
"major version. Issue the DROP CONSTRAINT / DROP INDEX / DETACH DELETE "
|
||||
"statements directly against your GraphStore instead.",
|
||||
DeprecationWarning,
|
||||
stacklevel=2,
|
||||
)
|
||||
|
||||
try:
|
||||
# Drop constraints
|
||||
constraints = [
|
||||
|
||||
@@ -2,8 +2,9 @@
|
||||
Semantica Explorer : FastAPI Dependencies
|
||||
|
||||
Provides ``Depends()``-compatible callables for injecting the
|
||||
current ``GraphSession`` and ``ConnectionManager`` into route handlers,
|
||||
and for enforcing API-key authentication on protected routes.
|
||||
current ``GraphSession`` into route handlers, and for enforcing API-key
|
||||
authentication on protected routes. WebSocket manager access is handled
|
||||
directly via ``app.state.ws_manager``.
|
||||
"""
|
||||
|
||||
import hmac
|
||||
@@ -14,7 +15,6 @@ from fastapi import Request, HTTPException, Security, status
|
||||
from fastapi.security.api_key import APIKeyHeader
|
||||
|
||||
from .session import GraphSession
|
||||
from .ws import ConnectionManager
|
||||
|
||||
_api_key_header = APIKeyHeader(name="X-API-Key", auto_error=False)
|
||||
|
||||
@@ -80,13 +80,3 @@ def get_session(request: Request) -> GraphSession:
|
||||
detail="GraphSession not initialized."
|
||||
)
|
||||
return request.app.state.session
|
||||
|
||||
|
||||
def get_ws_manager(request: Request) -> ConnectionManager:
|
||||
"""Retrieve the ConnectionManager stored on ``app.state``."""
|
||||
if not hasattr(request.app.state, "ws_manager") or request.app.state.ws_manager is None:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
|
||||
detail="WebSocket manager not initialized.",
|
||||
)
|
||||
return request.app.state.ws_manager
|
||||
|
||||
@@ -78,66 +78,6 @@ def _parse_bbox(raw_bbox: Optional[str]) -> Optional[tuple[float, float, float,
|
||||
return min_x, min_y, max_x, max_y
|
||||
|
||||
|
||||
def _coerce_embedding_vector(value: object) -> Optional[List[float]]:
|
||||
if isinstance(value, dict):
|
||||
# Probe keys in priority order: generic first, then framework-specific.
|
||||
# Must stay aligned with the top-level keys in _extract_node_embeddings.
|
||||
for key in ("embedding", "embeddings", "vector", "values", "node2vec", "semantic"):
|
||||
nested = _coerce_embedding_vector(value.get(key))
|
||||
if nested is not None:
|
||||
return nested
|
||||
return None
|
||||
|
||||
if not isinstance(value, (list, tuple)):
|
||||
return None
|
||||
|
||||
vector: List[float] = []
|
||||
for item in value:
|
||||
try:
|
||||
vector.append(float(item))
|
||||
except (TypeError, ValueError):
|
||||
return None
|
||||
|
||||
return vector if vector else None
|
||||
|
||||
|
||||
def _extract_node_embeddings(graph_dict: dict) -> dict[str, List[float]]:
|
||||
"""Extract embeddings from graph dictionary."""
|
||||
# Top-level keys to probe on each entity (and its metadata/properties dicts).
|
||||
# Priority: generic names first, then KG-extras-specific names.
|
||||
# Must stay aligned with the inner probe list in _coerce_embedding_vector.
|
||||
embedding_keys = (
|
||||
"embedding",
|
||||
"embeddings",
|
||||
"vector",
|
||||
"node_embedding",
|
||||
"node2vec_embedding",
|
||||
"semantic_embedding",
|
||||
"reasoning_embedding",
|
||||
)
|
||||
|
||||
embeddings: dict[str, List[float]] = {}
|
||||
for entity in graph_dict.get("entities") or graph_dict.get("nodes") or []:
|
||||
if not isinstance(entity, dict):
|
||||
continue
|
||||
node_id = entity.get("id") or entity.get("node_id")
|
||||
if not node_id:
|
||||
continue
|
||||
|
||||
metadata = entity.get("metadata") if isinstance(entity.get("metadata"), dict) else {}
|
||||
properties = entity.get("properties") if isinstance(entity.get("properties"), dict) else {}
|
||||
|
||||
for key in embedding_keys:
|
||||
vector = _coerce_embedding_vector(
|
||||
entity.get(key, metadata.get(key, properties.get(key)))
|
||||
)
|
||||
if vector is not None:
|
||||
embeddings[str(node_id)] = vector
|
||||
break
|
||||
|
||||
return embeddings
|
||||
|
||||
|
||||
def _get_cached_embeddings(session: GraphSession) -> dict[str, List[float]]:
|
||||
"""Get embeddings from session cache for optimal performance."""
|
||||
return session.get_cached_embeddings()
|
||||
|
||||
@@ -456,10 +456,6 @@ class DraftResponse(BaseModel):
|
||||
updated_at: str
|
||||
|
||||
|
||||
class ProposalState(BaseModel):
|
||||
state: Literal["draft", "proposed", "approved", "published", "rejected"]
|
||||
|
||||
|
||||
class ProposalRequest(BaseModel):
|
||||
draft_id: str
|
||||
ontology_uri: str
|
||||
|
||||
@@ -8,11 +8,6 @@ from typing import Any, Dict, List, Literal, Optional, Tuple
|
||||
from pydantic import BaseModel, Field, field_validator
|
||||
|
||||
|
||||
class ErrorResponse(BaseModel):
|
||||
detail: str
|
||||
status_code: int = 500
|
||||
|
||||
|
||||
class NodeResponse(BaseModel):
|
||||
id: str
|
||||
type: str
|
||||
@@ -187,12 +182,6 @@ class ComplianceResponse(BaseModel):
|
||||
violations: List[Dict[str, Any]] = Field(default_factory=list)
|
||||
|
||||
|
||||
class TemporalSnapshotResponse(BaseModel):
|
||||
timestamp: str
|
||||
active_nodes: List[NodeResponse]
|
||||
active_node_count: int
|
||||
|
||||
|
||||
class TemporalDiffResponse(BaseModel):
|
||||
from_time: str
|
||||
to_time: str
|
||||
@@ -256,13 +245,6 @@ class ExportRequest(BaseModel):
|
||||
node_ids: Optional[List[str]] = None
|
||||
|
||||
|
||||
class ExportResponse(BaseModel):
|
||||
format: str
|
||||
content_type: str
|
||||
filename: str
|
||||
size_bytes: int = 0
|
||||
|
||||
|
||||
class ImportResponse(BaseModel):
|
||||
status: str = "success"
|
||||
message: str = "Import successful"
|
||||
@@ -272,11 +254,6 @@ class ImportResponse(BaseModel):
|
||||
edges_imported: Optional[int] = None
|
||||
|
||||
|
||||
class StandardMessageResponse(BaseModel):
|
||||
status: str
|
||||
message: str
|
||||
|
||||
|
||||
class AnnotationCreate(BaseModel):
|
||||
node_id: str
|
||||
content: str
|
||||
|
||||
@@ -1124,47 +1124,6 @@ Text to extract from:
|
||||
return []
|
||||
|
||||
|
||||
def _parse_entity_result(result: Any, provider: str, model: Optional[str]) -> List[Entity]:
|
||||
"""Helper to parse raw LLM result into Entity objects."""
|
||||
entities = []
|
||||
items = []
|
||||
|
||||
if isinstance(result, list):
|
||||
items = result
|
||||
elif isinstance(result, dict):
|
||||
# Handle cases where LLM wraps the list in a key
|
||||
for key in ["entities", "data", "results"]:
|
||||
if key in result and isinstance(result[key], list):
|
||||
items = result[key]
|
||||
break
|
||||
if not items and "text" in result: # Single object instead of list
|
||||
items = [result]
|
||||
|
||||
for item in items:
|
||||
if not isinstance(item, dict):
|
||||
continue
|
||||
|
||||
text = item.get("text", "")
|
||||
if not text:
|
||||
continue
|
||||
|
||||
entities.append(
|
||||
Entity(
|
||||
text=text,
|
||||
label=item.get("label", "UNKNOWN"),
|
||||
start_char=item.get("start", 0),
|
||||
end_char=item.get("end", 0),
|
||||
confidence=item.get("confidence", 0.9),
|
||||
metadata={
|
||||
"provider": provider,
|
||||
"model": model,
|
||||
"extraction_method": "llm",
|
||||
},
|
||||
)
|
||||
)
|
||||
return entities
|
||||
|
||||
|
||||
def _extract_entities_chunked(
|
||||
text: str,
|
||||
provider: str,
|
||||
@@ -2559,48 +2518,6 @@ Text to extract from:
|
||||
return []
|
||||
|
||||
|
||||
def _parse_triplet_result(result: Any, provider: str, model: Optional[str]) -> List[Triplet]:
|
||||
"""Helper to parse raw LLM result into Triplet objects."""
|
||||
triplets = []
|
||||
items = []
|
||||
|
||||
if isinstance(result, list):
|
||||
items = result
|
||||
elif isinstance(result, dict):
|
||||
for key in ["triplets", "data", "results"]:
|
||||
if key in result and isinstance(result[key], list):
|
||||
items = result[key]
|
||||
break
|
||||
if not items and "subject" in result:
|
||||
items = [result]
|
||||
|
||||
for item in items:
|
||||
if not isinstance(item, dict):
|
||||
continue
|
||||
|
||||
subject = item.get("subject", "")
|
||||
predicate = item.get("predicate", "")
|
||||
obj = item.get("object", "")
|
||||
|
||||
if not subject or not predicate or not obj:
|
||||
continue
|
||||
|
||||
triplets.append(
|
||||
Triplet(
|
||||
subject=str(subject),
|
||||
predicate=str(predicate),
|
||||
object=str(obj),
|
||||
confidence=item.get("confidence", 0.9),
|
||||
metadata={
|
||||
"provider": provider,
|
||||
"model": model,
|
||||
"extraction_method": "llm",
|
||||
},
|
||||
)
|
||||
)
|
||||
return triplets
|
||||
|
||||
|
||||
def _extract_triplets_chunked(
|
||||
text: str,
|
||||
provider: str,
|
||||
|
||||
@@ -101,7 +101,6 @@ from .triplet_store import TripletStore
|
||||
# Global store registry
|
||||
_global_stores: Dict[str, TripletStore] = {}
|
||||
_default_store_id: Optional[str] = None
|
||||
_global_query_engine: Optional[QueryEngine] = None
|
||||
_global_bulk_loader: Optional[BulkLoader] = None
|
||||
|
||||
|
||||
@@ -131,25 +130,6 @@ def _get_store(store_id: Optional[str] = None) -> TripletStore:
|
||||
return _global_stores[target_id]
|
||||
|
||||
|
||||
def _get_query_engine() -> QueryEngine:
|
||||
"""Get or create global QueryEngine instance."""
|
||||
global _global_query_engine
|
||||
if _global_query_engine is None:
|
||||
# We need a store backend for the engine, but QueryEngine in this module
|
||||
# seems to be initialized with config in the old code.
|
||||
# In the new code, TripletStore has its own query_engine.
|
||||
# If we use this standalone function, we might need to rely on the store's engine.
|
||||
# But let's keep a standalone one if needed, or better, delegate to store.
|
||||
config = triplet_store_config.get_all()
|
||||
# QueryEngine now expects a backend, but we can initialize it without one
|
||||
# if we pass the backend at execution time?
|
||||
# Checking QueryEngine implementation... it takes `store_backend` in __init__.
|
||||
# So we can't easily have a global one without a store.
|
||||
# We'll rely on the store's engine.
|
||||
pass
|
||||
return None # Deprecated use of global engine
|
||||
|
||||
|
||||
def _get_bulk_loader() -> BulkLoader:
|
||||
"""Get or create global BulkLoader instance."""
|
||||
global _global_bulk_loader
|
||||
|
||||
Reference in New Issue
Block a user