Initial SQL-only 1C adapter baseline
This commit is contained in:
@@ -0,0 +1,129 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
sys.path.insert(0, str(ROOT))
|
||||
sys.path.insert(0, str(ROOT / "plugins" / "1c"))
|
||||
sys.path.insert(0, str(ROOT / "plugins" / "1c" / "connector"))
|
||||
|
||||
import adapter_1c_server as adapter_server # noqa: E402
|
||||
|
||||
|
||||
def require(condition: bool, message: str, failures: list[str]) -> None:
|
||||
if not condition:
|
||||
failures.append(message)
|
||||
|
||||
|
||||
def patch_adapter_reads() -> None:
|
||||
adapter_server.read_storage_file_bytes = lambda base_id, table, file_name, timeout_seconds=30: (b"fake", {"database": "fake"}, None)
|
||||
adapter_server.payload_text_from_bytes = lambda data: {
|
||||
"status": "ok",
|
||||
"text": "Процедура Проверка()\nКонецПроцедуры",
|
||||
}
|
||||
adapter_server.extension_module_owner_payload = lambda base_id, module_id, table, timeout_seconds=30: None
|
||||
adapter_server.cached_module_owner_payload = lambda base_id, module_id: None
|
||||
|
||||
|
||||
def read_origin(method: str, module_ref: str) -> dict[str, Any]:
|
||||
result = adapter_server.call_method(
|
||||
method,
|
||||
{
|
||||
"base_id": "upo_test",
|
||||
"module_ref": module_ref,
|
||||
"include_text": True,
|
||||
"max_chars": 200,
|
||||
},
|
||||
)
|
||||
origin = result.get("origin") if isinstance(result.get("origin"), dict) else {}
|
||||
return {"result": result, "origin": origin}
|
||||
|
||||
|
||||
def check_code_search_origin(failures: list[str]) -> None:
|
||||
adapter_server.search_modules = lambda payload: {
|
||||
"status": "ok",
|
||||
"source": {"kind": "live_metadata"},
|
||||
"matches": [
|
||||
{
|
||||
"snippet": {"text": "Процедура Проверка()", "offset": 0},
|
||||
"owner": {"status": "unresolved", "kind": None, "name": None},
|
||||
"origin": {
|
||||
"source": "cas_reference",
|
||||
"status": "owner_unresolved",
|
||||
"write_surface": "requires_owner_resolution",
|
||||
},
|
||||
"module": {"name": "Модуль БСЛ"},
|
||||
"read_selector": {"base_id": "upo_test", "module_ref": "ConfigCAS:object-module"},
|
||||
}
|
||||
],
|
||||
"counts": {"matches": 1, "complete": True, "scan_limit_hit": False},
|
||||
"diagnostics": {},
|
||||
}
|
||||
result = adapter_server.call_method("code.search", {"base_id": "upo_test", "query": "Проверка"})
|
||||
items = result.get("items") if isinstance(result.get("items"), list) else []
|
||||
origin = items[0].get("origin") if items and isinstance(items[0], dict) and isinstance(items[0].get("origin"), dict) else {}
|
||||
require(result.get("schema") == "onec_code_search.v1", "code.search must return code search schema", failures)
|
||||
require(bool(items), "code.search must return patched item", failures)
|
||||
require(origin.get("source") == "cas_reference", "code.search item must preserve modules.search origin", failures)
|
||||
require(origin.get("write_surface") == "requires_owner_resolution", "code.search item origin must keep write_surface", failures)
|
||||
|
||||
|
||||
def run_checks() -> dict[str, Any]:
|
||||
patch_adapter_reads()
|
||||
failures: list[str] = []
|
||||
|
||||
config = read_origin("modules.read", "Config:object-module")
|
||||
require(config["result"].get("status") == "ok", "Config module_ref must read in patched contract", failures)
|
||||
require(config["origin"].get("source") == "configuration", "Config module_ref must expose configuration origin", failures)
|
||||
require(config["origin"].get("write_surface") == "base_saved_state", "Config origin must point writes to base saved-state", failures)
|
||||
|
||||
save = read_origin("modules.read", "ConfigSave:object-module")
|
||||
require(save["result"].get("status") == "ok", "ConfigSave module_ref must read in patched contract", failures)
|
||||
require(save["origin"].get("source") == "saved_state", "ConfigSave module_ref must expose saved_state origin", failures)
|
||||
require(save["origin"].get("write_surface") == "base_saved_state", "ConfigSave origin must point writes to base saved-state", failures)
|
||||
|
||||
cas = read_origin("modules.read", "ConfigCAS:object-module")
|
||||
require(cas["result"].get("status") == "ok", "ConfigCAS module_ref must read in patched contract", failures)
|
||||
require(cas["origin"].get("source") == "cas_reference", "ConfigCAS fallback must not pretend extension/base owner", failures)
|
||||
require(cas["origin"].get("status") == "owner_unresolved", "ConfigCAS fallback must require owner resolution", failures)
|
||||
require(cas["origin"].get("write_surface") == "requires_owner_resolution", "ConfigCAS fallback must block direct write routing", failures)
|
||||
|
||||
code_save = read_origin("code.read", "ConfigSave:object-module")
|
||||
require(code_save["result"].get("schema") == "onec_code_read.v1", "code.read must wrap modules.read as onec_code_read", failures)
|
||||
require(code_save["origin"].get("source") == "saved_state", "code.read must preserve modules.read origin", failures)
|
||||
require(code_save["origin"].get("write_surface") == "base_saved_state", "code.read origin must keep write_surface", failures)
|
||||
check_code_search_origin(failures)
|
||||
|
||||
return {
|
||||
"schema": "onec_module_origin_contract_check.v1",
|
||||
"status": "ok" if not failures else "failed",
|
||||
"failures": failures,
|
||||
"checks": {
|
||||
"config_origin": "Config module_ref exposes configuration origin",
|
||||
"configsave_origin": "ConfigSave module_ref exposes saved_state origin",
|
||||
"configcas_owner_required": "ConfigCAS module_ref requires owner resolution",
|
||||
"code_read_preserves_origin": "code.read preserves origin evidence from modules.read",
|
||||
"code_search_preserves_origin": "code.search preserves origin evidence from modules.search",
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
def main() -> int:
|
||||
parser = argparse.ArgumentParser(description="Check modules.read origin/provenance contract invariants.")
|
||||
parser.add_argument("--print", action="store_true")
|
||||
args = parser.parse_args()
|
||||
report = run_checks()
|
||||
if args.print or report["status"] != "ok":
|
||||
print(json.dumps(report, ensure_ascii=False, indent=2))
|
||||
else:
|
||||
print("1C module origin contract status: ok")
|
||||
return 0 if report["status"] == "ok" else 1
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
Reference in New Issue
Block a user