mirror of
https://github.com/semantica-agi/semantica.git
synced 2026-08-29 04:26:20 +00:00
fix(core): consume the fallback flag at the call site, not in the helper
Review finding, reproduced. `call_custom_method(..., **kwargs)` builds a
fresh dict from the unpacking, so popping `fallback_on_custom_error`
inside the helper left the caller's own kwargs untouched. On the fallback
path the flag was then forwarded straight into the default
implementation, which is exactly the case the flag exists for.
Instrumenting the default exporter shows it arriving:
config handed to the default exporter: {'fallback_on_custom_error': True}
Most defaults take **kwargs and ignore it, which is why nothing failed
loudly, but any default with a fixed signature raises TypeError on it.
The helper's docstring promised the flag was never forwarded, so the
promise was false rather than merely untidy.
All 58 sites now pop the flag from their own bag and pass it explicitly.
One site in normalize/methods.py names its bag `**context` rather than
`**kwargs`, and is handled too.
3 further tests: the flag reaches neither the default implementation nor
a successful custom method, and a per-module guard that every call site
has a matching pop, since a site that forgets one reintroduces the leak
silently.
Failure set across the six affected modules is unchanged against
upstream/main: 37 pre-existing, none new.
This commit is contained in:
@@ -120,8 +120,9 @@ def generate_embeddings(
|
||||
# Check for custom method in registry
|
||||
custom_method = method_registry.get("generation", method)
|
||||
if custom_method:
|
||||
fallback = kwargs.pop("fallback_on_custom_error", False)
|
||||
result = call_custom_method(
|
||||
logger, method, custom_method, data, data_type=data_type, **kwargs
|
||||
logger, method, custom_method, data, data_type=data_type, fallback_on_custom_error=fallback, **kwargs
|
||||
)
|
||||
if result is not CUSTOM_METHOD_FELL_BACK:
|
||||
return result
|
||||
@@ -167,7 +168,10 @@ def embed_text(
|
||||
# Check for custom method in registry
|
||||
custom_method = method_registry.get("text", method)
|
||||
if custom_method:
|
||||
result = call_custom_method(logger, method, custom_method, text, **kwargs)
|
||||
fallback = kwargs.pop("fallback_on_custom_error", False)
|
||||
result = call_custom_method(
|
||||
logger, method, custom_method, text, fallback_on_custom_error=fallback, **kwargs
|
||||
)
|
||||
if result is not CUSTOM_METHOD_FELL_BACK:
|
||||
return result
|
||||
|
||||
@@ -224,7 +228,10 @@ def calculate_similarity(
|
||||
# Check for custom method in registry
|
||||
custom_method = method_registry.get("similarity", method)
|
||||
if custom_method:
|
||||
result = call_custom_method(logger, method, custom_method, embedding1, embedding2, **kwargs)
|
||||
fallback = kwargs.pop("fallback_on_custom_error", False)
|
||||
result = call_custom_method(
|
||||
logger, method, custom_method, embedding1, embedding2, fallback_on_custom_error=fallback, **kwargs
|
||||
)
|
||||
if result is not CUSTOM_METHOD_FELL_BACK:
|
||||
return result
|
||||
|
||||
@@ -268,7 +275,10 @@ def pool_embeddings(
|
||||
# Check for custom method in registry
|
||||
custom_method = method_registry.get("pooling", method)
|
||||
if custom_method:
|
||||
result = call_custom_method(logger, method, custom_method, embeddings, **kwargs)
|
||||
fallback = kwargs.pop("fallback_on_custom_error", False)
|
||||
result = call_custom_method(
|
||||
logger, method, custom_method, embeddings, fallback_on_custom_error=fallback, **kwargs
|
||||
)
|
||||
if result is not CUSTOM_METHOD_FELL_BACK:
|
||||
return result
|
||||
|
||||
|
||||
+32
-13
@@ -222,8 +222,9 @@ def export_rdf(
|
||||
# Check for custom method in registry
|
||||
custom_method = method_registry.get("rdf", method)
|
||||
if custom_method and custom_method is not export_rdf:
|
||||
fallback = kwargs.pop("fallback_on_custom_error", False)
|
||||
result = call_custom_method(
|
||||
logger, method, custom_method, data, file_path, format=format, **kwargs
|
||||
logger, method, custom_method, data, file_path, format=format, fallback_on_custom_error=fallback, **kwargs
|
||||
)
|
||||
if result is not CUSTOM_METHOD_FELL_BACK:
|
||||
return result
|
||||
@@ -270,8 +271,9 @@ def export_json(
|
||||
# Check for custom method in registry
|
||||
custom_method = method_registry.get("json", method)
|
||||
if custom_method and custom_method is not export_json:
|
||||
fallback = kwargs.pop("fallback_on_custom_error", False)
|
||||
result = call_custom_method(
|
||||
logger, method, custom_method, data, file_path, format=format, **kwargs
|
||||
logger, method, custom_method, data, file_path, format=format, fallback_on_custom_error=fallback, **kwargs
|
||||
)
|
||||
if result is not CUSTOM_METHOD_FELL_BACK:
|
||||
return result
|
||||
@@ -315,7 +317,10 @@ def export_csv(
|
||||
# Check for custom method in registry
|
||||
custom_method = method_registry.get("csv", method)
|
||||
if custom_method and custom_method is not export_csv:
|
||||
result = call_custom_method(logger, method, custom_method, data, file_path, **kwargs)
|
||||
fallback = kwargs.pop("fallback_on_custom_error", False)
|
||||
result = call_custom_method(
|
||||
logger, method, custom_method, data, file_path, fallback_on_custom_error=fallback, **kwargs
|
||||
)
|
||||
if result is not CUSTOM_METHOD_FELL_BACK:
|
||||
return result
|
||||
|
||||
@@ -357,7 +362,10 @@ def export_arrow(
|
||||
# Check for custom method in registry
|
||||
custom_method = method_registry.get("arrow", method)
|
||||
if custom_method and custom_method is not export_arrow:
|
||||
result = call_custom_method(logger, method, custom_method, data, file_path, **kwargs)
|
||||
fallback = kwargs.pop("fallback_on_custom_error", False)
|
||||
result = call_custom_method(
|
||||
logger, method, custom_method, data, file_path, fallback_on_custom_error=fallback, **kwargs
|
||||
)
|
||||
if result is not CUSTOM_METHOD_FELL_BACK:
|
||||
return result
|
||||
|
||||
@@ -414,8 +422,9 @@ def export_parquet(
|
||||
# Check for custom method in registry
|
||||
custom_method = method_registry.get("parquet", method)
|
||||
if custom_method and custom_method is not export_parquet:
|
||||
fallback = kwargs.pop("fallback_on_custom_error", False)
|
||||
result = call_custom_method(
|
||||
logger, method, custom_method, data, file_path, compression=compression, **kwargs
|
||||
logger, method, custom_method, data, file_path, compression=compression, fallback_on_custom_error=fallback, **kwargs
|
||||
)
|
||||
if result is not CUSTOM_METHOD_FELL_BACK:
|
||||
return result
|
||||
@@ -464,8 +473,9 @@ def export_graph(
|
||||
# Check for custom method in registry
|
||||
custom_method = method_registry.get("graph", method)
|
||||
if custom_method and custom_method is not export_graph:
|
||||
fallback = kwargs.pop("fallback_on_custom_error", False)
|
||||
result = call_custom_method(
|
||||
logger, method, custom_method, graph_data, file_path, format=format, **kwargs
|
||||
logger, method, custom_method, graph_data, file_path, format=format, fallback_on_custom_error=fallback, **kwargs
|
||||
)
|
||||
if result is not CUSTOM_METHOD_FELL_BACK:
|
||||
return result
|
||||
@@ -529,7 +539,10 @@ def export_yaml(
|
||||
# Check for custom method in registry
|
||||
custom_method = method_registry.get("yaml", method)
|
||||
if custom_method and custom_method is not export_yaml:
|
||||
result = call_custom_method(logger, method, custom_method, data, file_path, **kwargs)
|
||||
fallback = kwargs.pop("fallback_on_custom_error", False)
|
||||
result = call_custom_method(
|
||||
logger, method, custom_method, data, file_path, fallback_on_custom_error=fallback, **kwargs
|
||||
)
|
||||
if result is not CUSTOM_METHOD_FELL_BACK:
|
||||
return result
|
||||
|
||||
@@ -583,8 +596,9 @@ def export_owl(
|
||||
# Check for custom method in registry
|
||||
custom_method = method_registry.get("owl", method)
|
||||
if custom_method and custom_method is not export_owl:
|
||||
fallback = kwargs.pop("fallback_on_custom_error", False)
|
||||
result = call_custom_method(
|
||||
logger, method, custom_method, ontology, file_path, format=format, **kwargs
|
||||
logger, method, custom_method, ontology, file_path, format=format, fallback_on_custom_error=fallback, **kwargs
|
||||
)
|
||||
if result is not CUSTOM_METHOD_FELL_BACK:
|
||||
return result
|
||||
@@ -634,8 +648,9 @@ def export_vector(
|
||||
# Check for custom method in registry
|
||||
custom_method = method_registry.get("vector", method)
|
||||
if custom_method and custom_method is not export_vector:
|
||||
fallback = kwargs.pop("fallback_on_custom_error", False)
|
||||
result = call_custom_method(
|
||||
logger, method, custom_method, vectors, file_path, format=format, **kwargs
|
||||
logger, method, custom_method, vectors, file_path, format=format, fallback_on_custom_error=fallback, **kwargs
|
||||
)
|
||||
if result is not CUSTOM_METHOD_FELL_BACK:
|
||||
return result
|
||||
@@ -681,8 +696,9 @@ def export_lpg(
|
||||
# Check for custom method in registry
|
||||
custom_method = method_registry.get("lpg", method)
|
||||
if custom_method and custom_method is not export_lpg:
|
||||
fallback = kwargs.pop("fallback_on_custom_error", False)
|
||||
result = call_custom_method(
|
||||
logger, method, custom_method, knowledge_graph, file_path, **kwargs
|
||||
logger, method, custom_method, knowledge_graph, file_path, fallback_on_custom_error=fallback, **kwargs
|
||||
)
|
||||
if result is not CUSTOM_METHOD_FELL_BACK:
|
||||
return result
|
||||
@@ -723,8 +739,9 @@ def export_neo4j_csv(
|
||||
"""
|
||||
custom_method = method_registry.get("neo4j_csv", method)
|
||||
if custom_method and custom_method is not export_neo4j_csv:
|
||||
fallback = kwargs.pop("fallback_on_custom_error", False)
|
||||
result = call_custom_method(
|
||||
logger, method, custom_method, knowledge_graph, output_dir, **kwargs
|
||||
logger, method, custom_method, knowledge_graph, output_dir, fallback_on_custom_error=fallback, **kwargs
|
||||
)
|
||||
if result is not CUSTOM_METHOD_FELL_BACK:
|
||||
return result
|
||||
@@ -792,8 +809,9 @@ def export_arango(
|
||||
# Check for custom method in registry
|
||||
custom_method = method_registry.get("arango", method)
|
||||
if custom_method and custom_method is not export_arango:
|
||||
fallback = kwargs.pop("fallback_on_custom_error", False)
|
||||
result = call_custom_method(
|
||||
logger, method, custom_method, knowledge_graph, file_path, **kwargs
|
||||
logger, method, custom_method, knowledge_graph, file_path, fallback_on_custom_error=fallback, **kwargs
|
||||
)
|
||||
if result is not CUSTOM_METHOD_FELL_BACK:
|
||||
return result
|
||||
@@ -842,8 +860,9 @@ def generate_report(
|
||||
# Check for custom method in registry
|
||||
custom_method = method_registry.get("report", method)
|
||||
if custom_method and custom_method is not generate_report:
|
||||
fallback = kwargs.pop("fallback_on_custom_error", False)
|
||||
result = call_custom_method(
|
||||
logger, method, custom_method, data, file_path, format=format, **kwargs
|
||||
logger, method, custom_method, data, file_path, format=format, fallback_on_custom_error=fallback, **kwargs
|
||||
)
|
||||
if result is not CUSTOM_METHOD_FELL_BACK:
|
||||
return result
|
||||
|
||||
+52
-13
@@ -249,7 +249,10 @@ def ingest_file(
|
||||
# Check for custom method in registry
|
||||
custom_method = method_registry.get("file", method)
|
||||
if custom_method and custom_method != ingest_file:
|
||||
result = call_custom_method(logger, method, custom_method, source, **kwargs)
|
||||
fallback = kwargs.pop("fallback_on_custom_error", False)
|
||||
result = call_custom_method(
|
||||
logger, method, custom_method, source, fallback_on_custom_error=fallback, **kwargs
|
||||
)
|
||||
if result is not CUSTOM_METHOD_FELL_BACK:
|
||||
return result
|
||||
|
||||
@@ -312,7 +315,10 @@ def ingest_parquet(
|
||||
"""
|
||||
custom_method = method_registry.get("parquet", method)
|
||||
if custom_method and custom_method != ingest_parquet:
|
||||
result = call_custom_method(logger, method, custom_method, source, **kwargs)
|
||||
fallback = kwargs.pop("fallback_on_custom_error", False)
|
||||
result = call_custom_method(
|
||||
logger, method, custom_method, source, fallback_on_custom_error=fallback, **kwargs
|
||||
)
|
||||
if result is not CUSTOM_METHOD_FELL_BACK:
|
||||
return result
|
||||
|
||||
@@ -388,7 +394,10 @@ def ingest_arrow(
|
||||
"""
|
||||
custom_method = method_registry.get("arrow", method)
|
||||
if custom_method and custom_method != ingest_arrow:
|
||||
result = call_custom_method(logger, method, custom_method, source, **kwargs)
|
||||
fallback = kwargs.pop("fallback_on_custom_error", False)
|
||||
result = call_custom_method(
|
||||
logger, method, custom_method, source, fallback_on_custom_error=fallback, **kwargs
|
||||
)
|
||||
if result is not CUSTOM_METHOD_FELL_BACK:
|
||||
return result
|
||||
|
||||
@@ -469,7 +478,10 @@ def ingest_xml(
|
||||
"""
|
||||
custom_method = method_registry.get("xml", method)
|
||||
if custom_method and custom_method != ingest_xml:
|
||||
result = call_custom_method(logger, method, custom_method, source, **kwargs)
|
||||
fallback = kwargs.pop("fallback_on_custom_error", False)
|
||||
result = call_custom_method(
|
||||
logger, method, custom_method, source, fallback_on_custom_error=fallback, **kwargs
|
||||
)
|
||||
if result is not CUSTOM_METHOD_FELL_BACK:
|
||||
return result
|
||||
|
||||
@@ -530,7 +542,10 @@ def ingest_web(
|
||||
# Check for custom method in registry
|
||||
custom_method = method_registry.get("web", method)
|
||||
if custom_method and custom_method != ingest_web:
|
||||
result = call_custom_method(logger, method, custom_method, source, **kwargs)
|
||||
fallback = kwargs.pop("fallback_on_custom_error", False)
|
||||
result = call_custom_method(
|
||||
logger, method, custom_method, source, fallback_on_custom_error=fallback, **kwargs
|
||||
)
|
||||
if result is not CUSTOM_METHOD_FELL_BACK:
|
||||
return result
|
||||
|
||||
@@ -617,7 +632,10 @@ def ingest_public_api(
|
||||
"""
|
||||
custom_method = method_registry.get("public_api", method)
|
||||
if custom_method and custom_method != ingest_public_api:
|
||||
result = call_custom_method(logger, method, custom_method, source, **kwargs)
|
||||
fallback = kwargs.pop("fallback_on_custom_error", False)
|
||||
result = call_custom_method(
|
||||
logger, method, custom_method, source, fallback_on_custom_error=fallback, **kwargs
|
||||
)
|
||||
if result is not CUSTOM_METHOD_FELL_BACK:
|
||||
return result
|
||||
|
||||
@@ -701,7 +719,10 @@ def ingest_feed(
|
||||
# Check for custom method in registry
|
||||
custom_method = method_registry.get("feed", method)
|
||||
if custom_method and custom_method != ingest_feed:
|
||||
result = call_custom_method(logger, method, custom_method, source, **kwargs)
|
||||
fallback = kwargs.pop("fallback_on_custom_error", False)
|
||||
result = call_custom_method(
|
||||
logger, method, custom_method, source, fallback_on_custom_error=fallback, **kwargs
|
||||
)
|
||||
if result is not CUSTOM_METHOD_FELL_BACK:
|
||||
return result
|
||||
|
||||
@@ -767,7 +788,10 @@ def ingest_stream(
|
||||
# Check for custom method in registry
|
||||
custom_method = method_registry.get("stream", method)
|
||||
if custom_method and custom_method != ingest_stream:
|
||||
result = call_custom_method(logger, method, custom_method, source, **kwargs)
|
||||
fallback = kwargs.pop("fallback_on_custom_error", False)
|
||||
result = call_custom_method(
|
||||
logger, method, custom_method, source, fallback_on_custom_error=fallback, **kwargs
|
||||
)
|
||||
if result is not CUSTOM_METHOD_FELL_BACK:
|
||||
return result
|
||||
|
||||
@@ -841,7 +865,10 @@ def ingest_repository(
|
||||
# Check for custom method in registry
|
||||
custom_method = method_registry.get("repo", method)
|
||||
if custom_method and custom_method != ingest_repository:
|
||||
result = call_custom_method(logger, method, custom_method, source, **kwargs)
|
||||
fallback = kwargs.pop("fallback_on_custom_error", False)
|
||||
result = call_custom_method(
|
||||
logger, method, custom_method, source, fallback_on_custom_error=fallback, **kwargs
|
||||
)
|
||||
if result is not CUSTOM_METHOD_FELL_BACK:
|
||||
return result
|
||||
|
||||
@@ -910,7 +937,10 @@ def ingest_email(
|
||||
# Check for custom method in registry
|
||||
custom_method = method_registry.get("email", method)
|
||||
if custom_method and custom_method != ingest_email:
|
||||
result = call_custom_method(logger, method, custom_method, source, **kwargs)
|
||||
fallback = kwargs.pop("fallback_on_custom_error", False)
|
||||
result = call_custom_method(
|
||||
logger, method, custom_method, source, fallback_on_custom_error=fallback, **kwargs
|
||||
)
|
||||
if result is not CUSTOM_METHOD_FELL_BACK:
|
||||
return result
|
||||
|
||||
@@ -986,7 +1016,10 @@ def ingest_ontology(
|
||||
# Check for custom method in registry
|
||||
custom_method = method_registry.get("ontology", method)
|
||||
if custom_method and custom_method != ingest_ontology:
|
||||
result = call_custom_method(logger, method, custom_method, source, **kwargs)
|
||||
fallback = kwargs.pop("fallback_on_custom_error", False)
|
||||
result = call_custom_method(
|
||||
logger, method, custom_method, source, fallback_on_custom_error=fallback, **kwargs
|
||||
)
|
||||
if result is not CUSTOM_METHOD_FELL_BACK:
|
||||
return result
|
||||
|
||||
@@ -1049,7 +1082,10 @@ def ingest_database(
|
||||
if method:
|
||||
custom_method = method_registry.get("db", method)
|
||||
if custom_method and custom_method != ingest_database:
|
||||
result = call_custom_method(logger, method, custom_method, source, **kwargs)
|
||||
fallback = kwargs.pop("fallback_on_custom_error", False)
|
||||
result = call_custom_method(
|
||||
logger, method, custom_method, source, fallback_on_custom_error=fallback, **kwargs
|
||||
)
|
||||
if result is not CUSTOM_METHOD_FELL_BACK:
|
||||
return result
|
||||
|
||||
@@ -1153,7 +1189,10 @@ def ingest_mcp(
|
||||
# Check for custom method in registry
|
||||
custom_method = method_registry.get("mcp", method)
|
||||
if custom_method and custom_method != ingest_mcp:
|
||||
result = call_custom_method(logger, method, custom_method, source, **kwargs)
|
||||
fallback = kwargs.pop("fallback_on_custom_error", False)
|
||||
result = call_custom_method(
|
||||
logger, method, custom_method, source, fallback_on_custom_error=fallback, **kwargs
|
||||
)
|
||||
if result is not CUSTOM_METHOD_FELL_BACK:
|
||||
return result
|
||||
|
||||
|
||||
+12
-3
@@ -190,7 +190,10 @@ def build_kg(
|
||||
# Check for custom method in registry
|
||||
custom_method = method_registry.get("build", method)
|
||||
if custom_method:
|
||||
result = call_custom_method(logger, method, custom_method, sources, **kwargs)
|
||||
fallback = kwargs.pop("fallback_on_custom_error", False)
|
||||
result = call_custom_method(
|
||||
logger, method, custom_method, sources, fallback_on_custom_error=fallback, **kwargs
|
||||
)
|
||||
if result is not CUSTOM_METHOD_FELL_BACK:
|
||||
return result
|
||||
|
||||
@@ -235,7 +238,10 @@ def analyze_graph(
|
||||
# Check for custom method in registry
|
||||
custom_method = method_registry.get("analyze", method)
|
||||
if custom_method:
|
||||
result = call_custom_method(logger, method, custom_method, graph, **kwargs)
|
||||
fallback = kwargs.pop("fallback_on_custom_error", False)
|
||||
result = call_custom_method(
|
||||
logger, method, custom_method, graph, fallback_on_custom_error=fallback, **kwargs
|
||||
)
|
||||
if result is not CUSTOM_METHOD_FELL_BACK:
|
||||
return result
|
||||
|
||||
@@ -436,7 +442,10 @@ def analyze_connectivity(
|
||||
# Check for custom method in registry
|
||||
custom_method = method_registry.get("connectivity", method)
|
||||
if custom_method:
|
||||
result = call_custom_method(logger, method, custom_method, graph, **kwargs)
|
||||
fallback = kwargs.pop("fallback_on_custom_error", False)
|
||||
result = call_custom_method(
|
||||
logger, method, custom_method, graph, fallback_on_custom_error=fallback, **kwargs
|
||||
)
|
||||
if result is not CUSTOM_METHOD_FELL_BACK:
|
||||
return result
|
||||
|
||||
|
||||
@@ -169,7 +169,10 @@ def normalize_text(text: str, method: str = "default", **kwargs) -> str:
|
||||
"""
|
||||
custom_method = method_registry.get("text", method)
|
||||
if custom_method:
|
||||
result = call_custom_method(logger, method, custom_method, text, **kwargs)
|
||||
fallback = kwargs.pop("fallback_on_custom_error", False)
|
||||
result = call_custom_method(
|
||||
logger, method, custom_method, text, fallback_on_custom_error=fallback, **kwargs
|
||||
)
|
||||
if result is not CUSTOM_METHOD_FELL_BACK:
|
||||
return result
|
||||
|
||||
@@ -210,7 +213,10 @@ def clean_text(text: str, method: str = "default", **kwargs) -> str:
|
||||
"""
|
||||
custom_method = method_registry.get("clean", method)
|
||||
if custom_method:
|
||||
result = call_custom_method(logger, method, custom_method, text, **kwargs)
|
||||
fallback = kwargs.pop("fallback_on_custom_error", False)
|
||||
result = call_custom_method(
|
||||
logger, method, custom_method, text, fallback_on_custom_error=fallback, **kwargs
|
||||
)
|
||||
if result is not CUSTOM_METHOD_FELL_BACK:
|
||||
return result
|
||||
|
||||
@@ -257,8 +263,9 @@ def normalize_entity(
|
||||
"""
|
||||
custom_method = method_registry.get("entity", method)
|
||||
if custom_method:
|
||||
fallback = kwargs.pop("fallback_on_custom_error", False)
|
||||
result = call_custom_method(
|
||||
logger, method, custom_method, entity_name, entity_type, **kwargs
|
||||
logger, method, custom_method, entity_name, entity_type, fallback_on_custom_error=fallback, **kwargs
|
||||
)
|
||||
if result is not CUSTOM_METHOD_FELL_BACK:
|
||||
return result
|
||||
@@ -303,8 +310,9 @@ def resolve_aliases(
|
||||
"""
|
||||
custom_method = method_registry.get("entity", method)
|
||||
if custom_method:
|
||||
fallback = kwargs.pop("fallback_on_custom_error", False)
|
||||
result = call_custom_method(
|
||||
logger, method, custom_method, entity_name, entity_type, **kwargs
|
||||
logger, method, custom_method, entity_name, entity_type, fallback_on_custom_error=fallback, **kwargs
|
||||
)
|
||||
if result is not CUSTOM_METHOD_FELL_BACK:
|
||||
return result
|
||||
@@ -349,7 +357,10 @@ def disambiguate_entity(
|
||||
"""
|
||||
custom_method = method_registry.get("entity", method)
|
||||
if custom_method:
|
||||
result = call_custom_method(logger, method, custom_method, entity_name, **context)
|
||||
fallback = context.pop("fallback_on_custom_error", False)
|
||||
result = call_custom_method(
|
||||
logger, method, custom_method, entity_name, fallback_on_custom_error=fallback, **context
|
||||
)
|
||||
if result is not CUSTOM_METHOD_FELL_BACK:
|
||||
return result
|
||||
|
||||
@@ -401,8 +412,9 @@ def normalize_date(
|
||||
"""
|
||||
custom_method = method_registry.get("date", method)
|
||||
if custom_method:
|
||||
fallback = kwargs.pop("fallback_on_custom_error", False)
|
||||
result = call_custom_method(
|
||||
logger, method, custom_method, date_input, format, timezone, **kwargs
|
||||
logger, method, custom_method, date_input, format, timezone, fallback_on_custom_error=fallback, **kwargs
|
||||
)
|
||||
if result is not CUSTOM_METHOD_FELL_BACK:
|
||||
return result
|
||||
@@ -441,7 +453,10 @@ def normalize_time(time_input: Any, method: str = "default", **kwargs) -> str:
|
||||
"""
|
||||
custom_method = method_registry.get("date", method)
|
||||
if custom_method:
|
||||
result = call_custom_method(logger, method, custom_method, time_input, **kwargs)
|
||||
fallback = kwargs.pop("fallback_on_custom_error", False)
|
||||
result = call_custom_method(
|
||||
logger, method, custom_method, time_input, fallback_on_custom_error=fallback, **kwargs
|
||||
)
|
||||
if result is not CUSTOM_METHOD_FELL_BACK:
|
||||
return result
|
||||
|
||||
@@ -484,7 +499,10 @@ def normalize_number(
|
||||
"""
|
||||
custom_method = method_registry.get("number", method)
|
||||
if custom_method:
|
||||
result = call_custom_method(logger, method, custom_method, number_input, **kwargs)
|
||||
fallback = kwargs.pop("fallback_on_custom_error", False)
|
||||
result = call_custom_method(
|
||||
logger, method, custom_method, number_input, fallback_on_custom_error=fallback, **kwargs
|
||||
)
|
||||
if result is not CUSTOM_METHOD_FELL_BACK:
|
||||
return result
|
||||
|
||||
@@ -525,7 +543,10 @@ def normalize_quantity(
|
||||
"""
|
||||
custom_method = method_registry.get("number", method)
|
||||
if custom_method:
|
||||
result = call_custom_method(logger, method, custom_method, quantity_input, **kwargs)
|
||||
fallback = kwargs.pop("fallback_on_custom_error", False)
|
||||
result = call_custom_method(
|
||||
logger, method, custom_method, quantity_input, fallback_on_custom_error=fallback, **kwargs
|
||||
)
|
||||
if result is not CUSTOM_METHOD_FELL_BACK:
|
||||
return result
|
||||
|
||||
@@ -578,8 +599,9 @@ def clean_data(
|
||||
"""
|
||||
custom_method = method_registry.get("clean", method)
|
||||
if custom_method:
|
||||
fallback = kwargs.pop("fallback_on_custom_error", False)
|
||||
result = call_custom_method(
|
||||
logger, method, custom_method, dataset, remove_duplicates, validate, handle_missing, **kwargs
|
||||
logger, method, custom_method, dataset, remove_duplicates, validate, handle_missing, fallback_on_custom_error=fallback, **kwargs
|
||||
)
|
||||
if result is not CUSTOM_METHOD_FELL_BACK:
|
||||
return result
|
||||
@@ -630,8 +652,9 @@ def detect_duplicates(
|
||||
"""
|
||||
custom_method = method_registry.get("clean", method)
|
||||
if custom_method:
|
||||
fallback = kwargs.pop("fallback_on_custom_error", False)
|
||||
result = call_custom_method(
|
||||
logger, method, custom_method, dataset, threshold, key_fields, **kwargs
|
||||
logger, method, custom_method, dataset, threshold, key_fields, fallback_on_custom_error=fallback, **kwargs
|
||||
)
|
||||
if result is not CUSTOM_METHOD_FELL_BACK:
|
||||
return result
|
||||
@@ -676,7 +699,10 @@ def detect_language(
|
||||
"""
|
||||
custom_method = method_registry.get("language", method)
|
||||
if custom_method:
|
||||
result = call_custom_method(logger, method, custom_method, text, **kwargs)
|
||||
fallback = kwargs.pop("fallback_on_custom_error", False)
|
||||
result = call_custom_method(
|
||||
logger, method, custom_method, text, fallback_on_custom_error=fallback, **kwargs
|
||||
)
|
||||
if result is not CUSTOM_METHOD_FELL_BACK:
|
||||
return result
|
||||
|
||||
@@ -734,7 +760,10 @@ def handle_encoding(
|
||||
"""
|
||||
custom_method = method_registry.get("encoding", method)
|
||||
if custom_method:
|
||||
result = call_custom_method(logger, method, custom_method, data, operation, **kwargs)
|
||||
fallback = kwargs.pop("fallback_on_custom_error", False)
|
||||
result = call_custom_method(
|
||||
logger, method, custom_method, data, operation, fallback_on_custom_error=fallback, **kwargs
|
||||
)
|
||||
if result is not CUSTOM_METHOD_FELL_BACK:
|
||||
return result
|
||||
|
||||
|
||||
+46
-12
@@ -179,7 +179,10 @@ def parse_document(
|
||||
"""
|
||||
custom_method = method_registry.get("document", method)
|
||||
if custom_method:
|
||||
result = call_custom_method(logger, method, custom_method, file_path, file_type, **kwargs)
|
||||
fallback = kwargs.pop("fallback_on_custom_error", False)
|
||||
result = call_custom_method(
|
||||
logger, method, custom_method, file_path, file_type, fallback_on_custom_error=fallback, **kwargs
|
||||
)
|
||||
if result is not CUSTOM_METHOD_FELL_BACK:
|
||||
return result
|
||||
|
||||
@@ -287,8 +290,9 @@ def parse_web_content(
|
||||
"""
|
||||
custom_method = method_registry.get("web", method)
|
||||
if custom_method:
|
||||
fallback = kwargs.pop("fallback_on_custom_error", False)
|
||||
result = call_custom_method(
|
||||
logger, method, custom_method, content, content_type, base_url, **kwargs
|
||||
logger, method, custom_method, content, content_type, base_url, fallback_on_custom_error=fallback, **kwargs
|
||||
)
|
||||
if result is not CUSTOM_METHOD_FELL_BACK:
|
||||
return result
|
||||
@@ -342,7 +346,10 @@ def parse_structured_data(
|
||||
"""
|
||||
custom_method = method_registry.get("structured", method)
|
||||
if custom_method:
|
||||
result = call_custom_method(logger, method, custom_method, data, data_format, **kwargs)
|
||||
fallback = kwargs.pop("fallback_on_custom_error", False)
|
||||
result = call_custom_method(
|
||||
logger, method, custom_method, data, data_format, fallback_on_custom_error=fallback, **kwargs
|
||||
)
|
||||
if result is not CUSTOM_METHOD_FELL_BACK:
|
||||
return result
|
||||
|
||||
@@ -386,7 +393,10 @@ def parse_email(
|
||||
"""
|
||||
custom_method = method_registry.get("email", method)
|
||||
if custom_method:
|
||||
result = call_custom_method(logger, method, custom_method, email_content, **kwargs)
|
||||
fallback = kwargs.pop("fallback_on_custom_error", False)
|
||||
result = call_custom_method(
|
||||
logger, method, custom_method, email_content, fallback_on_custom_error=fallback, **kwargs
|
||||
)
|
||||
if result is not CUSTOM_METHOD_FELL_BACK:
|
||||
return result
|
||||
|
||||
@@ -433,7 +443,10 @@ def parse_code(
|
||||
"""
|
||||
custom_method = method_registry.get("code", method)
|
||||
if custom_method:
|
||||
result = call_custom_method(logger, method, custom_method, file_path, language, **kwargs)
|
||||
fallback = kwargs.pop("fallback_on_custom_error", False)
|
||||
result = call_custom_method(
|
||||
logger, method, custom_method, file_path, language, fallback_on_custom_error=fallback, **kwargs
|
||||
)
|
||||
if result is not CUSTOM_METHOD_FELL_BACK:
|
||||
return result
|
||||
|
||||
@@ -483,7 +496,10 @@ def parse_media(
|
||||
"""
|
||||
custom_method = method_registry.get("media", method)
|
||||
if custom_method:
|
||||
result = call_custom_method(logger, method, custom_method, file_path, media_type, **kwargs)
|
||||
fallback = kwargs.pop("fallback_on_custom_error", False)
|
||||
result = call_custom_method(
|
||||
logger, method, custom_method, file_path, media_type, fallback_on_custom_error=fallback, **kwargs
|
||||
)
|
||||
if result is not CUSTOM_METHOD_FELL_BACK:
|
||||
return result
|
||||
|
||||
@@ -526,7 +542,10 @@ def parse_pdf(
|
||||
"""
|
||||
custom_method = method_registry.get("document", method)
|
||||
if custom_method:
|
||||
result = call_custom_method(logger, method, custom_method, file_path, **kwargs)
|
||||
fallback = kwargs.pop("fallback_on_custom_error", False)
|
||||
result = call_custom_method(
|
||||
logger, method, custom_method, file_path, fallback_on_custom_error=fallback, **kwargs
|
||||
)
|
||||
if result is not CUSTOM_METHOD_FELL_BACK:
|
||||
return result
|
||||
|
||||
@@ -567,7 +586,10 @@ def parse_docx(
|
||||
"""
|
||||
custom_method = method_registry.get("document", method)
|
||||
if custom_method:
|
||||
result = call_custom_method(logger, method, custom_method, file_path, **kwargs)
|
||||
fallback = kwargs.pop("fallback_on_custom_error", False)
|
||||
result = call_custom_method(
|
||||
logger, method, custom_method, file_path, fallback_on_custom_error=fallback, **kwargs
|
||||
)
|
||||
if result is not CUSTOM_METHOD_FELL_BACK:
|
||||
return result
|
||||
|
||||
@@ -607,7 +629,10 @@ def parse_json(file_path: Union[str, Path], method: str = "default", **kwargs) -
|
||||
"""
|
||||
custom_method = method_registry.get("structured", method)
|
||||
if custom_method:
|
||||
result = call_custom_method(logger, method, custom_method, file_path, **kwargs)
|
||||
fallback = kwargs.pop("fallback_on_custom_error", False)
|
||||
result = call_custom_method(
|
||||
logger, method, custom_method, file_path, fallback_on_custom_error=fallback, **kwargs
|
||||
)
|
||||
if result is not CUSTOM_METHOD_FELL_BACK:
|
||||
return result
|
||||
|
||||
@@ -651,7 +676,10 @@ def parse_csv(
|
||||
"""
|
||||
custom_method = method_registry.get("structured", method)
|
||||
if custom_method:
|
||||
result = call_custom_method(logger, method, custom_method, file_path, delimiter, **kwargs)
|
||||
fallback = kwargs.pop("fallback_on_custom_error", False)
|
||||
result = call_custom_method(
|
||||
logger, method, custom_method, file_path, delimiter, fallback_on_custom_error=fallback, **kwargs
|
||||
)
|
||||
if result is not CUSTOM_METHOD_FELL_BACK:
|
||||
return result
|
||||
|
||||
@@ -687,7 +715,10 @@ def parse_xml(file_path: Union[str, Path], method: str = "default", **kwargs) ->
|
||||
"""
|
||||
custom_method = method_registry.get("structured", method)
|
||||
if custom_method:
|
||||
result = call_custom_method(logger, method, custom_method, file_path, **kwargs)
|
||||
fallback = kwargs.pop("fallback_on_custom_error", False)
|
||||
result = call_custom_method(
|
||||
logger, method, custom_method, file_path, fallback_on_custom_error=fallback, **kwargs
|
||||
)
|
||||
if result is not CUSTOM_METHOD_FELL_BACK:
|
||||
return result
|
||||
|
||||
@@ -732,7 +763,10 @@ def parse_image(
|
||||
"""
|
||||
custom_method = method_registry.get("media", method)
|
||||
if custom_method:
|
||||
result = call_custom_method(logger, method, custom_method, file_path, **kwargs)
|
||||
fallback = kwargs.pop("fallback_on_custom_error", False)
|
||||
result = call_custom_method(
|
||||
logger, method, custom_method, file_path, fallback_on_custom_error=fallback, **kwargs
|
||||
)
|
||||
if result is not CUSTOM_METHOD_FELL_BACK:
|
||||
return result
|
||||
|
||||
|
||||
@@ -154,3 +154,72 @@ def test_no_module_still_swallows_custom_method_failures(module_name):
|
||||
assert "falling back to default" not in source, (
|
||||
f"semantica/{module_name}/methods.py still swallows custom method failures"
|
||||
)
|
||||
|
||||
|
||||
# ── Review findings on the first revision of this fix ────────────────────────
|
||||
|
||||
def test_the_reserved_flag_never_reaches_the_default_implementation(monkeypatch, tmp_path):
|
||||
"""
|
||||
`**kwargs` unpacking builds a fresh dict inside the helper, so popping there
|
||||
left the caller's own kwargs untouched and the flag was forwarded on to the
|
||||
default path. The helper documents the flag as never forwarded, so that
|
||||
promise was false for exactly the case the flag exists for.
|
||||
"""
|
||||
seen = {}
|
||||
|
||||
class Spy:
|
||||
def __init__(self, **config):
|
||||
seen.update(config)
|
||||
|
||||
def export(self, *args, **kwargs):
|
||||
(tmp_path / "written").write_text("default ran")
|
||||
|
||||
monkeypatch.setattr(export_methods, "RDFExporter", Spy)
|
||||
|
||||
def gate(data, file_path, **kwargs):
|
||||
raise Refused("rejected")
|
||||
|
||||
method_registry.register("rdf", "gate", gate)
|
||||
export_methods.export_rdf(
|
||||
KG, str(tmp_path / "out.ttl"), method="gate", fallback_on_custom_error=True
|
||||
)
|
||||
|
||||
assert (tmp_path / "written").exists(), "the default path did not run"
|
||||
assert "fallback_on_custom_error" not in seen, (
|
||||
f"the reserved flag was forwarded to the default implementation: {seen}"
|
||||
)
|
||||
|
||||
|
||||
def test_the_reserved_flag_never_reaches_a_successful_custom_method(tmp_path):
|
||||
seen = {}
|
||||
|
||||
def writer(data, file_path, **kwargs):
|
||||
seen.update(kwargs)
|
||||
return "ok"
|
||||
|
||||
method_registry.register("rdf", "writer", writer)
|
||||
result = export_methods.export_rdf(
|
||||
KG, str(tmp_path / "out.ttl"), method="writer", fallback_on_custom_error=True
|
||||
)
|
||||
|
||||
assert result == "ok"
|
||||
assert "fallback_on_custom_error" not in seen, seen
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"module_name", ["export", "ingest", "parse", "normalize", "embeddings", "kg"],
|
||||
)
|
||||
def test_every_site_consumes_the_flag_before_forwarding(module_name):
|
||||
"""A site that forgets the pop reintroduces the leak silently."""
|
||||
import semantica
|
||||
|
||||
source = (
|
||||
Path(semantica.__file__).parent / module_name / "methods.py"
|
||||
).read_text(encoding="utf-8")
|
||||
|
||||
calls = source.count("result = call_custom_method(")
|
||||
pops = source.count('.pop("fallback_on_custom_error", False)')
|
||||
assert calls == pops, (
|
||||
f"semantica/{module_name}/methods.py has {calls} call site(s) but "
|
||||
f"{pops} consume the reserved flag"
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user