import hashlib import json import os import FreeCAD as App import Part FREECAD_COMMIT = "0108fd4b4850cc46e625b60e53cea7a7bbe69f8d" def shape_snapshot(obj): shape = obj.Shape if shape.isNull(): return {"isNull": True, "valid": False, "shapeType": "Null", "solids": 0, "faces": 0, "edges": 0, "vertices": 0, "area": 0.0, "volume": 0.0, "brepSha256": None} return { "isNull": False, "valid": bool(shape.isValid()), "shapeType": shape.ShapeType, "solids": len(shape.Solids), "faces": len(shape.Faces), "edges": len(shape.Edges), "vertices": len(shape.Vertexes), "area": round(float(shape.Area), 9), "volume": round(float(shape.Volume), 9), "brepSha256": hashlib.sha256(shape.exportBrepToString().encode("utf-8")).hexdigest(), } def object_snapshot(document): owner = document.getObject("SketchProbe") targets = [document.getObject("ExportA"), document.getObject("ExportB")] return { "objectSet": [{"name": item.Name, "typeId": item.TypeId} for item in document.Objects], "object": { "name": owner.Name, "typeId": owner.TypeId, "propertyName": "Exports", "propertyTypeId": owner.getTypeIdOfProperty("Exports"), "group": owner.getGroupOfProperty("Exports"), "value": [item.Name for item in owner.Exports], "propertyStatus": [str(item) for item in owner.getPropertyStatus("Exports")], "editorMode": [str(item) for item in owner.getEditorMode("Exports")], "state": [str(item) for item in owner.State], "statusString": str(owner.getStatusString()), "shape": shape_snapshot(owner), "outList": [item.Name for item in owner.OutList], }, "targets": { target.Name: { "typeId": target.TypeId, "inList": [item.Name for item in target.InList], "shape": shape_snapshot(target), } for target in targets }, } def create_native(path): document = App.newDocument("PropertyLinkListHiddenRoundtrip") try: owner = document.addObject("Sketcher::SketchObject", "SketchProbe") first = document.addObject("Part::Feature", "ExportA") first.Shape = Part.makeBox(2.0, 3.0, 4.0) second = document.addObject("Part::Feature", "ExportB") second.Shape = Part.makeCylinder(1.5, 5.0) owner.Exports = [first, second] document.recompute() document.saveAs(path) finally: App.closeDocument(document.Name) reopened = App.openDocument(path) try: reopened.recompute() return object_snapshot(reopened) finally: App.closeDocument(reopened.Name) def verify_native(path, resaved_path): document = App.openDocument(path) try: document.recompute() reopened = object_snapshot(document) document.saveAs(resaved_path) finally: App.closeDocument(document.Name) resaved_document = App.openDocument(resaved_path) try: resaved_document.recompute() resaved = object_snapshot(resaved_document) finally: App.closeDocument(resaved_document.Name) return {"reopened": reopened, "resaved": resaved} mode = os.environ.get("FREECAD_PROPERTY_LINKLISTHIDDEN_ROUNDTRIP_MODE", "") path = os.environ.get("FREECAD_PROPERTY_LINKLISTHIDDEN_ROUNDTRIP_PATH", "") resaved_path = os.environ.get("FREECAD_PROPERTY_LINKLISTHIDDEN_ROUNDTRIP_RESAVED_PATH", "") if mode == "create": result = create_native(path) elif mode == "verify": result = verify_native(path, resaved_path) else: raise RuntimeError("FREECAD_PROPERTY_LINKLISTHIDDEN_ROUNDTRIP_MODE must be create or verify") print("FREECAD_PROPERTY_LINKLISTHIDDEN_ROUNDTRIP_RESULT=" + json.dumps({"schemaVersion": 1, "status": "pass", "baselineId": "freecad-1.1.1-property-linklisthidden-roundtrip", "freecadVersion": ".".join(str(value) for value in App.Version()[:3]), "gitCommit": FREECAD_COMMIT, "mode": mode, "result": result}, sort_keys=True))