astichi 0.1.0__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.
Files changed (260) hide show
  1. astichi-0.1.0/.gitignore +14 -0
  2. astichi-0.1.0/LICENSE +21 -0
  3. astichi-0.1.0/PKG-INFO +310 -0
  4. astichi-0.1.0/README.md +267 -0
  5. astichi-0.1.0/astichi/__init__.py +17 -0
  6. astichi-0.1.0/astichi/ast_provenance.py +131 -0
  7. astichi-0.1.0/astichi/asttools/__init__.py +40 -0
  8. astichi-0.1.0/astichi/asttools/imports.py +47 -0
  9. astichi-0.1.0/astichi/asttools/inserts.py +33 -0
  10. astichi-0.1.0/astichi/asttools/scopes.py +157 -0
  11. astichi-0.1.0/astichi/asttools/shapes.py +86 -0
  12. astichi-0.1.0/astichi/builder/__init__.py +35 -0
  13. astichi-0.1.0/astichi/builder/api.py +10 -0
  14. astichi-0.1.0/astichi/builder/graph.py +452 -0
  15. astichi-0.1.0/astichi/builder/handles.py +1257 -0
  16. astichi-0.1.0/astichi/diagnostics/__init__.py +13 -0
  17. astichi-0.1.0/astichi/diagnostics/formatting.py +48 -0
  18. astichi-0.1.0/astichi/emit/__init__.py +19 -0
  19. astichi-0.1.0/astichi/emit/api.py +87 -0
  20. astichi-0.1.0/astichi/frontend/__init__.py +18 -0
  21. astichi-0.1.0/astichi/frontend/api.py +239 -0
  22. astichi-0.1.0/astichi/frontend/compiled.py +9 -0
  23. astichi-0.1.0/astichi/frontend/source_kind.py +51 -0
  24. astichi-0.1.0/astichi/hygiene/__init__.py +29 -0
  25. astichi-0.1.0/astichi/hygiene/api.py +1316 -0
  26. astichi-0.1.0/astichi/lowering/__init__.py +129 -0
  27. astichi-0.1.0/astichi/lowering/boundaries.py +324 -0
  28. astichi-0.1.0/astichi/lowering/call_argument_payloads.py +375 -0
  29. astichi-0.1.0/astichi/lowering/external_bind.py +492 -0
  30. astichi-0.1.0/astichi/lowering/external_ref.py +517 -0
  31. astichi-0.1.0/astichi/lowering/marker_contexts.py +61 -0
  32. astichi-0.1.0/astichi/lowering/markers.py +1260 -0
  33. astichi-0.1.0/astichi/lowering/parameters.py +138 -0
  34. astichi-0.1.0/astichi/lowering/pyimport.py +371 -0
  35. astichi-0.1.0/astichi/lowering/sentinel_attrs.py +41 -0
  36. astichi-0.1.0/astichi/lowering/unroll.py +565 -0
  37. astichi-0.1.0/astichi/lowering/unroll_domain.py +147 -0
  38. astichi-0.1.0/astichi/materialize/__init__.py +9 -0
  39. astichi-0.1.0/astichi/materialize/api.py +4227 -0
  40. astichi-0.1.0/astichi/materialize/pyimport.py +217 -0
  41. astichi-0.1.0/astichi/model/__init__.py +99 -0
  42. astichi-0.1.0/astichi/model/basic.py +639 -0
  43. astichi-0.1.0/astichi/model/composable.py +29 -0
  44. astichi-0.1.0/astichi/model/descriptors.py +398 -0
  45. astichi-0.1.0/astichi/model/external_values.py +224 -0
  46. astichi-0.1.0/astichi/model/origin.py +14 -0
  47. astichi-0.1.0/astichi/model/ports.py +295 -0
  48. astichi-0.1.0/astichi/model/semantics.py +352 -0
  49. astichi-0.1.0/astichi/path_resolution.py +710 -0
  50. astichi-0.1.0/astichi/shell_refs.py +340 -0
  51. astichi-0.1.0/dev-docs/AstichiBindBuilderDesign.md +659 -0
  52. astichi-0.1.0/dev-docs/AstichiCodingRules.md +263 -0
  53. astichi-0.1.0/dev-docs/AstichiCommentsProposal.md +471 -0
  54. astichi-0.1.0/dev-docs/AstichiImportProposedEnhancements.md +84 -0
  55. astichi-0.1.0/dev-docs/AstichiSingleSourceSummary.md +837 -0
  56. astichi-0.1.0/dev-docs/AtichiBuildResolverProposal.md +253 -0
  57. astichi-0.1.0/dev-docs/historical/AstichiApiDesignComposed.md +409 -0
  58. astichi-0.1.0/dev-docs/historical/AstichiApiDesignProposal.md +483 -0
  59. astichi-0.1.0/dev-docs/historical/AstichiApiDesignV1-BindExternal.md +1033 -0
  60. astichi-0.1.0/dev-docs/historical/AstichiApiDesignV1-CompositionUnification.md +642 -0
  61. astichi-0.1.0/dev-docs/historical/AstichiApiDesignV1-InsertExpression.md +798 -0
  62. astichi-0.1.0/dev-docs/historical/AstichiApiDesignV1-MarkerPreservingEmit.md +339 -0
  63. astichi-0.1.0/dev-docs/historical/AstichiApiDesignV1-UnrollRevision.md +627 -0
  64. astichi-0.1.0/dev-docs/historical/AstichiApiDesignV1.md +746 -0
  65. astichi-0.1.0/dev-docs/historical/AstichiComposableSelfDescription.md +1087 -0
  66. astichi-0.1.0/dev-docs/historical/AstichiCompositionModel.md +35 -0
  67. astichi-0.1.0/dev-docs/historical/AstichiDataDrivenBuilderApi.md +394 -0
  68. astichi-0.1.0/dev-docs/historical/AstichiDecriptorAPIProposal.md +790 -0
  69. astichi-0.1.0/dev-docs/historical/AstichiFixNoEnumViolations.md +994 -0
  70. astichi-0.1.0/dev-docs/historical/AstichiImplementationBoundaries.md +277 -0
  71. astichi-0.1.0/dev-docs/historical/AstichiInternalsDesignV1.md +359 -0
  72. astichi-0.1.0/dev-docs/historical/AstichiMultiBindFixPlan.md +372 -0
  73. astichi-0.1.0/dev-docs/historical/AstichiUserDocumentationPlan.md +138 -0
  74. astichi-0.1.0/dev-docs/historical/AstichiV1Milestones.md +77 -0
  75. astichi-0.1.0/dev-docs/historical/AstichiV2TestAugments.md +347 -0
  76. astichi-0.1.0/dev-docs/historical/AstichiV3CallArgumentAddendum.md +284 -0
  77. astichi-0.1.0/dev-docs/historical/AstichiV3CallArgumentImplementationPlan.md +328 -0
  78. astichi-0.1.0/dev-docs/historical/AstichiV3ExternalRefBind.m4 +280 -0
  79. astichi-0.1.0/dev-docs/historical/AstichiV3ParameterHoleImplementationPlan.md +108 -0
  80. astichi-0.1.0/dev-docs/historical/AstichiV3ParameterHoleSpec.md +359 -0
  81. astichi-0.1.0/dev-docs/historical/AstichiV3TargetAdditionalHoleShapes.md +707 -0
  82. astichi-0.1.0/dev-docs/historical/AstichiV3TestPlan.md +744 -0
  83. astichi-0.1.0/dev-docs/historical/BoundaryScopePolicyProposal.md +289 -0
  84. astichi-0.1.0/dev-docs/historical/BuilderIdentityAndAliasesDesign.md +115 -0
  85. astichi-0.1.0/dev-docs/historical/IdentifierHygieneRequirements.md +67 -0
  86. astichi-0.1.0/dev-docs/historical/README.md +11 -0
  87. astichi-0.1.0/dev-docs/historical/V1DeferredFeatures.md +201 -0
  88. astichi-0.1.0/dev-docs/historical/V1Plan.md +1069 -0
  89. astichi-0.1.0/dev-docs/historical/V1ProgressRegister.md +284 -0
  90. astichi-0.1.0/dev-docs/historical/V1StartHere.md +82 -0
  91. astichi-0.1.0/dev-docs/historical/V2DeferredFeatures.md +193 -0
  92. astichi-0.1.0/dev-docs/historical/V2Plan.md +419 -0
  93. astichi-0.1.0/dev-docs/historical/V2ProgressRegister.md +276 -0
  94. astichi-0.1.0/dev-docs/historical/V2StartHere.md +117 -0
  95. astichi-0.1.0/dev-docs/historical/v1_issues/README.md +27 -0
  96. astichi-0.1.0/dev-docs/historical/v1_issues/resolved/001-expression-insert-materialization-gap.md +72 -0
  97. astichi-0.1.0/dev-docs/historical/v1_issues/resolved/002-expression-port-shape-validation-gap.md +64 -0
  98. astichi-0.1.0/dev-docs/historical/v1_issues/resolved/004-expression-insert-end-to-end-test-gap.md +54 -0
  99. astichi-0.1.0/dev-docs/historical/v1_issues/resolved/005-expression-shape-rejection-test-gap.md +51 -0
  100. astichi-0.1.0/dev-docs/historical/v1_issues/resolved/006-provenance-contract-test-gap.md +45 -0
  101. astichi-0.1.0/dev-docs/historical/v2_issues/003-provenance-format-drift.md +77 -0
  102. astichi-0.1.0/dev-docs/historical/v2_issues/004-materialize-free-name-soundness.md +174 -0
  103. astichi-0.1.0/dev-docs/historical/v2_issues/005-definitional-name-replacement.md +300 -0
  104. astichi-0.1.0/dev-docs/historical/v2_issues/006-cross-scope-identifier-threading.md +95 -0
  105. astichi-0.1.0/dev-docs/historical/v2_issues/README.md +27 -0
  106. astichi-0.1.0/dev-docs/historical/v3_issues/001-deep-descendant-cross-composable-addressing.md +853 -0
  107. astichi-0.1.0/dev-docs/historical/v3_issues/README.md +14 -0
  108. astichi-0.1.0/dev-docs/history/AstichiImportProposal.md +726 -0
  109. astichi-0.1.0/dev-docs/history/AstichiImportProposalDetailedCodingPlan.md +1199 -0
  110. astichi-0.1.0/dev-docs/history/AstichiImportProposalDetailedReccomendations.md +293 -0
  111. astichi-0.1.0/dev-docs/history/AstichiImportProposalPlan.md +792 -0
  112. astichi-0.1.0/dev-docs/history/AstichiImportRefactorPrep.md +719 -0
  113. astichi-0.1.0/docs/README.md +38 -0
  114. astichi-0.1.0/docs/reference/README.md +33 -0
  115. astichi-0.1.0/pyproject.toml +51 -0
  116. astichi-0.1.0/tests/README.md +74 -0
  117. astichi-0.1.0/tests/data/gold_src/arg_identifier_kwarg.py +46 -0
  118. astichi-0.1.0/tests/data/gold_src/bind_external_literal.py +25 -0
  119. astichi-0.1.0/tests/data/gold_src/boundary_pass_export.py +67 -0
  120. astichi-0.1.0/tests/data/gold_src/call_argument_payload.py +271 -0
  121. astichi-0.1.0/tests/data/gold_src/comment_marker.py +62 -0
  122. astichi-0.1.0/tests/data/gold_src/compile_basic.py +29 -0
  123. astichi-0.1.0/tests/data/gold_src/descriptor_assign_and_bind_identifier.py +122 -0
  124. astichi-0.1.0/tests/data/gold_src/descriptor_bind_identifier.py +86 -0
  125. astichi-0.1.0/tests/data/gold_src/descriptor_bind_identifier_same_name_collision.py +131 -0
  126. astichi-0.1.0/tests/data/gold_src/dict_expansion_hygiene.py +52 -0
  127. astichi-0.1.0/tests/data/gold_src/edge_multibind.py +86 -0
  128. astichi-0.1.0/tests/data/gold_src/edge_multibind_staged.py +68 -0
  129. astichi-0.1.0/tests/data/gold_src/function_parameter_scope_hygiene.py +77 -0
  130. astichi-0.1.0/tests/data/gold_src/hygiene_boundary_isolation.py +104 -0
  131. astichi-0.1.0/tests/data/gold_src/hygiene_scope_collision.py +46 -0
  132. astichi-0.1.0/tests/data/gold_src/identifier_bind.py +41 -0
  133. astichi-0.1.0/tests/data/gold_src/import_arg_identifier.py +34 -0
  134. astichi-0.1.0/tests/data/gold_src/indexed_instance_family.py +78 -0
  135. astichi-0.1.0/tests/data/gold_src/inline_insert_block.py +54 -0
  136. astichi-0.1.0/tests/data/gold_src/param_hole_staged_compose.py +70 -0
  137. astichi-0.1.0/tests/data/gold_src/parameter_holes.py +163 -0
  138. astichi-0.1.0/tests/data/gold_src/provenance_absorb_roundtrip.py +42 -0
  139. astichi-0.1.0/tests/data/gold_src/pyimport_dotted_module.py +21 -0
  140. astichi-0.1.0/tests/data/gold_src/pyimport_dynamic_module_ref.py +22 -0
  141. astichi-0.1.0/tests/data/gold_src/pyimport_expression_multi_stage.py +73 -0
  142. astichi-0.1.0/tests/data/gold_src/pyimport_from_basic.py +21 -0
  143. astichi-0.1.0/tests/data/gold_src/pyimport_hygiene_collision.py +26 -0
  144. astichi-0.1.0/tests/data/gold_src/pyimport_multi_stage_multi_hole.py +65 -0
  145. astichi-0.1.0/tests/data/gold_src/pyimport_plain_alias.py +22 -0
  146. astichi-0.1.0/tests/data/gold_src/pyimport_staged_composition.py +38 -0
  147. astichi-0.1.0/tests/data/gold_src/pyimport_with_docstring_and_future.py +22 -0
  148. astichi-0.1.0/tests/data/gold_src/ref_param_hygiene.py +90 -0
  149. astichi-0.1.0/tests/data/gold_src/staged_build_trace.py +87 -0
  150. astichi-0.1.0/tests/data/gold_src/support/__init__.py +1 -0
  151. astichi-0.1.0/tests/data/gold_src/support/golden_case.py +61 -0
  152. astichi-0.1.0/tests/data/gold_src/tuple_list_expression_expansion.py +60 -0
  153. astichi-0.1.0/tests/data/gold_src/unroll_bind_domain.py +55 -0
  154. astichi-0.1.0/tests/data/gold_src/unroll_literal.py +85 -0
  155. astichi-0.1.0/tests/data/goldens/materialized/arg_identifier_kwarg.py +4 -0
  156. astichi-0.1.0/tests/data/goldens/materialized/bind_external_literal.py +1 -0
  157. astichi-0.1.0/tests/data/goldens/materialized/boundary_pass_export.py +9 -0
  158. astichi-0.1.0/tests/data/goldens/materialized/call_argument_payload.py +31 -0
  159. astichi-0.1.0/tests/data/goldens/materialized/comment_marker.py +9 -0
  160. astichi-0.1.0/tests/data/goldens/materialized/compile_basic.py +8 -0
  161. astichi-0.1.0/tests/data/goldens/materialized/descriptor_assign_and_bind_identifier.py +7 -0
  162. astichi-0.1.0/tests/data/goldens/materialized/descriptor_bind_identifier.py +4 -0
  163. astichi-0.1.0/tests/data/goldens/materialized/descriptor_bind_identifier_same_name_collision.py +6 -0
  164. astichi-0.1.0/tests/data/goldens/materialized/dict_expansion_hygiene.py +1 -0
  165. astichi-0.1.0/tests/data/goldens/materialized/edge_multibind.py +12 -0
  166. astichi-0.1.0/tests/data/goldens/materialized/edge_multibind_staged.py +6 -0
  167. astichi-0.1.0/tests/data/goldens/materialized/function_parameter_scope_hygiene.py +12 -0
  168. astichi-0.1.0/tests/data/goldens/materialized/hygiene_boundary_isolation.py +8 -0
  169. astichi-0.1.0/tests/data/goldens/materialized/hygiene_scope_collision.py +4 -0
  170. astichi-0.1.0/tests/data/goldens/materialized/identifier_bind.py +8 -0
  171. astichi-0.1.0/tests/data/goldens/materialized/import_arg_identifier.py +3 -0
  172. astichi-0.1.0/tests/data/goldens/materialized/indexed_instance_family.py +6 -0
  173. astichi-0.1.0/tests/data/goldens/materialized/inline_insert_block.py +4 -0
  174. astichi-0.1.0/tests/data/goldens/materialized/param_hole_staged_compose.py +2 -0
  175. astichi-0.1.0/tests/data/goldens/materialized/parameter_holes.py +18 -0
  176. astichi-0.1.0/tests/data/goldens/materialized/provenance_absorb_roundtrip.py +2 -0
  177. astichi-0.1.0/tests/data/goldens/materialized/pyimport_dotted_module.py +2 -0
  178. astichi-0.1.0/tests/data/goldens/materialized/pyimport_dynamic_module_ref.py +2 -0
  179. astichi-0.1.0/tests/data/goldens/materialized/pyimport_expression_multi_stage.py +5 -0
  180. astichi-0.1.0/tests/data/goldens/materialized/pyimport_from_basic.py +2 -0
  181. astichi-0.1.0/tests/data/goldens/materialized/pyimport_hygiene_collision.py +3 -0
  182. astichi-0.1.0/tests/data/goldens/materialized/pyimport_multi_stage_multi_hole.py +11 -0
  183. astichi-0.1.0/tests/data/goldens/materialized/pyimport_plain_alias.py +3 -0
  184. astichi-0.1.0/tests/data/goldens/materialized/pyimport_staged_composition.py +2 -0
  185. astichi-0.1.0/tests/data/goldens/materialized/pyimport_with_docstring_and_future.py +4 -0
  186. astichi-0.1.0/tests/data/goldens/materialized/ref_param_hygiene.py +11 -0
  187. astichi-0.1.0/tests/data/goldens/materialized/staged_build_trace.py +10 -0
  188. astichi-0.1.0/tests/data/goldens/materialized/tuple_list_expression_expansion.py +2 -0
  189. astichi-0.1.0/tests/data/goldens/materialized/unroll_bind_domain.py +2 -0
  190. astichi-0.1.0/tests/data/goldens/materialized/unroll_literal.py +7 -0
  191. astichi-0.1.0/tests/data/goldens/pre_materialized/arg_identifier_kwarg.py +5 -0
  192. astichi-0.1.0/tests/data/goldens/pre_materialized/bind_external_literal.py +2 -0
  193. astichi-0.1.0/tests/data/goldens/pre_materialized/boundary_pass_export.py +29 -0
  194. astichi-0.1.0/tests/data/goldens/pre_materialized/call_argument_payload.py +37 -0
  195. astichi-0.1.0/tests/data/goldens/pre_materialized/comment_marker.py +19 -0
  196. astichi-0.1.0/tests/data/goldens/pre_materialized/compile_basic.py +9 -0
  197. astichi-0.1.0/tests/data/goldens/pre_materialized/descriptor_assign_and_bind_identifier.py +34 -0
  198. astichi-0.1.0/tests/data/goldens/pre_materialized/descriptor_bind_identifier.py +21 -0
  199. astichi-0.1.0/tests/data/goldens/pre_materialized/descriptor_bind_identifier_same_name_collision.py +33 -0
  200. astichi-0.1.0/tests/data/goldens/pre_materialized/dict_expansion_hygiene.py +6 -0
  201. astichi-0.1.0/tests/data/goldens/pre_materialized/edge_multibind.py +34 -0
  202. astichi-0.1.0/tests/data/goldens/pre_materialized/edge_multibind_staged.py +34 -0
  203. astichi-0.1.0/tests/data/goldens/pre_materialized/function_parameter_scope_hygiene.py +29 -0
  204. astichi-0.1.0/tests/data/goldens/pre_materialized/hygiene_boundary_isolation.py +35 -0
  205. astichi-0.1.0/tests/data/goldens/pre_materialized/hygiene_scope_collision.py +13 -0
  206. astichi-0.1.0/tests/data/goldens/pre_materialized/identifier_bind.py +9 -0
  207. astichi-0.1.0/tests/data/goldens/pre_materialized/import_arg_identifier.py +4 -0
  208. astichi-0.1.0/tests/data/goldens/pre_materialized/indexed_instance_family.py +25 -0
  209. astichi-0.1.0/tests/data/goldens/pre_materialized/inline_insert_block.py +16 -0
  210. astichi-0.1.0/tests/data/goldens/pre_materialized/param_hole_staged_compose.py +16 -0
  211. astichi-0.1.0/tests/data/goldens/pre_materialized/parameter_holes.py +55 -0
  212. astichi-0.1.0/tests/data/goldens/pre_materialized/provenance_absorb_roundtrip.py +3 -0
  213. astichi-0.1.0/tests/data/goldens/pre_materialized/pyimport_dotted_module.py +3 -0
  214. astichi-0.1.0/tests/data/goldens/pre_materialized/pyimport_dynamic_module_ref.py +3 -0
  215. astichi-0.1.0/tests/data/goldens/pre_materialized/pyimport_expression_multi_stage.py +8 -0
  216. astichi-0.1.0/tests/data/goldens/pre_materialized/pyimport_from_basic.py +3 -0
  217. astichi-0.1.0/tests/data/goldens/pre_materialized/pyimport_hygiene_collision.py +8 -0
  218. astichi-0.1.0/tests/data/goldens/pre_materialized/pyimport_multi_stage_multi_hole.py +29 -0
  219. astichi-0.1.0/tests/data/goldens/pre_materialized/pyimport_plain_alias.py +4 -0
  220. astichi-0.1.0/tests/data/goldens/pre_materialized/pyimport_staged_composition.py +12 -0
  221. astichi-0.1.0/tests/data/goldens/pre_materialized/pyimport_with_docstring_and_future.py +5 -0
  222. astichi-0.1.0/tests/data/goldens/pre_materialized/ref_param_hygiene.py +20 -0
  223. astichi-0.1.0/tests/data/goldens/pre_materialized/staged_build_trace.py +53 -0
  224. astichi-0.1.0/tests/data/goldens/pre_materialized/tuple_list_expression_expansion.py +7 -0
  225. astichi-0.1.0/tests/data/goldens/pre_materialized/unroll_bind_domain.py +15 -0
  226. astichi-0.1.0/tests/data/goldens/pre_materialized/unroll_literal.py +33 -0
  227. astichi-0.1.0/tests/test_arg_identifier_kwarg.py +150 -0
  228. astichi-0.1.0/tests/test_ast_goldens.py +121 -0
  229. astichi-0.1.0/tests/test_ast_provenance.py +132 -0
  230. astichi-0.1.0/tests/test_asttools.py +131 -0
  231. astichi-0.1.0/tests/test_bind_external.py +132 -0
  232. astichi-0.1.0/tests/test_boundaries.py +1008 -0
  233. astichi-0.1.0/tests/test_build_merge.py +561 -0
  234. astichi-0.1.0/tests/test_builder_handles.py +856 -0
  235. astichi-0.1.0/tests/test_builder_raw.py +105 -0
  236. astichi-0.1.0/tests/test_call_arg_hole_anchor.py +124 -0
  237. astichi-0.1.0/tests/test_call_argument_payload_materialize.py +360 -0
  238. astichi-0.1.0/tests/test_call_argument_payload_model.py +85 -0
  239. astichi-0.1.0/tests/test_call_argument_payload_recognition.py +141 -0
  240. astichi-0.1.0/tests/test_comments.py +77 -0
  241. astichi-0.1.0/tests/test_descriptors.py +219 -0
  242. astichi-0.1.0/tests/test_diagnostics_formatting.py +48 -0
  243. astichi-0.1.0/tests/test_emit.py +151 -0
  244. astichi-0.1.0/tests/test_expression_insert_pipeline.py +272 -0
  245. astichi-0.1.0/tests/test_external_bind.py +216 -0
  246. astichi-0.1.0/tests/test_external_ref.py +397 -0
  247. astichi-0.1.0/tests/test_external_values.py +164 -0
  248. astichi-0.1.0/tests/test_frontend_compile.py +93 -0
  249. astichi-0.1.0/tests/test_hygiene.py +409 -0
  250. astichi-0.1.0/tests/test_lowering_markers.py +334 -0
  251. astichi-0.1.0/tests/test_lowering_shapes.py +165 -0
  252. astichi-0.1.0/tests/test_materialize.py +802 -0
  253. astichi-0.1.0/tests/test_model.py +269 -0
  254. astichi-0.1.0/tests/test_parameter_holes.py +406 -0
  255. astichi-0.1.0/tests/test_pyimport_phase1.py +218 -0
  256. astichi-0.1.0/tests/test_staged_build_refs_and_bindings.py +572 -0
  257. astichi-0.1.0/tests/test_unroll.py +375 -0
  258. astichi-0.1.0/tests/test_unroll_domain.py +171 -0
  259. astichi-0.1.0/tests/test_versioned_test_harness.py +175 -0
  260. astichi-0.1.0/tests/versioned_test_harness.py +481 -0
