typehaus 0.1.0a0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- typehaus-0.1.0a0/.gitignore +211 -0
- typehaus-0.1.0a0/PKG-INFO +93 -0
- typehaus-0.1.0a0/README.md +50 -0
- typehaus-0.1.0a0/pyproject.toml +60 -0
- typehaus-0.1.0a0/pytest.ini +3 -0
- typehaus-0.1.0a0/scripts/bench_rebuild.py +95 -0
- typehaus-0.1.0a0/src/typehaus/__init__.py +15 -0
- typehaus-0.1.0a0/src/typehaus/_meta.py +28 -0
- typehaus-0.1.0a0/src/typehaus/analysis.py +149 -0
- typehaus-0.1.0a0/src/typehaus/checks/__init__.py +30 -0
- typehaus-0.1.0a0/src/typehaus/checks/advisory/__init__.py +3 -0
- typehaus-0.1.0a0/src/typehaus/checks/advisory/checks.py +297 -0
- typehaus-0.1.0a0/src/typehaus/checks/building_science/__init__.py +5 -0
- typehaus-0.1.0a0/src/typehaus/checks/building_science/condensation.py +221 -0
- typehaus-0.1.0a0/src/typehaus/checks/building_science/glaser.py +403 -0
- typehaus-0.1.0a0/src/typehaus/checks/building_science/wwr.py +112 -0
- typehaus-0.1.0a0/src/typehaus/checks/code/__init__.py +0 -0
- typehaus-0.1.0a0/src/typehaus/checks/code/mn_energy.py +186 -0
- typehaus-0.1.0a0/src/typehaus/checks/code/mn_residential/__init__.py +6 -0
- typehaus-0.1.0a0/src/typehaus/checks/code/mn_residential/profile.py +34 -0
- typehaus-0.1.0a0/src/typehaus/checks/code/mn_residential/rules.py +372 -0
- typehaus-0.1.0a0/src/typehaus/checks/code/site.py +65 -0
- typehaus-0.1.0a0/src/typehaus/checks/integrity/__init__.py +3 -0
- typehaus-0.1.0a0/src/typehaus/checks/integrity/checks.py +120 -0
- typehaus-0.1.0a0/src/typehaus/checks/mep/__init__.py +7 -0
- typehaus-0.1.0a0/src/typehaus/checks/mep/electrical.py +266 -0
- typehaus-0.1.0a0/src/typehaus/checks/mep/hvac.py +76 -0
- typehaus-0.1.0a0/src/typehaus/checks/mep/plumbing.py +272 -0
- typehaus-0.1.0a0/src/typehaus/checks/mep/vent_path.py +107 -0
- typehaus-0.1.0a0/src/typehaus/checks/permit.py +96 -0
- typehaus-0.1.0a0/src/typehaus/checks/pytest_plugin.py +56 -0
- typehaus-0.1.0a0/src/typehaus/checks/registry.py +163 -0
- typehaus-0.1.0a0/src/typehaus/checks/run.py +97 -0
- typehaus-0.1.0a0/src/typehaus/checks/structural/__init__.py +6 -0
- typehaus-0.1.0a0/src/typehaus/checks/structural/checks.py +272 -0
- typehaus-0.1.0a0/src/typehaus/checks/structural/deck.py +451 -0
- typehaus-0.1.0a0/src/typehaus/checks/structural/deck_tables.py +139 -0
- typehaus-0.1.0a0/src/typehaus/checks/structural/interference.py +401 -0
- typehaus-0.1.0a0/src/typehaus/checks/structural/stairs.py +173 -0
- typehaus-0.1.0a0/src/typehaus/cli/__init__.py +7 -0
- typehaus-0.1.0a0/src/typehaus/cli/app.py +904 -0
- typehaus-0.1.0a0/src/typehaus/cli/digest.py +33 -0
- typehaus-0.1.0a0/src/typehaus/cli/furniture_import.py +88 -0
- typehaus-0.1.0a0/src/typehaus/cli/prices.py +190 -0
- typehaus-0.1.0a0/src/typehaus/cli/scaffold.py +276 -0
- typehaus-0.1.0a0/src/typehaus/cli/variants.py +209 -0
- typehaus-0.1.0a0/src/typehaus/diff/__init__.py +39 -0
- typehaus-0.1.0a0/src/typehaus/diff/assembly_compare.py +116 -0
- typehaus-0.1.0a0/src/typehaus/diff/compare.py +301 -0
- typehaus-0.1.0a0/src/typehaus/diff/equivalence.py +283 -0
- typehaus-0.1.0a0/src/typehaus/diff/ifc_adapter.py +299 -0
- typehaus-0.1.0a0/src/typehaus/diff/matcher.py +118 -0
- typehaus-0.1.0a0/src/typehaus/diff/model.py +29 -0
- typehaus-0.1.0a0/src/typehaus/diff/report.py +171 -0
- typehaus-0.1.0a0/src/typehaus/diff/semantic.py +408 -0
- typehaus-0.1.0a0/src/typehaus/diff/variants.py +167 -0
- typehaus-0.1.0a0/src/typehaus/emit/__init__.py +0 -0
- typehaus-0.1.0a0/src/typehaus/emit/draw/__init__.py +38 -0
- typehaus-0.1.0a0/src/typehaus/emit/draw/_shared.py +151 -0
- typehaus-0.1.0a0/src/typehaus/emit/draw/card.py +135 -0
- typehaus-0.1.0a0/src/typehaus/emit/draw/detail_components/__init__.py +215 -0
- typehaus-0.1.0a0/src/typehaus/emit/draw/detail_components/below_grade.py +162 -0
- typehaus-0.1.0a0/src/typehaus/emit/draw/detail_components/breezeway.py +226 -0
- typehaus-0.1.0a0/src/typehaus/emit/draw/detail_components/chrome.py +175 -0
- typehaus-0.1.0a0/src/typehaus/emit/draw/detail_components/config.py +365 -0
- typehaus-0.1.0a0/src/typehaus/emit/draw/detail_components/dispatch.py +187 -0
- typehaus-0.1.0a0/src/typehaus/emit/draw/detail_components/eave.py +122 -0
- typehaus-0.1.0a0/src/typehaus/emit/draw/detail_components/geometry.py +288 -0
- typehaus-0.1.0a0/src/typehaus/emit/draw/detail_components/opening.py +164 -0
- typehaus-0.1.0a0/src/typehaus/emit/draw/detail_components/ridge.py +102 -0
- typehaus-0.1.0a0/src/typehaus/emit/draw/detail_components/sauna.py +247 -0
- typehaus-0.1.0a0/src/typehaus/emit/draw/detail_components/shower.py +215 -0
- typehaus-0.1.0a0/src/typehaus/emit/draw/detail_components/stack.py +152 -0
- typehaus-0.1.0a0/src/typehaus/emit/draw/detail_components/wall_base.py +216 -0
- typehaus-0.1.0a0/src/typehaus/emit/draw/details.py +772 -0
- typehaus-0.1.0a0/src/typehaus/emit/draw/door_symbols.py +320 -0
- typehaus-0.1.0a0/src/typehaus/emit/draw/dxf_writer.py +266 -0
- typehaus-0.1.0a0/src/typehaus/emit/draw/electricalplan.py +77 -0
- typehaus-0.1.0a0/src/typehaus/emit/draw/elevation.py +283 -0
- typehaus-0.1.0a0/src/typehaus/emit/draw/floorplan.py +216 -0
- typehaus-0.1.0a0/src/typehaus/emit/draw/foundation_schedule.py +391 -0
- typehaus-0.1.0a0/src/typehaus/emit/draw/foundationplan.py +312 -0
- typehaus-0.1.0a0/src/typehaus/emit/draw/framing_schedule.py +295 -0
- typehaus-0.1.0a0/src/typehaus/emit/draw/framingplan.py +196 -0
- typehaus-0.1.0a0/src/typehaus/emit/draw/hvacplan.py +89 -0
- typehaus-0.1.0a0/src/typehaus/emit/draw/ir.py +123 -0
- typehaus-0.1.0a0/src/typehaus/emit/draw/joints.py +193 -0
- typehaus-0.1.0a0/src/typehaus/emit/draw/palette.py +190 -0
- typehaus-0.1.0a0/src/typehaus/emit/draw/pdf_writer.py +366 -0
- typehaus-0.1.0a0/src/typehaus/emit/draw/plumbingplan.py +69 -0
- typehaus-0.1.0a0/src/typehaus/emit/draw/render.py +78 -0
- typehaus-0.1.0a0/src/typehaus/emit/draw/roofframingplan.py +251 -0
- typehaus-0.1.0a0/src/typehaus/emit/draw/roofplan.py +31 -0
- typehaus-0.1.0a0/src/typehaus/emit/draw/scene.py +160 -0
- typehaus-0.1.0a0/src/typehaus/emit/draw/schedule_block.py +174 -0
- typehaus-0.1.0a0/src/typehaus/emit/draw/section.py +755 -0
- typehaus-0.1.0a0/src/typehaus/emit/draw/sheets.py +493 -0
- typehaus-0.1.0a0/src/typehaus/emit/draw/siteplan.py +304 -0
- typehaus-0.1.0a0/src/typehaus/emit/draw/structural_common.py +100 -0
- typehaus-0.1.0a0/src/typehaus/emit/gltf/__init__.py +13 -0
- typehaus-0.1.0a0/src/typehaus/emit/gltf/buffers.py +90 -0
- typehaus-0.1.0a0/src/typehaus/emit/gltf/canvas_objects.py +119 -0
- typehaus-0.1.0a0/src/typehaus/emit/gltf/emitter.py +211 -0
- typehaus-0.1.0a0/src/typehaus/emit/gltf/geometry.py +136 -0
- typehaus-0.1.0a0/src/typehaus/emit/gltf/members.py +48 -0
- typehaus-0.1.0a0/src/typehaus/emit/gltf/mesh.py +250 -0
- typehaus-0.1.0a0/src/typehaus/emit/gltf/openings.py +106 -0
- typehaus-0.1.0a0/src/typehaus/emit/gltf/palette.py +218 -0
- typehaus-0.1.0a0/src/typehaus/emit/gltf/roofs.py +236 -0
- typehaus-0.1.0a0/src/typehaus/emit/gltf/scene.py +120 -0
- typehaus-0.1.0a0/src/typehaus/emit/gltf/walls.py +98 -0
- typehaus-0.1.0a0/src/typehaus/emit/ifc/__init__.py +16 -0
- typehaus-0.1.0a0/src/typehaus/emit/ifc/electrical.py +88 -0
- typehaus-0.1.0a0/src/typehaus/emit/ifc/emitter.py +1040 -0
- typehaus-0.1.0a0/src/typehaus/emit/ifc/lowlevel.py +348 -0
- typehaus-0.1.0a0/src/typehaus/emit/ifc/roof.py +325 -0
- typehaus-0.1.0a0/src/typehaus/energy.py +289 -0
- typehaus-0.1.0a0/src/typehaus/findings.py +67 -0
- typehaus-0.1.0a0/src/typehaus/model/__init__.py +239 -0
- typehaus-0.1.0a0/src/typehaus/model/assembly.py +173 -0
- typehaus-0.1.0a0/src/typehaus/model/base.py +48 -0
- typehaus-0.1.0a0/src/typehaus/model/canvas.py +194 -0
- typehaus-0.1.0a0/src/typehaus/model/electrical.py +36 -0
- typehaus-0.1.0a0/src/typehaus/model/elements.py +98 -0
- typehaus-0.1.0a0/src/typehaus/model/enums.py +249 -0
- typehaus-0.1.0a0/src/typehaus/model/floors.py +146 -0
- typehaus-0.1.0a0/src/typehaus/model/ids.py +41 -0
- typehaus-0.1.0a0/src/typehaus/model/materials.py +57 -0
- typehaus-0.1.0a0/src/typehaus/model/mep.py +185 -0
- typehaus-0.1.0a0/src/typehaus/model/patterns.py +14 -0
- typehaus-0.1.0a0/src/typehaus/model/placeable_symbols/__init__.py +99 -0
- typehaus-0.1.0a0/src/typehaus/model/placeable_symbols/_families.py +456 -0
- typehaus-0.1.0a0/src/typehaus/model/placeable_symbols/_frame.py +146 -0
- typehaus-0.1.0a0/src/typehaus/model/placeable_symbols/appliances.py +154 -0
- typehaus-0.1.0a0/src/typehaus/model/placeable_symbols/furniture.py +67 -0
- typehaus-0.1.0a0/src/typehaus/model/placeable_symbols/plumbing.py +243 -0
- typehaus-0.1.0a0/src/typehaus/model/placeables.py +98 -0
- typehaus-0.1.0a0/src/typehaus/model/plan.py +114 -0
- typehaus-0.1.0a0/src/typehaus/model/project.py +85 -0
- typehaus-0.1.0a0/src/typehaus/model/refs.py +95 -0
- typehaus-0.1.0a0/src/typehaus/model/registry.py +90 -0
- typehaus-0.1.0a0/src/typehaus/model/remap.py +158 -0
- typehaus-0.1.0a0/src/typehaus/model/site.py +149 -0
- typehaus-0.1.0a0/src/typehaus/model/spatial.py +172 -0
- typehaus-0.1.0a0/src/typehaus/model/structure.py +275 -0
- typehaus-0.1.0a0/src/typehaus/model/trim.py +146 -0
- typehaus-0.1.0a0/src/typehaus/model/types.py +129 -0
- typehaus-0.1.0a0/src/typehaus/model/views.py +108 -0
- typehaus-0.1.0a0/src/typehaus/quantities/__init__.py +32 -0
- typehaus-0.1.0a0/src/typehaus/quantities/_base.py +77 -0
- typehaus-0.1.0a0/src/typehaus/quantities/angle.py +133 -0
- typehaus-0.1.0a0/src/typehaus/quantities/area.py +84 -0
- typehaus-0.1.0a0/src/typehaus/quantities/length.py +184 -0
- typehaus-0.1.0a0/src/typehaus/quantities/point.py +72 -0
- typehaus-0.1.0a0/src/typehaus/quantities/thermal.py +188 -0
- typehaus-0.1.0a0/src/typehaus/resolve/__init__.py +26 -0
- typehaus-0.1.0a0/src/typehaus/resolve/accessories.py +337 -0
- typehaus-0.1.0a0/src/typehaus/resolve/construction.py +390 -0
- typehaus-0.1.0a0/src/typehaus/resolve/envelope.py +446 -0
- typehaus-0.1.0a0/src/typehaus/resolve/floor_heat.py +45 -0
- typehaus-0.1.0a0/src/typehaus/resolve/floors.py +307 -0
- typehaus-0.1.0a0/src/typehaus/resolve/framing/__init__.py +39 -0
- typehaus-0.1.0a0/src/typehaus/resolve/framing/backing.py +86 -0
- typehaus-0.1.0a0/src/typehaus/resolve/framing/corners.py +125 -0
- typehaus-0.1.0a0/src/typehaus/resolve/framing/footprint.py +66 -0
- typehaus-0.1.0a0/src/typehaus/resolve/framing/openings.py +282 -0
- typehaus-0.1.0a0/src/typehaus/resolve/framing/profiles.py +157 -0
- typehaus-0.1.0a0/src/typehaus/resolve/framing/roof.py +441 -0
- typehaus-0.1.0a0/src/typehaus/resolve/framing/roof_gable.py +253 -0
- typehaus-0.1.0a0/src/typehaus/resolve/framing/solver.py +409 -0
- typehaus-0.1.0a0/src/typehaus/resolve/framing/stud_module.py +98 -0
- typehaus-0.1.0a0/src/typehaus/resolve/framing/tables.py +172 -0
- typehaus-0.1.0a0/src/typehaus/resolve/geometry.py +84 -0
- typehaus-0.1.0a0/src/typehaus/resolve/mep.py +263 -0
- typehaus-0.1.0a0/src/typehaus/resolve/model.py +538 -0
- typehaus-0.1.0a0/src/typehaus/resolve/orientation.py +274 -0
- typehaus-0.1.0a0/src/typehaus/resolve/pipeline.py +270 -0
- typehaus-0.1.0a0/src/typehaus/resolve/placeable_clear_floor_obstruction.py +129 -0
- typehaus-0.1.0a0/src/typehaus/resolve/placeable_groups.py +94 -0
- typehaus-0.1.0a0/src/typehaus/resolve/placeables.py +312 -0
- typehaus-0.1.0a0/src/typehaus/resolve/platform.py +103 -0
- typehaus-0.1.0a0/src/typehaus/resolve/roof_edge.py +195 -0
- typehaus-0.1.0a0/src/typehaus/resolve/roof_edge_geometry.py +286 -0
- typehaus-0.1.0a0/src/typehaus/resolve/roof_geometry.py +184 -0
- typehaus-0.1.0a0/src/typehaus/resolve/roof_layer_setbacks.py +175 -0
- typehaus-0.1.0a0/src/typehaus/resolve/roof_trim.py +379 -0
- typehaus-0.1.0a0/src/typehaus/resolve/rooms.py +84 -0
- typehaus-0.1.0a0/src/typehaus/resolve/site_earth.py +66 -0
- typehaus-0.1.0a0/src/typehaus/resolve/solar.py +91 -0
- typehaus-0.1.0a0/src/typehaus/resolve/stacking.py +118 -0
- typehaus-0.1.0a0/src/typehaus/resolve/stairs/__init__.py +23 -0
- typehaus-0.1.0a0/src/typehaus/resolve/stairs/bearing.py +265 -0
- typehaus-0.1.0a0/src/typehaus/resolve/stairs/common.py +83 -0
- typehaus-0.1.0a0/src/typehaus/resolve/stairs/dispatch.py +197 -0
- typehaus-0.1.0a0/src/typehaus/resolve/stairs/straight.py +53 -0
- typehaus-0.1.0a0/src/typehaus/resolve/stairs/u_split.py +150 -0
- typehaus-0.1.0a0/src/typehaus/resolve/stairs/winder.py +144 -0
- typehaus-0.1.0a0/src/typehaus/resolve/topology.py +697 -0
- typehaus-0.1.0a0/src/typehaus/resolve/vent_termination.py +62 -0
- typehaus-0.1.0a0/src/typehaus/server/__init__.py +0 -0
- typehaus-0.1.0a0/src/typehaus/server/app.py +376 -0
- typehaus-0.1.0a0/src/typehaus/server/building_height_summary.py +76 -0
- typehaus-0.1.0a0/src/typehaus/server/events.py +32 -0
- typehaus-0.1.0a0/src/typehaus/server/macros_api.py +205 -0
- typehaus-0.1.0a0/src/typehaus/server/model_json.py +562 -0
- typehaus-0.1.0a0/src/typehaus/server/space_summary.py +53 -0
- typehaus-0.1.0a0/src/typehaus/server/state.py +370 -0
- typehaus-0.1.0a0/src/typehaus/source/__init__.py +43 -0
- typehaus-0.1.0a0/src/typehaus/source/assembly_ops.py +133 -0
- typehaus-0.1.0a0/src/typehaus/source/bundle.py +328 -0
- typehaus-0.1.0a0/src/typehaus/source/coordinator.py +240 -0
- typehaus-0.1.0a0/src/typehaus/source/detail_ops.py +79 -0
- typehaus-0.1.0a0/src/typehaus/source/dialect.py +219 -0
- typehaus-0.1.0a0/src/typehaus/source/fmt.py +69 -0
- typehaus-0.1.0a0/src/typehaus/source/imported_furniture.py +86 -0
- typehaus-0.1.0a0/src/typehaus/source/imports.py +141 -0
- typehaus-0.1.0a0/src/typehaus/source/imports_py.py +105 -0
- typehaus-0.1.0a0/src/typehaus/source/inmemory.py +178 -0
- typehaus-0.1.0a0/src/typehaus/source/journal.py +60 -0
- typehaus-0.1.0a0/src/typehaus/source/loader.py +397 -0
- typehaus-0.1.0a0/src/typehaus/source/macros.py +871 -0
- typehaus-0.1.0a0/src/typehaus/source/ops.py +194 -0
- typehaus-0.1.0a0/src/typehaus/source/placeable_import.py +397 -0
- typehaus-0.1.0a0/src/typehaus/source/placeables.py +166 -0
- typehaus-0.1.0a0/src/typehaus/source/provenance.py +79 -0
- typehaus-0.1.0a0/src/typehaus/source/serialize.py +105 -0
- typehaus-0.1.0a0/src/typehaus/source/writeback.py +387 -0
- typehaus-0.1.0a0/src/typehaus/source/writeback_py.py +364 -0
- typehaus-0.1.0a0/src/typehaus/takeoff/__init__.py +64 -0
- typehaus-0.1.0a0/src/typehaus/takeoff/anchors.py +258 -0
- typehaus-0.1.0a0/src/typehaus/takeoff/bom.py +71 -0
- typehaus-0.1.0a0/src/typehaus/takeoff/electrical.py +216 -0
- typehaus-0.1.0a0/src/typehaus/takeoff/fasteners.py +171 -0
- typehaus-0.1.0a0/src/typehaus/takeoff/framing.py +234 -0
- typehaus-0.1.0a0/src/typehaus/takeoff/glazing.py +152 -0
- typehaus-0.1.0a0/src/typehaus/takeoff/hangers.py +167 -0
- typehaus-0.1.0a0/src/typehaus/takeoff/hardware.py +36 -0
- typehaus-0.1.0a0/src/typehaus/takeoff/hardware_catalog.py +146 -0
- typehaus-0.1.0a0/src/typehaus/takeoff/hardware_config.py +130 -0
- typehaus-0.1.0a0/src/typehaus/takeoff/placeables.py +53 -0
- typehaus-0.1.0a0/src/typehaus/takeoff/plan_geometry.py +57 -0
- typehaus-0.1.0a0/tests/conftest.py +75 -0
- typehaus-0.1.0a0/tests/fixtures/catlin_reference/README.md +38 -0
- typehaus-0.1.0a0/tests/fixtures/catlin_reference/basementconstruction.json +20 -0
- typehaus-0.1.0a0/tests/fixtures/catlin_reference/basementplan.json +27 -0
- typehaus-0.1.0a0/tests/fixtures/catlin_reference/basementtoframedwalldetail.json +27 -0
- typehaus-0.1.0a0/tests/fixtures/catlin_reference/catlin_house_reference.ifc.gz +0 -0
- typehaus-0.1.0a0/tests/fixtures/catlin_reference/houseframing.json +13 -0
- typehaus-0.1.0a0/tests/fixtures/catlin_reference/images/basement_floor_plan_ifc.png +0 -0
- typehaus-0.1.0a0/tests/fixtures/catlin_reference/images/basement_to_framed_wall_detail_ifc.png +0 -0
- typehaus-0.1.0a0/tests/fixtures/catlin_reference/images/garage_wall_detail_side_ifc.png +0 -0
- typehaus-0.1.0a0/tests/fixtures/catlin_reference/images/roof_wall_eave_detail_ifc.png +0 -0
- typehaus-0.1.0a0/tests/fixtures/catlin_reference/images/sauna_basement_wall_detail_ifc.png +0 -0
- typehaus-0.1.0a0/tests/fixtures/catlin_reference/images/sauna_shower_basement_detail_ifc.png +0 -0
- typehaus-0.1.0a0/tests/fixtures/catlin_reference/saunashowerdetail.json +43 -0
- typehaus-0.1.0a0/tests/fixtures/catlin_reference/scripts/basement_floor_plan_ifc.py +160 -0
- typehaus-0.1.0a0/tests/fixtures/catlin_reference/scripts/basement_to_framed_wall_detail_ifc.py +482 -0
- typehaus-0.1.0a0/tests/fixtures/catlin_reference/scripts/build_catlin_house_ifc.py +25 -0
- typehaus-0.1.0a0/tests/fixtures/catlin_reference/scripts/detail_utils.py +582 -0
- typehaus-0.1.0a0/tests/fixtures/catlin_reference/scripts/garage_wall_detail_side_ifc.py +353 -0
- typehaus-0.1.0a0/tests/fixtures/catlin_reference/scripts/roof_wall_eave_detail_ifc.py +350 -0
- typehaus-0.1.0a0/tests/fixtures/catlin_reference/scripts/sauna_basement_wall_detail_ifc.py +405 -0
- typehaus-0.1.0a0/tests/fixtures/catlin_reference/scripts/sauna_shower_basement_detail_ifc.py +465 -0
- typehaus-0.1.0a0/tests/test_accessories.py +352 -0
- typehaus-0.1.0a0/tests/test_building_height_summary.py +62 -0
- typehaus-0.1.0a0/tests/test_building_science_m5.py +263 -0
- typehaus-0.1.0a0/tests/test_building_science_monthly_gate.py +259 -0
- typehaus-0.1.0a0/tests/test_bundle_portability.py +181 -0
- typehaus-0.1.0a0/tests/test_canvas_placeables.py +420 -0
- typehaus-0.1.0a0/tests/test_catlin_contract_m3.py +792 -0
- typehaus-0.1.0a0/tests/test_catlin_equivalence_m3.py +376 -0
- typehaus-0.1.0a0/tests/test_catlin_outdoor_structures.py +158 -0
- typehaus-0.1.0a0/tests/test_catlin_reference_parity.py +238 -0
- typehaus-0.1.0a0/tests/test_cavity_fill.py +128 -0
- typehaus-0.1.0a0/tests/test_construction_rules.py +101 -0
- typehaus-0.1.0a0/tests/test_detail_server.py +55 -0
- typehaus-0.1.0a0/tests/test_detail_sheets.py +67 -0
- typehaus-0.1.0a0/tests/test_detail_vocabulary.py +649 -0
- typehaus-0.1.0a0/tests/test_dialect.py +47 -0
- typehaus-0.1.0a0/tests/test_diff_m2.py +86 -0
- typehaus-0.1.0a0/tests/test_doors.py +403 -0
- typehaus-0.1.0a0/tests/test_draw_m2.py +112 -0
- typehaus-0.1.0a0/tests/test_editable_guard.py +63 -0
- typehaus-0.1.0a0/tests/test_electrical_circuits.py +380 -0
- typehaus-0.1.0a0/tests/test_electrical_plan.py +140 -0
- typehaus-0.1.0a0/tests/test_elevation_annotations.py +93 -0
- typehaus-0.1.0a0/tests/test_energy_sheet.py +151 -0
- typehaus-0.1.0a0/tests/test_envelope_resolution.py +107 -0
- typehaus-0.1.0a0/tests/test_floor_opening_framing.py +143 -0
- typehaus-0.1.0a0/tests/test_foundation_plan.py +141 -0
- typehaus-0.1.0a0/tests/test_framing_plan.py +113 -0
- typehaus-0.1.0a0/tests/test_framing_takeoff.py +114 -0
- typehaus-0.1.0a0/tests/test_generated_provenance.py +96 -0
- typehaus-0.1.0a0/tests/test_gltf_opening_fillings.py +297 -0
- typehaus-0.1.0a0/tests/test_hardware_takeoff.py +291 -0
- typehaus-0.1.0a0/tests/test_header_spec_framing.py +146 -0
- typehaus-0.1.0a0/tests/test_hvac_plan.py +59 -0
- typehaus-0.1.0a0/tests/test_ifc_mep.py +118 -0
- typehaus-0.1.0a0/tests/test_ifc_openings.py +133 -0
- typehaus-0.1.0a0/tests/test_ifc_roof.py +168 -0
- typehaus-0.1.0a0/tests/test_ifc_site.py +53 -0
- typehaus-0.1.0a0/tests/test_inmemory_equivalence.py +88 -0
- typehaus-0.1.0a0/tests/test_junction_solver.py +257 -0
- typehaus-0.1.0a0/tests/test_macros_gltf_m2.py +712 -0
- typehaus-0.1.0a0/tests/test_masonry_finish.py +147 -0
- typehaus-0.1.0a0/tests/test_member_interference.py +193 -0
- typehaus-0.1.0a0/tests/test_mep_hvac.py +99 -0
- typehaus-0.1.0a0/tests/test_mep_plumbing.py +447 -0
- typehaus-0.1.0a0/tests/test_model_and_emit.py +86 -0
- typehaus-0.1.0a0/tests/test_model_json.py +306 -0
- typehaus-0.1.0a0/tests/test_palette_parity.py +75 -0
- typehaus-0.1.0a0/tests/test_placeable_clear_floor_obstruction.py +240 -0
- typehaus-0.1.0a0/tests/test_placeable_groups.py +150 -0
- typehaus-0.1.0a0/tests/test_placeable_import.py +204 -0
- typehaus-0.1.0a0/tests/test_placeable_symbols.py +107 -0
- typehaus-0.1.0a0/tests/test_platform_continuity.py +65 -0
- typehaus-0.1.0a0/tests/test_plumbing_plan.py +86 -0
- typehaus-0.1.0a0/tests/test_prices_takeoff.py +146 -0
- typehaus-0.1.0a0/tests/test_profiles.py +103 -0
- typehaus-0.1.0a0/tests/test_quantities.py +32 -0
- typehaus-0.1.0a0/tests/test_resolve_and_checks.py +116 -0
- typehaus-0.1.0a0/tests/test_roof_gable_and_heel.py +760 -0
- typehaus-0.1.0a0/tests/test_scaffold_m2.py +52 -0
- typehaus-0.1.0a0/tests/test_semantic_equivalence.py +163 -0
- typehaus-0.1.0a0/tests/test_server_m2.py +195 -0
- typehaus-0.1.0a0/tests/test_sheet_index.py +76 -0
- typehaus-0.1.0a0/tests/test_site_checks.py +138 -0
- typehaus-0.1.0a0/tests/test_site_earth.py +102 -0
- typehaus-0.1.0a0/tests/test_site_plan.py +137 -0
- typehaus-0.1.0a0/tests/test_solar.py +166 -0
- typehaus-0.1.0a0/tests/test_solver_units.py +164 -0
- typehaus-0.1.0a0/tests/test_stair_framing.py +558 -0
- typehaus-0.1.0a0/tests/test_stair_landing_post_bearing.py +122 -0
- typehaus-0.1.0a0/tests/test_stair_tread_geometry.py +169 -0
- typehaus-0.1.0a0/tests/test_storey_component_windings.py +123 -0
- typehaus-0.1.0a0/tests/test_structural_sheets.py +296 -0
- typehaus-0.1.0a0/tests/test_transition_details.py +212 -0
- typehaus-0.1.0a0/tests/test_variant_compare.py +69 -0
- typehaus-0.1.0a0/tests/test_variants_m2.py +191 -0
- typehaus-0.1.0a0/tests/test_wall_corner_and_opening_framing.py +300 -0
- typehaus-0.1.0a0/tests/test_wall_interior_room.py +81 -0
- typehaus-0.1.0a0/tests/test_writeback.py +164 -0
- typehaus-0.1.0a0/tests/test_writeback_parity.py +116 -0
- typehaus-0.1.0a0/tests/test_writer_layer_coverage.py +51 -0
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
# Byte-compiled / optimized / DLL files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
|
|
6
|
+
# C extensions
|
|
7
|
+
*.so
|
|
8
|
+
|
|
9
|
+
# Distribution / packaging
|
|
10
|
+
.Python
|
|
11
|
+
build/
|
|
12
|
+
develop-eggs/
|
|
13
|
+
dist/
|
|
14
|
+
downloads/
|
|
15
|
+
eggs/
|
|
16
|
+
.eggs/
|
|
17
|
+
lib/
|
|
18
|
+
lib64/
|
|
19
|
+
parts/
|
|
20
|
+
sdist/
|
|
21
|
+
var/
|
|
22
|
+
wheels/
|
|
23
|
+
share/python-wheels/
|
|
24
|
+
*.egg-info/
|
|
25
|
+
.installed.cfg
|
|
26
|
+
*.egg
|
|
27
|
+
MANIFEST
|
|
28
|
+
|
|
29
|
+
# PyInstaller
|
|
30
|
+
# Usually these files are written by a python script from a template
|
|
31
|
+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
|
32
|
+
*.manifest
|
|
33
|
+
*.spec
|
|
34
|
+
|
|
35
|
+
# Installer logs
|
|
36
|
+
pip-log.txt
|
|
37
|
+
pip-delete-this-directory.txt
|
|
38
|
+
|
|
39
|
+
# Unit test / coverage reports
|
|
40
|
+
htmlcov/
|
|
41
|
+
.tox/
|
|
42
|
+
.nox/
|
|
43
|
+
.coverage
|
|
44
|
+
.coverage.*
|
|
45
|
+
.cache
|
|
46
|
+
nosetests.xml
|
|
47
|
+
coverage.xml
|
|
48
|
+
*.cover
|
|
49
|
+
*.py,cover
|
|
50
|
+
.hypothesis/
|
|
51
|
+
.pytest_cache/
|
|
52
|
+
cover/
|
|
53
|
+
|
|
54
|
+
# Translations
|
|
55
|
+
*.mo
|
|
56
|
+
*.pot
|
|
57
|
+
|
|
58
|
+
# Django stuff:
|
|
59
|
+
*.log
|
|
60
|
+
local_settings.py
|
|
61
|
+
db.sqlite3
|
|
62
|
+
db.sqlite3-journal
|
|
63
|
+
|
|
64
|
+
# Flask stuff:
|
|
65
|
+
instance/
|
|
66
|
+
.webassets-cache
|
|
67
|
+
|
|
68
|
+
# Scrapy stuff:
|
|
69
|
+
.scrapy
|
|
70
|
+
|
|
71
|
+
# Sphinx documentation
|
|
72
|
+
docs/_build/
|
|
73
|
+
|
|
74
|
+
# PyBuilder
|
|
75
|
+
.pybuilder/
|
|
76
|
+
target/
|
|
77
|
+
|
|
78
|
+
# Jupyter Notebook
|
|
79
|
+
.ipynb_checkpoints
|
|
80
|
+
|
|
81
|
+
# IPython
|
|
82
|
+
profile_default/
|
|
83
|
+
ipython_config.py
|
|
84
|
+
|
|
85
|
+
# pyenv
|
|
86
|
+
# For a library or package, you might want to ignore these files since the code is
|
|
87
|
+
# intended to run in multiple environments; otherwise, check them in:
|
|
88
|
+
# .python-version
|
|
89
|
+
|
|
90
|
+
# pipenv
|
|
91
|
+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
|
92
|
+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
|
93
|
+
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
|
94
|
+
# install all needed dependencies.
|
|
95
|
+
#Pipfile.lock
|
|
96
|
+
|
|
97
|
+
# UV
|
|
98
|
+
# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
|
|
99
|
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
100
|
+
# commonly ignored for libraries.
|
|
101
|
+
#uv.lock
|
|
102
|
+
|
|
103
|
+
# poetry
|
|
104
|
+
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
|
105
|
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
106
|
+
# commonly ignored for libraries.
|
|
107
|
+
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
|
108
|
+
#poetry.lock
|
|
109
|
+
|
|
110
|
+
# pdm
|
|
111
|
+
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
|
112
|
+
#pdm.lock
|
|
113
|
+
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
|
|
114
|
+
# in version control.
|
|
115
|
+
# https://pdm.fming.dev/latest/usage/project/#working-with-version-control
|
|
116
|
+
.pdm.toml
|
|
117
|
+
.pdm-python
|
|
118
|
+
.pdm-build/
|
|
119
|
+
|
|
120
|
+
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
|
121
|
+
__pypackages__/
|
|
122
|
+
|
|
123
|
+
# Celery stuff
|
|
124
|
+
celerybeat-schedule
|
|
125
|
+
celerybeat.pid
|
|
126
|
+
|
|
127
|
+
# SageMath parsed files
|
|
128
|
+
*.sage.py
|
|
129
|
+
|
|
130
|
+
# Environments
|
|
131
|
+
.env
|
|
132
|
+
.venv
|
|
133
|
+
env/
|
|
134
|
+
venv/
|
|
135
|
+
ENV/
|
|
136
|
+
env.bak/
|
|
137
|
+
venv.bak/
|
|
138
|
+
|
|
139
|
+
# Spyder project settings
|
|
140
|
+
.spyderproject
|
|
141
|
+
.spyproject
|
|
142
|
+
|
|
143
|
+
# Rope project settings
|
|
144
|
+
.ropeproject
|
|
145
|
+
|
|
146
|
+
# mkdocs documentation
|
|
147
|
+
/site
|
|
148
|
+
|
|
149
|
+
# mypy
|
|
150
|
+
.mypy_cache/
|
|
151
|
+
.dmypy.json
|
|
152
|
+
dmypy.json
|
|
153
|
+
|
|
154
|
+
# Pyre type checker
|
|
155
|
+
.pyre/
|
|
156
|
+
|
|
157
|
+
# pytype static type analyzer
|
|
158
|
+
.pytype/
|
|
159
|
+
|
|
160
|
+
# Cython debug symbols
|
|
161
|
+
cython_debug/
|
|
162
|
+
|
|
163
|
+
# PyCharm
|
|
164
|
+
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
|
165
|
+
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
|
166
|
+
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
|
167
|
+
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
|
168
|
+
#.idea/
|
|
169
|
+
|
|
170
|
+
# Ruff stuff:
|
|
171
|
+
.ruff_cache/
|
|
172
|
+
|
|
173
|
+
# PyPI configuration file
|
|
174
|
+
.pypirc
|
|
175
|
+
|
|
176
|
+
# Cursor
|
|
177
|
+
# Cursor is an AI-powered code editor.`.cursorignore` specifies files/directories to
|
|
178
|
+
# exclude from AI features like autocomplete and code analysis. Recommended for sensitive data
|
|
179
|
+
# refer to https://docs.cursor.com/context/ignore-files
|
|
180
|
+
.cursorignore
|
|
181
|
+
.cursorindexingignore
|
|
182
|
+
|
|
183
|
+
**/.DS_Store
|
|
184
|
+
|
|
185
|
+
# build artifacts
|
|
186
|
+
houses/*/out/
|
|
187
|
+
**/out/
|
|
188
|
+
.venv/
|
|
189
|
+
|
|
190
|
+
# Generated by ui/scripts/build-pwa-assets.mjs (M4 offline engine bundle)
|
|
191
|
+
ui/public/typehaus-engine.tar
|
|
192
|
+
ui/public/typehaus-ifc-ext.tar
|
|
193
|
+
# Generated by ui/scripts/build-house-asset.mjs (U9 bundled default house)
|
|
194
|
+
ui/public/catlin-house.json
|
|
195
|
+
|
|
196
|
+
# Source trees are never build output. The Python-packaging patterns above (build/, lib/,
|
|
197
|
+
# dist/, parts/, var/, target/, instance/, cover/) are unanchored, so they match at ANY
|
|
198
|
+
# depth — `ui/src/three/build/` was silently swallowed once already, and the commit shipped
|
|
199
|
+
# importing five modules that git never took. These negations make that structurally
|
|
200
|
+
# impossible; `ui/dist` and `packages/**/build` still ignore normally.
|
|
201
|
+
!ui/src/**
|
|
202
|
+
!packages/*/src/**
|
|
203
|
+
!library/**
|
|
204
|
+
!houses/*/plan/**
|
|
205
|
+
!houses/*/params/**
|
|
206
|
+
# ...but re-ignore the genuine artifacts that live *inside* those trees, since a negation
|
|
207
|
+
# re-admits everything it covers, including caches and compiled output.
|
|
208
|
+
__pycache__/
|
|
209
|
+
*.py[cod]
|
|
210
|
+
*.tsbuildinfo
|
|
211
|
+
.DS_Store
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: typehaus
|
|
3
|
+
Version: 0.1.0a0
|
|
4
|
+
Summary: Type:Haus — infrastructure-as-code for residential houses. Pre-alpha.
|
|
5
|
+
Project-URL: Homepage, https://type-haus.com
|
|
6
|
+
Author-email: Colin Catlin <colin.catlin@gmail.com>
|
|
7
|
+
License: MIT
|
|
8
|
+
Keywords: BIM,CAD,IFC,architecture,infrastructure-as-code,residential
|
|
9
|
+
Classifier: Development Status :: 2 - Pre-Alpha
|
|
10
|
+
Classifier: Intended Audience :: Developers
|
|
11
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
15
|
+
Classifier: Topic :: Scientific/Engineering
|
|
16
|
+
Requires-Python: >=3.11
|
|
17
|
+
Requires-Dist: ezdxf>=1.1
|
|
18
|
+
Requires-Dist: ifcopenshell<0.9,>=0.8
|
|
19
|
+
Requires-Dist: libcst>=1.1
|
|
20
|
+
Requires-Dist: matplotlib>=3.8
|
|
21
|
+
Requires-Dist: pydantic>=2.6
|
|
22
|
+
Requires-Dist: pyproj>=3.6
|
|
23
|
+
Requires-Dist: rich>=13.0
|
|
24
|
+
Requires-Dist: shapely>=2.0
|
|
25
|
+
Requires-Dist: trimesh>=4.0
|
|
26
|
+
Requires-Dist: typer>=0.12
|
|
27
|
+
Provides-Extra: dev
|
|
28
|
+
Requires-Dist: fastapi>=0.110; extra == 'dev'
|
|
29
|
+
Requires-Dist: httpx>=0.27; extra == 'dev'
|
|
30
|
+
Requires-Dist: hypothesis>=6.90; extra == 'dev'
|
|
31
|
+
Requires-Dist: mypy>=1.9; extra == 'dev'
|
|
32
|
+
Requires-Dist: pytest>=8.0; extra == 'dev'
|
|
33
|
+
Requires-Dist: ruff>=0.4; extra == 'dev'
|
|
34
|
+
Requires-Dist: uvicorn>=0.29; extra == 'dev'
|
|
35
|
+
Requires-Dist: watchfiles>=0.21; extra == 'dev'
|
|
36
|
+
Requires-Dist: websockets>=12; extra == 'dev'
|
|
37
|
+
Provides-Extra: server
|
|
38
|
+
Requires-Dist: fastapi>=0.110; extra == 'server'
|
|
39
|
+
Requires-Dist: uvicorn>=0.29; extra == 'server'
|
|
40
|
+
Requires-Dist: watchfiles>=0.21; extra == 'server'
|
|
41
|
+
Requires-Dist: websockets>=12; extra == 'server'
|
|
42
|
+
Description-Content-Type: text/markdown
|
|
43
|
+
|
|
44
|
+
# typehaus
|
|
45
|
+
|
|
46
|
+
The Type:Haus engine — infrastructure-as-code for residential houses. Author a house plan as
|
|
47
|
+
typed, declarative Python; resolve topology, stacking, and framing; emit an IFC4 model,
|
|
48
|
+
`model.json`, and assembly section cards; and run integrity / code / structural checks.
|
|
49
|
+
|
|
50
|
+
> **Pre-alpha.** APIs, schema, and outputs change without notice. Not for production use.
|
|
51
|
+
|
|
52
|
+
This is the Python package behind the `haus` CLI. See the repository root and `docs/plan/`
|
|
53
|
+
for the full design documentation and monorepo layout.
|
|
54
|
+
|
|
55
|
+
## Install
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
pip install -e packages/engine # from the repo root
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## CLI
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
haus ls houses/starter --summary # compact plan digest
|
|
65
|
+
haus build houses/starter # -> out/model.json (+ IFC when ifcopenshell present)
|
|
66
|
+
haus check houses/starter # integrity/code/advisory/structural findings
|
|
67
|
+
haus explain HOUSE_WALL_2X6_WITH_ZIPR houses/starter --card
|
|
68
|
+
haus explain transitions houses/starter # derived boundary conditions
|
|
69
|
+
|
|
70
|
+
# M2 — the loop closes
|
|
71
|
+
haus new my-house --name "My House" # scaffold a self-contained house
|
|
72
|
+
haus serve houses/starter # FastAPI: model.json, PATCH /plan, undo/redo, live reload
|
|
73
|
+
haus render houses/starter --view plan # -> out/render/plan_*.png (agent eyes, #52)
|
|
74
|
+
haus print houses/starter # -> out/sheets/plan_*.dxf + .pdf (AIA layers)
|
|
75
|
+
haus fmt houses/starter # assign missing uids (merge-friendly canonical)
|
|
76
|
+
haus diff architect.ifc houses/starter # semantic diff -> out/diff.json + table
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
IFC emission (and `haus diff`'s external-IFC read) requires `ifcopenshell` (pin `0.8.x`);
|
|
80
|
+
when it is absent, `haus build` still writes `model.json` and reports the skipped IFC step.
|
|
81
|
+
The server is an optional extra: `pip install -e 'packages/engine[server]'`.
|
|
82
|
+
|
|
83
|
+
### The `model.json` contract + write safety (M2)
|
|
84
|
+
|
|
85
|
+
`haus serve` exposes the resolved `model.json` (revision hash, per-element provenance, live
|
|
86
|
+
findings). Every `PATCH /plan` carries the project revision as a precondition (stale → 409),
|
|
87
|
+
applies element-level ops through the libcst writeback (comments/formatting preserved),
|
|
88
|
+
stages + validates the whole project, then writes each file atomically. Undo/redo is
|
|
89
|
+
server-owned (the file is the state); an external VSCode/Claude edit seals the journal.
|
|
90
|
+
|
|
91
|
+
## License
|
|
92
|
+
|
|
93
|
+
MIT © Colin Catlin.
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# typehaus
|
|
2
|
+
|
|
3
|
+
The Type:Haus engine — infrastructure-as-code for residential houses. Author a house plan as
|
|
4
|
+
typed, declarative Python; resolve topology, stacking, and framing; emit an IFC4 model,
|
|
5
|
+
`model.json`, and assembly section cards; and run integrity / code / structural checks.
|
|
6
|
+
|
|
7
|
+
> **Pre-alpha.** APIs, schema, and outputs change without notice. Not for production use.
|
|
8
|
+
|
|
9
|
+
This is the Python package behind the `haus` CLI. See the repository root and `docs/plan/`
|
|
10
|
+
for the full design documentation and monorepo layout.
|
|
11
|
+
|
|
12
|
+
## Install
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
pip install -e packages/engine # from the repo root
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## CLI
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
haus ls houses/starter --summary # compact plan digest
|
|
22
|
+
haus build houses/starter # -> out/model.json (+ IFC when ifcopenshell present)
|
|
23
|
+
haus check houses/starter # integrity/code/advisory/structural findings
|
|
24
|
+
haus explain HOUSE_WALL_2X6_WITH_ZIPR houses/starter --card
|
|
25
|
+
haus explain transitions houses/starter # derived boundary conditions
|
|
26
|
+
|
|
27
|
+
# M2 — the loop closes
|
|
28
|
+
haus new my-house --name "My House" # scaffold a self-contained house
|
|
29
|
+
haus serve houses/starter # FastAPI: model.json, PATCH /plan, undo/redo, live reload
|
|
30
|
+
haus render houses/starter --view plan # -> out/render/plan_*.png (agent eyes, #52)
|
|
31
|
+
haus print houses/starter # -> out/sheets/plan_*.dxf + .pdf (AIA layers)
|
|
32
|
+
haus fmt houses/starter # assign missing uids (merge-friendly canonical)
|
|
33
|
+
haus diff architect.ifc houses/starter # semantic diff -> out/diff.json + table
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
IFC emission (and `haus diff`'s external-IFC read) requires `ifcopenshell` (pin `0.8.x`);
|
|
37
|
+
when it is absent, `haus build` still writes `model.json` and reports the skipped IFC step.
|
|
38
|
+
The server is an optional extra: `pip install -e 'packages/engine[server]'`.
|
|
39
|
+
|
|
40
|
+
### The `model.json` contract + write safety (M2)
|
|
41
|
+
|
|
42
|
+
`haus serve` exposes the resolved `model.json` (revision hash, per-element provenance, live
|
|
43
|
+
findings). Every `PATCH /plan` carries the project revision as a precondition (stale → 409),
|
|
44
|
+
applies element-level ops through the libcst writeback (comments/formatting preserved),
|
|
45
|
+
stages + validates the whole project, then writes each file atomically. Undo/redo is
|
|
46
|
+
server-owned (the file is the state); an external VSCode/Claude edit seals the journal.
|
|
47
|
+
|
|
48
|
+
## License
|
|
49
|
+
|
|
50
|
+
MIT © Colin Catlin.
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "typehaus"
|
|
7
|
+
version = "0.1.0a0"
|
|
8
|
+
description = "Type:Haus — infrastructure-as-code for residential houses. Pre-alpha."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = { text = "MIT" }
|
|
11
|
+
authors = [{ name = "Colin Catlin", email = "colin.catlin@gmail.com" }]
|
|
12
|
+
requires-python = ">=3.11"
|
|
13
|
+
keywords = ["architecture", "BIM", "IFC", "residential", "infrastructure-as-code", "CAD"]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Development Status :: 2 - Pre-Alpha",
|
|
16
|
+
"Intended Audience :: Developers",
|
|
17
|
+
"License :: OSI Approved :: MIT License",
|
|
18
|
+
"Programming Language :: Python :: 3",
|
|
19
|
+
"Programming Language :: Python :: 3.11",
|
|
20
|
+
"Programming Language :: Python :: 3.12",
|
|
21
|
+
"Topic :: Scientific/Engineering",
|
|
22
|
+
]
|
|
23
|
+
dependencies = [
|
|
24
|
+
"pydantic>=2.6",
|
|
25
|
+
"typer>=0.12",
|
|
26
|
+
"rich>=13.0",
|
|
27
|
+
"shapely>=2.0",
|
|
28
|
+
"libcst>=1.1",
|
|
29
|
+
"ifcopenshell>=0.8,<0.9",
|
|
30
|
+
"ezdxf>=1.1",
|
|
31
|
+
"matplotlib>=3.8",
|
|
32
|
+
"pyproj>=3.6",
|
|
33
|
+
"trimesh>=4.0",
|
|
34
|
+
]
|
|
35
|
+
|
|
36
|
+
[project.optional-dependencies]
|
|
37
|
+
# The FastAPI server (`haus serve`) + live-reload watcher — optional so a headless
|
|
38
|
+
# build/check/render install stays lean (→ 20 §FastAPI server).
|
|
39
|
+
# `websockets` is required for the `/events` live-reload socket — bare `uvicorn`
|
|
40
|
+
# ships no WS implementation and rejects every upgrade with 403.
|
|
41
|
+
server = ["fastapi>=0.110", "uvicorn>=0.29", "websockets>=12", "watchfiles>=0.21"]
|
|
42
|
+
dev = [
|
|
43
|
+
"pytest>=8.0", "hypothesis>=6.90", "mypy>=1.9", "ruff>=0.4",
|
|
44
|
+
"fastapi>=0.110", "uvicorn>=0.29", "websockets>=12", "watchfiles>=0.21", "httpx>=0.27",
|
|
45
|
+
]
|
|
46
|
+
|
|
47
|
+
[project.urls]
|
|
48
|
+
Homepage = "https://type-haus.com"
|
|
49
|
+
|
|
50
|
+
[project.scripts]
|
|
51
|
+
haus = "typehaus.cli.app:main"
|
|
52
|
+
|
|
53
|
+
[project.entry-points.pytest11]
|
|
54
|
+
typehaus_checks = "typehaus.checks.pytest_plugin"
|
|
55
|
+
|
|
56
|
+
[tool.hatch.build.targets.wheel]
|
|
57
|
+
packages = ["src/typehaus"]
|
|
58
|
+
# The pre-built UI ships inside the wheel so `pip install typehaus && haus serve`
|
|
59
|
+
# works without node (→ 02 §Repo layout).
|
|
60
|
+
artifacts = ["src/typehaus/server/static/**"]
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
"""Rebuild/resolve micro-benchmark (Phase 0 instrumentation → responsiveness plan).
|
|
2
|
+
|
|
3
|
+
Opens a house, runs N full rebuilds and one simulated ``move_nodes`` patch, and prints
|
|
4
|
+
per-stage medians so each later optimization phase is measured, not assumed.
|
|
5
|
+
|
|
6
|
+
Run with the repo .venv::
|
|
7
|
+
|
|
8
|
+
PYTHONPATH=packages/engine/src .venv/bin/python packages/engine/scripts/bench_rebuild.py \
|
|
9
|
+
--house houses/catlin --iters 15
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
|
|
14
|
+
import argparse
|
|
15
|
+
import statistics
|
|
16
|
+
import time
|
|
17
|
+
from pathlib import Path
|
|
18
|
+
|
|
19
|
+
from typehaus.server.macros_api import build_macro_ops
|
|
20
|
+
from typehaus.server.state import ProjectState
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def _median_timings(runs: list[dict[str, float]]) -> dict[str, float]:
|
|
24
|
+
keys = sorted({k for r in runs for k in r})
|
|
25
|
+
return {k: statistics.median([r[k] for r in runs if k in r]) for k in keys}
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def _print_table(title: str, timings: dict[str, float]) -> None:
|
|
29
|
+
print(f"\n== {title} ==")
|
|
30
|
+
for k, v in sorted(timings.items(), key=lambda kv: -kv[1]):
|
|
31
|
+
print(f" {v:8.2f} ms {k}")
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def main() -> None:
|
|
35
|
+
ap = argparse.ArgumentParser()
|
|
36
|
+
ap.add_argument("--house", default="houses/catlin")
|
|
37
|
+
ap.add_argument("--iters", type=int, default=15)
|
|
38
|
+
ap.add_argument("--storey", default="main")
|
|
39
|
+
ap.add_argument("--node", default="N-M-S1")
|
|
40
|
+
args = ap.parse_args()
|
|
41
|
+
|
|
42
|
+
house = Path(args.house).resolve()
|
|
43
|
+
print(f"opening {house} ...")
|
|
44
|
+
state = ProjectState.open(house)
|
|
45
|
+
plan = state.model.plan if state.model else None
|
|
46
|
+
n_walls = len(state.model.walls) if state.model else 0
|
|
47
|
+
print(f"opened: {n_walls} resolved walls, ok={state.ok}")
|
|
48
|
+
|
|
49
|
+
# --- N plain rebuilds (load_plan + resolve + checks) ---
|
|
50
|
+
rebuild_runs: list[dict[str, float]] = []
|
|
51
|
+
wall_times: list[float] = []
|
|
52
|
+
for _ in range(args.iters):
|
|
53
|
+
t0 = time.perf_counter()
|
|
54
|
+
state.rebuild()
|
|
55
|
+
wall_times.append((time.perf_counter() - t0) * 1000.0)
|
|
56
|
+
rebuild_runs.append(dict(state.timings))
|
|
57
|
+
print(f"\nfull rebuild wall time: median {statistics.median(wall_times):.1f} ms "
|
|
58
|
+
f"(min {min(wall_times):.1f}, max {max(wall_times):.1f})")
|
|
59
|
+
_print_table("rebuild stage medians", _median_timings(rebuild_runs))
|
|
60
|
+
|
|
61
|
+
# --- one simulated move_nodes patch via the slow path (writeback + rebuild), then undo ---
|
|
62
|
+
if plan is not None:
|
|
63
|
+
body = {"macro": "move_nodes", "storey": args.storey,
|
|
64
|
+
"nodes": [args.node], "dx": 0.01, "dy": 0.0}
|
|
65
|
+
patch_runs: list[dict[str, float]] = []
|
|
66
|
+
commit_times: list[float] = []
|
|
67
|
+
for _ in range(min(args.iters, 8)):
|
|
68
|
+
t0 = time.perf_counter()
|
|
69
|
+
result = build_macro_ops(state.model.plan, body)
|
|
70
|
+
state.coordinator.apply_patch(result.ops, None)
|
|
71
|
+
state.rebuild()
|
|
72
|
+
commit_times.append((time.perf_counter() - t0) * 1000.0)
|
|
73
|
+
patch_runs.append(dict(state.timings))
|
|
74
|
+
state.coordinator.undo()
|
|
75
|
+
state.rebuild()
|
|
76
|
+
print(f"\nmove_nodes commit wall time (slow path, writeback+rebuild): median "
|
|
77
|
+
f"{statistics.median(commit_times):.1f} ms")
|
|
78
|
+
_print_table("patch-triggered rebuild stage medians",
|
|
79
|
+
_median_timings(patch_runs))
|
|
80
|
+
|
|
81
|
+
# --- the same macro via the fast path (Phase 2b: in-memory apply, async writeback) ---
|
|
82
|
+
fast_times: list[float] = []
|
|
83
|
+
for _ in range(min(args.iters, 8)):
|
|
84
|
+
result = build_macro_ops(state.model.plan, body)
|
|
85
|
+
t0 = time.perf_counter()
|
|
86
|
+
state.apply_edit(result.ops, None)
|
|
87
|
+
fast_times.append((time.perf_counter() - t0) * 1000.0)
|
|
88
|
+
state._flush_writes() # keep source/plan settled before the next undo
|
|
89
|
+
state.history(undo=True)
|
|
90
|
+
print(f"\nmove_nodes commit wall time (fast path, in-memory apply): median "
|
|
91
|
+
f"{statistics.median(fast_times):.1f} ms")
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
if __name__ == "__main__":
|
|
95
|
+
main()
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"""Type:Haus engine — typed declarative residential house modeling.
|
|
2
|
+
|
|
3
|
+
The public authoring surface (everything the plan dialect may import) is re-exported
|
|
4
|
+
here from ``typehaus.model``. Plan files import from ``typehaus`` and ``library``.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from typehaus._meta import PROJECT_NAME, engine_version
|
|
10
|
+
from typehaus.model import * # noqa: F401,F403 — re-export the authoring surface
|
|
11
|
+
from typehaus.model import __all__ as _model_all
|
|
12
|
+
|
|
13
|
+
__version__ = engine_version()
|
|
14
|
+
|
|
15
|
+
__all__ = ["PROJECT_NAME", "engine_version", "__version__", *_model_all]
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"""Brand-name and build-identity constants, centralized for cheap rename (→ 01 §Naming).
|
|
2
|
+
|
|
3
|
+
A rename touches only this file, the ``pyproject.toml`` ``name``, the ``src/typehaus``
|
|
4
|
+
directory, and the UI ``branding.ts`` — see ``docs/RENAME.md``.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from importlib.metadata import PackageNotFoundError, version
|
|
10
|
+
|
|
11
|
+
PROJECT_NAME = "Type:Haus"
|
|
12
|
+
PROJECT_SLUG = "typehaus"
|
|
13
|
+
PROJECT_URL = "https://type-haus.com"
|
|
14
|
+
CLI_NAME = "haus"
|
|
15
|
+
|
|
16
|
+
# IFC header application name and pset prefix. The prefix is kept short and
|
|
17
|
+
# brand-agnostic so the emitted IFC does not churn on a rename (→ 01 §Naming).
|
|
18
|
+
IFC_APP_NAME = "Type:Haus"
|
|
19
|
+
PSET_PREFIX = "Pset_TH"
|
|
20
|
+
PSET_SOURCE = f"{PSET_PREFIX}_Source"
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def engine_version() -> str:
|
|
24
|
+
"""Installed engine version, or a dev sentinel when running from a source tree."""
|
|
25
|
+
try:
|
|
26
|
+
return version(PROJECT_SLUG)
|
|
27
|
+
except PackageNotFoundError:
|
|
28
|
+
return "0.0.0+dev"
|