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:
VinvAI
2026-08-24 22:19:03 +05:00
committed by GitHub
co-authored by noQbot Vinv-AI noQbot
parent 58aad80d56
commit 2f63896fb4
9 changed files with 32 additions and 212 deletions
-9
View File
@@ -187,15 +187,6 @@ def poc_vuln3():
}) })
return nodes 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 # Attack payloads
payloads = [ payloads = [
# Header injection payload (chained with VULN-1) # Header injection payload (chained with VULN-1)
@@ -31,6 +31,7 @@ import hashlib
import json import json
import sqlite3 import sqlite3
import threading import threading
import warnings
from abc import ABC, abstractmethod from abc import ABC, abstractmethod
from datetime import datetime from datetime import datetime
from pathlib import Path from pathlib import Path
@@ -62,6 +63,12 @@ def create_graph_snapshot_record(
""" """
Creates a standardized snapshot metadata record for a named graph. 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: Args:
version_id: Unique identifier for this snapshot version_id: Unique identifier for this snapshot
graph_uri: The underlying named graph URI in the triplet store 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 description: Purpose or context of the snapshot
metadata: Additional tags or pipeline context 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 = { record = {
"label": version_id, "label": version_id,
+15
View File
@@ -6,6 +6,7 @@ including node labels, relationship types, and indexes for graph databases.
""" """
import json import json
import warnings
from typing import Dict, Any, List from typing import Dict, Any, List
from ..graph_store import GraphStore from ..graph_store import GraphStore
@@ -460,11 +461,25 @@ def drop_decision_schema(graph_store: GraphStore) -> None:
""" """
Drop decision tracking schema (for cleanup/testing). 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: Args:
graph_store: Graph database instance graph_store: Graph database instance
""" """
logger = get_logger(__name__) 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: try:
# Drop constraints # Drop constraints
constraints = [ constraints = [
+3 -13
View File
@@ -2,8 +2,9 @@
Semantica Explorer : FastAPI Dependencies Semantica Explorer : FastAPI Dependencies
Provides ``Depends()``-compatible callables for injecting the Provides ``Depends()``-compatible callables for injecting the
current ``GraphSession`` and ``ConnectionManager`` into route handlers, current ``GraphSession`` into route handlers, and for enforcing API-key
and for enforcing API-key authentication on protected routes. authentication on protected routes. WebSocket manager access is handled
directly via ``app.state.ws_manager``.
""" """
import hmac import hmac
@@ -14,7 +15,6 @@ from fastapi import Request, HTTPException, Security, status
from fastapi.security.api_key import APIKeyHeader from fastapi.security.api_key import APIKeyHeader
from .session import GraphSession from .session import GraphSession
from .ws import ConnectionManager
_api_key_header = APIKeyHeader(name="X-API-Key", auto_error=False) _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." detail="GraphSession not initialized."
) )
return request.app.state.session 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
-60
View File
@@ -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 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]]: def _get_cached_embeddings(session: GraphSession) -> dict[str, List[float]]:
"""Get embeddings from session cache for optimal performance.""" """Get embeddings from session cache for optimal performance."""
return session.get_cached_embeddings() return session.get_cached_embeddings()
-4
View File
@@ -456,10 +456,6 @@ class DraftResponse(BaseModel):
updated_at: str updated_at: str
class ProposalState(BaseModel):
state: Literal["draft", "proposed", "approved", "published", "rejected"]
class ProposalRequest(BaseModel): class ProposalRequest(BaseModel):
draft_id: str draft_id: str
ontology_uri: str ontology_uri: str
-23
View File
@@ -8,11 +8,6 @@ from typing import Any, Dict, List, Literal, Optional, Tuple
from pydantic import BaseModel, Field, field_validator from pydantic import BaseModel, Field, field_validator
class ErrorResponse(BaseModel):
detail: str
status_code: int = 500
class NodeResponse(BaseModel): class NodeResponse(BaseModel):
id: str id: str
type: str type: str
@@ -187,12 +182,6 @@ class ComplianceResponse(BaseModel):
violations: List[Dict[str, Any]] = Field(default_factory=list) 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): class TemporalDiffResponse(BaseModel):
from_time: str from_time: str
to_time: str to_time: str
@@ -256,13 +245,6 @@ class ExportRequest(BaseModel):
node_ids: Optional[List[str]] = None node_ids: Optional[List[str]] = None
class ExportResponse(BaseModel):
format: str
content_type: str
filename: str
size_bytes: int = 0
class ImportResponse(BaseModel): class ImportResponse(BaseModel):
status: str = "success" status: str = "success"
message: str = "Import successful" message: str = "Import successful"
@@ -272,11 +254,6 @@ class ImportResponse(BaseModel):
edges_imported: Optional[int] = None edges_imported: Optional[int] = None
class StandardMessageResponse(BaseModel):
status: str
message: str
class AnnotationCreate(BaseModel): class AnnotationCreate(BaseModel):
node_id: str node_id: str
content: str content: str
-83
View File
@@ -1124,47 +1124,6 @@ Text to extract from:
return [] 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( def _extract_entities_chunked(
text: str, text: str,
provider: str, provider: str,
@@ -2559,48 +2518,6 @@ Text to extract from:
return [] 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( def _extract_triplets_chunked(
text: str, text: str,
provider: str, provider: str,
-20
View File
@@ -101,7 +101,6 @@ from .triplet_store import TripletStore
# Global store registry # Global store registry
_global_stores: Dict[str, TripletStore] = {} _global_stores: Dict[str, TripletStore] = {}
_default_store_id: Optional[str] = None _default_store_id: Optional[str] = None
_global_query_engine: Optional[QueryEngine] = None
_global_bulk_loader: Optional[BulkLoader] = 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] 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: def _get_bulk_loader() -> BulkLoader:
"""Get or create global BulkLoader instance.""" """Get or create global BulkLoader instance."""
global _global_bulk_loader global _global_bulk_loader