@@ -0,0 +1,14 @@
1
+ .DS_Store
2
+ .venv/
3
+ __pycache__/
4
+ .pytest_cache/
5
+ .coverage
6
+ htmlcov/
7
+ *.pyc
8
+ build/
9
+ dist/
10
+ *.egg-info/
11
+ tests/.uv-venvs/
12
+ tests/actual_test_results/
13
+ scratch/
14
+ *-old.py
astichi-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 astichi contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
astichi-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,310 @@
1
+ Metadata-Version: 2.4
2
+ Name: astichi
3
+ Version: 0.1.0
4
+ Summary: AST composition helpers: markers, hygiene, lifting, and lowering for composable Python code generation
5
+ Author: astichi contributors
6
+ License: MIT License
7
+
8
+ Copyright (c) 2026 astichi contributors
9
+
10
+ Permission is hereby granted, free of charge, to any person obtaining a copy
11
+ of this software and associated documentation files (the "Software"), to deal
12
+ in the Software without restriction, including without limitation the rights
13
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
+ copies of the Software, and to permit persons to whom the Software is
15
+ furnished to do so, subject to the following conditions:
16
+
17
+ The above copyright notice and this permission notice shall be included in all
18
+ copies or substantial portions of the Software.
19
+
20
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
+ SOFTWARE.
27
+ License-File: LICENSE
28
+ Keywords: ast,codegen,compiler,composition
29
+ Classifier: Development Status :: 2 - Pre-Alpha
30
+ Classifier: Intended Audience :: Developers
31
+ Classifier: License :: OSI Approved :: MIT License
32
+ Classifier: Programming Language :: Python :: 3
33
+ Classifier: Programming Language :: Python :: 3.12
34
+ Classifier: Programming Language :: Python :: 3.13
35
+ Classifier: Programming Language :: Python :: 3.14
36
+ Classifier: Programming Language :: Python :: 3.15
37
+ Requires-Python: >=3.12
38
+ Provides-Extra: dev
39
+ Requires-Dist: pytest>=7.0; extra == 'dev'
40
+ Provides-Extra: test
41
+ Requires-Dist: pytest>=7.0; extra == 'test'
42
+ Description-Content-Type: text/markdown
43
+
44
+ # astichi
45
+
46
+ AST-level composition and stitching for Python code generation.
47
+
48
+ Astichi takes small, marker-bearing Python snippets, composes them into one
49
+ coherent program, and emits runnable Python. It is built for generators that
50
+ need low-overhead output without falling back to brittle string templates or
51
+ runtime abstraction in hot paths.
52
+
53
+ Astichi is a fit when you want to:
54
+
55
+ - describe codegen intent in Python-shaped snippets
56
+ - stitch block and expression fragments at named composition sites
57
+ - bind compile-time values into source before final lowering
58
+ - unroll compile-time loops into straight-line Python
59
+ - synthesize managed imports that participate in hygiene
60
+ - inspect composables with descriptors before wiring them
61
+ - emit inspectable source with provenance instead of opaque runtime machinery
62
+
63
+ It is **not** a general macro system and **not** a generic codemod framework.
64
+ It is a focused library for generators that need a reliable AST stitcher.
65
+
66
+ ## Why Astichi
67
+
68
+ Code generators often hit the same wall: the desired output is simple,
69
+ specialized Python, but the implementation ends up split between string
70
+ concatenation, ad hoc templates, and fragile scope management.
71
+
72
+ Astichi handles the parts that usually go wrong:
73
+
74
+ - valid Python ASTs instead of fragile template fragments
75
+ - deterministic insertion order for stitched code
76
+ - compile-time binding and loop unrolling before emission
77
+ - specialized straight-line Python instead of runtime dispatch layers
78
+ - emitted source you can diff, test, and round-trip
79
+
80
+ ## Marker mental model
81
+
82
+ Astichi is marker-bearing Python source plus a small build pipeline.
83
+
84
+ - Markers are recognized from authored Python source.
85
+ - Marker meaning comes from AST position, not string matching alone.
86
+ - `compile(...)` parses marker-bearing source into a `Composable`.
87
+ - `build()` wires composables together.
88
+ - `describe()` exposes holes, binds, ports, and builder target addresses for
89
+ data-driven composition.
90
+ - `materialize()` resolves inserts, bindings, and hygiene, then produces real
91
+ Python.
92
+
93
+ The core markers are:
94
+
95
+ - `astichi_hole(name)` -> insertion site
96
+ - `astichi_keep(name)` -> hygiene-preserved name in expression / statement source
97
+ - `name__astichi_keep__` -> hygiene-preserved name in identifier position
98
+ - `name__astichi_arg__` -> identifier demand
99
+ - `name__astichi_param_hole__` -> function-parameter insertion target
100
+ - `astichi_funcargs(...)` -> call-argument payload
101
+ - `astichi_bind_external(name)` -> external/literal value slot
102
+ - `astichi_ref(path)` -> compile-time reducible identifier / attribute path
103
+ - `astichi_pyimport(module=..., names=(...))` -> managed Python import
104
+ - `astichi_comment("...")` -> final-output source comment
105
+ - `astichi_pass(name, outer_bind=True)` -> explicit same-name boundary read
106
+ - `astichi_import(name)` -> explicit whole-scope boundary import
107
+ - `astichi_export(name)` -> explicit outward supply
108
+ - `astichi_insert(...)` -> internal emitted metadata, not general authored API
109
+
110
+ Comment marker note:
111
+
112
+ - `astichi_comment("...")` is statement-only. Ordinary `materialize()` strips
113
+ it for executable output; `emit_commented()` renders it as real `#` comments.
114
+ - Multi-line payloads keep the marker statement's indentation, and only exact
115
+ `{__file__}` / `{__line__}` substrings are expanded.
116
+
117
+ Value-form target note:
118
+
119
+ - `astichi_ref(...)` and `astichi_pass(...)` are ordinary value-form surfaces in
120
+ expressions.
121
+ - If the marker result itself must occupy an `Assign` / `AugAssign` / `Delete`
122
+ target position, append `._` or `.astichi_v`:
123
+ `astichi_ref("self.f0")._ = 1`,
124
+ `astichi_pass(counter).astichi_v = 1`.
125
+ - If you immediately continue to a real attribute, plain Python target syntax
126
+ already works:
127
+ `astichi_pass(obj).field = 1`.
128
+
129
+ The one rule that matters most is scope:
130
+
131
+ - `astichi_insert` is the basic Astichi boundary.
132
+ - Each inserted composable lives in its own Astichi scope.
133
+ - There is no implicit capture across that boundary.
134
+ - If a name crosses the boundary, make it explicit with `keep`, `pass`,
135
+ `import`, or `export`.
136
+ - Function parameters are the pinned exception: parameter names and uses in the
137
+ function scope stay attached to that parameter binding.
138
+
139
+ Small example:
140
+
141
+ ```python
142
+ import astichi
143
+
144
+ builder = astichi.build()
145
+ builder.add.Root(
146
+ astichi.compile(
147
+ """
148
+ items = []
149
+ astichi_hole(body)
150
+ result = tuple(items)
151
+ """
152
+ )
153
+ )
154
+ builder.add.Step(
155
+ astichi.compile(
156
+ """
157
+ astichi_pass(items, outer_bind=True).append("x")
158
+ """
159
+ )
160
+ )
161
+ builder.Root.body.add.Step(order=0)
162
+
163
+ materialized = builder.build().materialize()
164
+ print(materialized.emit(provenance=False))
165
+ ```
166
+
167
+ Emitted Python:
168
+
169
+ ```python
170
+ items = []
171
+ items.append("x")
172
+ result = tuple(items)
173
+ ```
174
+
175
+ Without `astichi_pass(items, outer_bind=True)`, the inner snippet does not get
176
+ to reuse `items` just because the spelling matches. That is deliberate. Astichi
177
+ defaults to isolated scopes and only crosses them when the source says so.
178
+
179
+ The fluent builder is also available as a data-driven named API. Descriptor
180
+ target data can feed that API directly:
181
+
182
+ ```python
183
+ hole = root.describe().single_hole_named("body")
184
+
185
+ builder = astichi.build()
186
+ builder.add("Root", root)
187
+ builder.add("Step", astichi.compile("value = 1\n"))
188
+ builder.target(hole.with_root_instance("Root")).add("Step")
189
+ ```
190
+
191
+ That `builder.target(...)` call uses the same target address as
192
+ `builder.Root.body.add.Step()`, but the address came from `describe()` instead
193
+ of a Python attribute chain.
194
+
195
+ ## Example: schema-specialized row projector
196
+
197
+ Suppose an ingestion pipeline knows its event schema at build time, and each
198
+ field needs its own normalization step. A runtime loop or dispatch table adds
199
+ overhead to every row. String templating works until ordering, scope, and
200
+ correctness start fighting each other.
201
+
202
+ Astichi lets you define the skeleton once, stitch in field-specific steps, and
203
+ emit the straight-line Python you actually want to run.
204
+
205
+ ```python
206
+ import astichi
207
+
208
+ root = astichi.compile(
209
+ """
210
+ astichi_bind_external(FIELDS)
211
+
212
+ def project_row(row):
213
+ out = {}
214
+ for field in astichi_for(FIELDS):
215
+ astichi_hole(step)
216
+ return out
217
+ """
218
+ ).bind(FIELDS=("user_id", "total_cents", "created_at"))
219
+
220
+ builder = astichi.build()
221
+ builder.add.Root(root)
222
+
223
+ builder.add.UserId(
224
+ astichi.compile("out['user_id'] = int(row['user_id'])\n")
225
+ )
226
+ builder.add.TotalCents(
227
+ astichi.compile("out['total_cents'] = int(row['total_cents'])\n")
228
+ )
229
+ builder.add.CreatedAt(
230
+ astichi.compile("out['created_at'] = row['created_at'][:10]\n")
231
+ )
232
+
233
+ builder.Root.step[0].add.UserId()
234
+ builder.Root.step[1].add.TotalCents()
235
+ builder.Root.step[2].add.CreatedAt()
236
+
237
+ projector = builder.build().materialize()
238
+ print(projector.emit(provenance=False))
239
+ ```
240
+
241
+ Emitted Python:
242
+
243
+ ```python
244
+ def project_row(row):
245
+ out = {}
246
+ out["user_id"] = int(row["user_id"])
247
+ out["total_cents"] = int(row["total_cents"])
248
+ out["created_at"] = row["created_at"][:10]
249
+ return out
250
+ ```
251
+
252
+ That is the point: no runtime field loop, no dispatch registry, no handwritten
253
+ template surgery. The generated function is plain Python, specialized to the
254
+ known schema, and suitable for hot-path use.
255
+
256
+ This is exactly the class of problem where a reliable AST stitcher matters:
257
+
258
+ - block fragments must land in the right lexical scope
259
+ - per-field steps must keep deterministic order
260
+ - compile-time schema data must become literal Python
261
+ - the final output must still be valid, inspectable source
262
+
263
+ ## Current surface
264
+
265
+ Astichi currently provides:
266
+
267
+ - `astichi.compile(source, file_name=None, line_number=1, offset=0)`
268
+ - `astichi.build()` for builder-based composition
269
+ - concrete composables with `.bind(...)`, `.describe()`, `.materialize()`, and
270
+ `.emit(...)` / `.emit_commented()`
271
+ - data-driven builder calls such as `builder.add("Root", root)` and
272
+ `builder.target(hole.with_root_instance("Root")).add("Step")`
273
+ - provenance helpers in `astichi.emit`
274
+
275
+ Supported pieces today include block holes, expression inserts, external
276
+ binding, managed Python imports, materialization, emission, and builder-driven
277
+ loop unrolling.
278
+
279
+ ## Layout
280
+
281
+ | Path | Role |
282
+ |------|------|
283
+ | `src/astichi/` | Library code |
284
+ | `docs/` | User-facing docs |
285
+ | `tests/` | Pytest suite |
286
+ | `dev-docs/` | Design notes, active summary, and requirements |
287
+ | `scratch/` | Throwaway experiments (not shipped) |
288
+
289
+ ## Development
290
+
291
+ ```bash
292
+ python -m venv .venv && source .venv/bin/activate
293
+ pip install -e ".[dev]"
294
+ PYTEST_DISABLE_PLUGIN_AUTOLOAD=1 python -m pytest
295
+ ```
296
+
297
+ ## Status
298
+
299
+ Early development (`0.1.0`), but already useful for controlled codegen
300
+ pipelines.
301
+
302
+ Start with:
303
+
304
+ - `docs/` for the user-facing surface
305
+ - `dev-docs/AstichiSingleSourceSummary.md` for the current implementation
306
+ snapshot and known gaps
307
+
308
+ ## License
309
+
310
+ MIT. See [LICENSE](LICENSE).
@@ -0,0 +1,267 @@
1
+ # astichi
2
+
3
+ AST-level composition and stitching for Python code generation.
4
+
5
+ Astichi takes small, marker-bearing Python snippets, composes them into one
6
+ coherent program, and emits runnable Python. It is built for generators that
7
+ need low-overhead output without falling back to brittle string templates or
8
+ runtime abstraction in hot paths.
9
+
10
+ Astichi is a fit when you want to:
11
+
12
+ - describe codegen intent in Python-shaped snippets
13
+ - stitch block and expression fragments at named composition sites
14
+ - bind compile-time values into source before final lowering
15
+ - unroll compile-time loops into straight-line Python
16
+ - synthesize managed imports that participate in hygiene
17
+ - inspect composables with descriptors before wiring them
18
+ - emit inspectable source with provenance instead of opaque runtime machinery
19
+
20
+ It is **not** a general macro system and **not** a generic codemod framework.
21
+ It is a focused library for generators that need a reliable AST stitcher.
22
+
23
+ ## Why Astichi
24
+
25
+ Code generators often hit the same wall: the desired output is simple,
26
+ specialized Python, but the implementation ends up split between string
27
+ concatenation, ad hoc templates, and fragile scope management.
28
+
29
+ Astichi handles the parts that usually go wrong:
30
+
31
+ - valid Python ASTs instead of fragile template fragments
32
+ - deterministic insertion order for stitched code
33
+ - compile-time binding and loop unrolling before emission
34
+ - specialized straight-line Python instead of runtime dispatch layers
35
+ - emitted source you can diff, test, and round-trip
36
+
37
+ ## Marker mental model
38
+
39
+ Astichi is marker-bearing Python source plus a small build pipeline.
40
+
41
+ - Markers are recognized from authored Python source.
42
+ - Marker meaning comes from AST position, not string matching alone.
43
+ - `compile(...)` parses marker-bearing source into a `Composable`.
44
+ - `build()` wires composables together.
45
+ - `describe()` exposes holes, binds, ports, and builder target addresses for
46
+ data-driven composition.
47
+ - `materialize()` resolves inserts, bindings, and hygiene, then produces real
48
+ Python.
49
+
50
+ The core markers are:
51
+
52
+ - `astichi_hole(name)` -> insertion site
53
+ - `astichi_keep(name)` -> hygiene-preserved name in expression / statement source
54
+ - `name__astichi_keep__` -> hygiene-preserved name in identifier position
55
+ - `name__astichi_arg__` -> identifier demand
56
+ - `name__astichi_param_hole__` -> function-parameter insertion target
57
+ - `astichi_funcargs(...)` -> call-argument payload
58
+ - `astichi_bind_external(name)` -> external/literal value slot
59
+ - `astichi_ref(path)` -> compile-time reducible identifier / attribute path
60
+ - `astichi_pyimport(module=..., names=(...))` -> managed Python import
61
+ - `astichi_comment("...")` -> final-output source comment
62
+ - `astichi_pass(name, outer_bind=True)` -> explicit same-name boundary read
63
+ - `astichi_import(name)` -> explicit whole-scope boundary import
64
+ - `astichi_export(name)` -> explicit outward supply
65
+ - `astichi_insert(...)` -> internal emitted metadata, not general authored API
66
+
67
+ Comment marker note:
68
+
69
+ - `astichi_comment("...")` is statement-only. Ordinary `materialize()` strips
70
+ it for executable output; `emit_commented()` renders it as real `#` comments.
71
+ - Multi-line payloads keep the marker statement's indentation, and only exact
72
+ `{__file__}` / `{__line__}` substrings are expanded.
73
+
74
+ Value-form target note:
75
+
76
+ - `astichi_ref(...)` and `astichi_pass(...)` are ordinary value-form surfaces in
77
+ expressions.
78
+ - If the marker result itself must occupy an `Assign` / `AugAssign` / `Delete`
79
+ target position, append `._` or `.astichi_v`:
80
+ `astichi_ref("self.f0")._ = 1`,
81
+ `astichi_pass(counter).astichi_v = 1`.
82
+ - If you immediately continue to a real attribute, plain Python target syntax
83
+ already works:
84
+ `astichi_pass(obj).field = 1`.
85
+
86
+ The one rule that matters most is scope:
87
+
88
+ - `astichi_insert` is the basic Astichi boundary.
89
+ - Each inserted composable lives in its own Astichi scope.
90
+ - There is no implicit capture across that boundary.
91
+ - If a name crosses the boundary, make it explicit with `keep`, `pass`,
92
+ `import`, or `export`.
93
+ - Function parameters are the pinned exception: parameter names and uses in the
94
+ function scope stay attached to that parameter binding.
95
+
96
+ Small example:
97
+
98
+ ```python
99
+ import astichi
100
+
101
+ builder = astichi.build()
102
+ builder.add.Root(
103
+ astichi.compile(
104
+ """
105
+ items = []
106
+ astichi_hole(body)
107
+ result = tuple(items)
108
+ """
109
+ )
110
+ )
111
+ builder.add.Step(
112
+ astichi.compile(
113
+ """
114
+ astichi_pass(items, outer_bind=True).append("x")
115
+ """
116
+ )
117
+ )
118
+ builder.Root.body.add.Step(order=0)
119
+
120
+ materialized = builder.build().materialize()
121
+ print(materialized.emit(provenance=False))
122
+ ```
123
+
124
+ Emitted Python:
125
+
126
+ ```python
127
+ items = []
128
+ items.append("x")
129
+ result = tuple(items)
130
+ ```
131
+
132
+ Without `astichi_pass(items, outer_bind=True)`, the inner snippet does not get
133
+ to reuse `items` just because the spelling matches. That is deliberate. Astichi
134
+ defaults to isolated scopes and only crosses them when the source says so.
135
+
136
+ The fluent builder is also available as a data-driven named API. Descriptor
137
+ target data can feed that API directly:
138
+
139
+ ```python
140
+ hole = root.describe().single_hole_named("body")
141
+
142
+ builder = astichi.build()
143
+ builder.add("Root", root)
144
+ builder.add("Step", astichi.compile("value = 1\n"))
145
+ builder.target(hole.with_root_instance("Root")).add("Step")
146
+ ```
147
+
148
+ That `builder.target(...)` call uses the same target address as
149
+ `builder.Root.body.add.Step()`, but the address came from `describe()` instead
150
+ of a Python attribute chain.
151
+
152
+ ## Example: schema-specialized row projector
153
+
154
+ Suppose an ingestion pipeline knows its event schema at build time, and each
155
+ field needs its own normalization step. A runtime loop or dispatch table adds
156
+ overhead to every row. String templating works until ordering, scope, and
157
+ correctness start fighting each other.
158
+
159
+ Astichi lets you define the skeleton once, stitch in field-specific steps, and
160
+ emit the straight-line Python you actually want to run.
161
+
162
+ ```python
163
+ import astichi
164
+
165
+ root = astichi.compile(
166
+ """
167
+ astichi_bind_external(FIELDS)
168
+
169
+ def project_row(row):
170
+ out = {}
171
+ for field in astichi_for(FIELDS):
172
+ astichi_hole(step)
173
+ return out
174
+ """
175
+ ).bind(FIELDS=("user_id", "total_cents", "created_at"))
176
+
177
+ builder = astichi.build()
178
+ builder.add.Root(root)
179
+
180
+ builder.add.UserId(
181
+ astichi.compile("out['user_id'] = int(row['user_id'])\n")
182
+ )
183
+ builder.add.TotalCents(
184
+ astichi.compile("out['total_cents'] = int(row['total_cents'])\n")
185
+ )
186
+ builder.add.CreatedAt(
187
+ astichi.compile("out['created_at'] = row['created_at'][:10]\n")
188
+ )
189
+
190
+ builder.Root.step[0].add.UserId()
191
+ builder.Root.step[1].add.TotalCents()
192
+ builder.Root.step[2].add.CreatedAt()
193
+
194
+ projector = builder.build().materialize()
195
+ print(projector.emit(provenance=False))
196
+ ```
197
+
198
+ Emitted Python:
199
+
200
+ ```python
201
+ def project_row(row):
202
+ out = {}
203
+ out["user_id"] = int(row["user_id"])
204
+ out["total_cents"] = int(row["total_cents"])
205
+ out["created_at"] = row["created_at"][:10]
206
+ return out
207
+ ```
208
+
209
+ That is the point: no runtime field loop, no dispatch registry, no handwritten
210
+ template surgery. The generated function is plain Python, specialized to the
211
+ known schema, and suitable for hot-path use.
212
+
213
+ This is exactly the class of problem where a reliable AST stitcher matters:
214
+
215
+ - block fragments must land in the right lexical scope
216
+ - per-field steps must keep deterministic order
217
+ - compile-time schema data must become literal Python
218
+ - the final output must still be valid, inspectable source
219
+
220
+ ## Current surface
221
+
222
+ Astichi currently provides:
223
+
224
+ - `astichi.compile(source, file_name=None, line_number=1, offset=0)`
225
+ - `astichi.build()` for builder-based composition
226
+ - concrete composables with `.bind(...)`, `.describe()`, `.materialize()`, and
227
+ `.emit(...)` / `.emit_commented()`
228
+ - data-driven builder calls such as `builder.add("Root", root)` and
229
+ `builder.target(hole.with_root_instance("Root")).add("Step")`
230
+ - provenance helpers in `astichi.emit`
231
+
232
+ Supported pieces today include block holes, expression inserts, external
233
+ binding, managed Python imports, materialization, emission, and builder-driven
234
+ loop unrolling.
235
+
236
+ ## Layout
237
+
238
+ | Path | Role |
239
+ |------|------|
240
+ | `src/astichi/` | Library code |
241
+ | `docs/` | User-facing docs |
242
+ | `tests/` | Pytest suite |
243
+ | `dev-docs/` | Design notes, active summary, and requirements |
244
+ | `scratch/` | Throwaway experiments (not shipped) |
245
+
246
+ ## Development
247
+
248
+ ```bash
249
+ python -m venv .venv && source .venv/bin/activate
250
+ pip install -e ".[dev]"
251
+ PYTEST_DISABLE_PLUGIN_AUTOLOAD=1 python -m pytest
252
+ ```
253
+
254
+ ## Status
255
+
256
+ Early development (`0.1.0`), but already useful for controlled codegen
257
+ pipelines.
258
+
259
+ Start with:
260
+
261
+ - `docs/` for the user-facing surface
262
+ - `dev-docs/AstichiSingleSourceSummary.md` for the current implementation
263
+ snapshot and known gaps
264
+
265
+ ## License
266
+
267
+ MIT. See [LICENSE](LICENSE).
@@ -0,0 +1,17 @@
1
+ """astichi — AST composition for ahead-of-time Python codegen."""
2
+
3
+ __version__ = "0.1.0"
4
+
5
+ from astichi.builder import build
6
+ from astichi.frontend import compile
7
+ from astichi.model import Composable, ComposableDescription, ComposableHole, TargetAddress
8
+
9
+ __all__ = [
10
+ "__version__",
11
+ "Composable",
12
+ "ComposableDescription",
13
+ "ComposableHole",
14
+ "TargetAddress",
15
+ "build",
16
+ "compile",
17
+ ]