Files
cadSet/SimpleCADAPI/tools/scene_contract_fixtures/package_cases.py

264 lines
8.4 KiB
Python

"""Scene package provenance and connector-binding fixture builders."""
from __future__ import annotations
from copy import deepcopy
from typing import Callable
from simplecadapi.scene import with_scene_revision
from .common import (
JsonObject,
ScenePackage,
inline_package_case,
replace_entity_sidecar,
set_product_material_appearance,
)
def build_source_scene_package(
base_scene: JsonObject,
base_entity: JsonObject,
base_blobs: dict[str, bytes],
variant: str,
) -> ScenePackage:
scene = deepcopy(base_scene)
entity = deepcopy(base_entity)
definition = scene["definitions"][0]
source_for: Callable[[JsonObject], JsonObject]
status_for: Callable[[JsonObject], str]
if variant == "imported_shape":
definition_id = "definition/root/shape/imported/element"
scene["scene_id"] = "imported_fixture"
scene["source"] = {
"artifact_hash": "sha256:" + "1" * 64,
"format": "step",
"kind": "imported",
}
definition.update(
{
"definition_id": definition_id,
"kind": "shape",
"source": {
"kind": "imported",
"root_id": "root",
"source_element_id": "element",
},
}
)
source_for = lambda record: {
"kind": "imported_primitive",
"source_element_id": record["entity_id"],
}
status_for = lambda record: (
"not_applicable" if record["kind"] == "solid" else "owner_not_part"
)
else:
definition_kind = "part" if variant == "model_part" else "shape"
definition_id = (
"definition/root/part/model_part"
if definition_kind == "part"
else "definition/root/shape/model/graph/body/0"
)
scene["scene_id"] = f"{variant}_fixture"
scene["source"] = {
"artifact_hash": "sha256:" + "2" * 64,
"graph_id": "graph",
"kind": "model",
"model_schema_version": "2.0",
}
definition_source: JsonObject = {
"graph_id": "graph",
"kind": "product_model" if definition_kind == "part" else "model_output",
"node_id": "body",
"output_slot": 0,
"root_id": "root",
}
if definition_kind == "part":
definition_source.update(
{"semantic_id": "model_part", "semantic_type": "Part"}
)
definition.update(
{
"definition_id": definition_id,
"kind": definition_kind,
"source": definition_source,
}
)
topology_kind = {
"solid": "SOLID",
"face": "FACE",
"edge": "EDGE",
"vertex": "VERTEX",
}
if variant == "model_part":
source_for = lambda record: {
"graph_id": "graph",
"kind": "model_topology",
"node_id": "body",
"output_slot": 0,
"topo_id": record["entity_id"],
"topology_kind": topology_kind[record["kind"]],
}
statuses = iter(
["supported", "selector_ambiguous", "selector_unstable", "supported"]
)
def status_for(record: JsonObject) -> str:
return (
"not_applicable"
if record["kind"] == "solid"
else next(statuses, "supported")
)
else:
source_for = lambda _record: {
"graph_id": "graph",
"kind": "model_output",
"node_id": "body",
"output_slot": 0,
}
status_for = lambda record: (
"not_applicable"
if record["kind"] == "solid"
else "owner_not_part"
)
if definition["kind"] == "part":
scene["nodes"][0]["source"] = {
"component_path": [],
"kind": "product_occurrence",
"root_id": "root",
}
scene["nodes"][0]["definition_id"] = definition_id
entity["definition_id"] = definition_id
for record in entity["entities"]:
record["source"] = source_for(record)
record["connector_binding_status"] = status_for(record)
if variant == "model_part":
edge = next(record for record in entity["entities"] if record["kind"] == "edge")
edge["sdk_connector_frame"] = None
edge["connector_binding_status"] = "frame_undefined"
scene, entity, blobs = replace_entity_sidecar(
scene, entity, dict(base_blobs)
)
if definition["kind"] == "part":
set_product_material_appearance(scene)
return with_scene_revision(scene), entity, blobs
def build_package_matrix_cases(
scene: JsonObject,
entity: JsonObject,
blobs: dict[str, bytes],
scene_packages: dict[str, ScenePackage],
blob_pool: dict[str, str],
) -> list[dict[str, object]]:
cases: list[dict[str, object]] = []
for variant in ("imported_shape", "model_shape", "model_part"):
package = build_source_scene_package(scene, entity, blobs, variant)
cases.append(
inline_package_case(
f"valid_{variant}", package[0], package[2], blob_pool
)
)
nested = scene_packages["nested_assembly"]
model_part = build_source_scene_package(scene, entity, blobs, "model_part")
status_mutations = [
(
"solid_status_precedence",
(deepcopy(scene), deepcopy(entity), dict(blobs)),
"solid",
"supported",
),
(
"owner_not_part_status_precedence",
(deepcopy(scene), deepcopy(entity), dict(blobs)),
"face",
"source_not_model",
),
(
"source_not_model_status_precedence",
deepcopy(nested),
"face",
"supported",
),
(
"frame_undefined_status_precedence",
deepcopy(model_part),
"edge",
"owner_not_part",
),
]
for name, package, kind, status in status_mutations:
status_scene, status_entity, status_blobs = package
target = next(
record for record in status_entity["entities"] if record["kind"] == kind
)
target["connector_binding_status"] = status
status_scene, _status_entity, status_blobs = replace_entity_sidecar(
status_scene, status_entity, status_blobs
)
cases.append(
inline_package_case(
name, with_scene_revision(status_scene), status_blobs, blob_pool
)
)
forwarded_scene, _forwarded_entity, forwarded_blobs = deepcopy(nested)
root_connector = next(
record
for record in forwarded_scene["connectors"]
if record["connector_id"] == "root_mount"
)
root_connector["local_transform"]["origin"] = [0, 0, 6]
cases.append(
inline_package_case(
"forwarded_transform_mismatch",
with_scene_revision(forwarded_scene),
forwarded_blobs,
blob_pool,
)
)
missing_child_scene, _missing_child_entity, missing_child_blobs = deepcopy(nested)
root_connector = next(
record
for record in missing_child_scene["connectors"]
if record["connector_id"] == "root_mount"
)
root_connector["forwarded_from"]["source_component_id"] = "missing"
cases.append(
inline_package_case(
"forwarded_direct_child_missing",
with_scene_revision(missing_child_scene),
missing_child_blobs,
blob_pool,
)
)
part_owner_scene, _part_owner_entity, part_owner_blobs = deepcopy(nested)
root_connector = next(
record
for record in part_owner_scene["connectors"]
if record["connector_id"] == "root_mount"
)
root_connector["owner_definition_id"] = "definition/root/part/shared_part"
root_connector["connector_snapshot_id"] = (
"connector/root/part/shared_part/root_mount"
)
part_owner_scene["connectors"].sort(
key=lambda record: record["connector_snapshot_id"]
)
cases.append(
inline_package_case(
"forwarded_owner_not_assembly",
with_scene_revision(part_owner_scene),
part_owner_blobs,
blob_pool,
)
)
return cases