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
# 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,
+15
View File
@@ -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 = [
+3 -13
View File
@@ -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
-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
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()
-4
View File
@@ -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
-23
View File
@@ -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
-83
View File
@@ -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,
-20
View File
@@ -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