damlforge 0.0.13__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 (391) hide show
  1. damlforge-0.0.13/.claude/skills/damlforge-vy-lang/SKILL.md +83 -0
  2. damlforge-0.0.13/.claude/skills/damlforge-vy-lang/reference.md +445 -0
  3. damlforge-0.0.13/.github/workflows/build-wheel.yml +50 -0
  4. damlforge-0.0.13/.github/workflows/license-header.yml +19 -0
  5. damlforge-0.0.13/.github/workflows/publish-pypi.yml +66 -0
  6. damlforge-0.0.13/.gitignore +78 -0
  7. damlforge-0.0.13/LICENSE +201 -0
  8. damlforge-0.0.13/Makefile +89 -0
  9. damlforge-0.0.13/PKG-INFO +336 -0
  10. damlforge-0.0.13/README.md +293 -0
  11. damlforge-0.0.13/damlforge.egg-info/PKG-INFO +336 -0
  12. damlforge-0.0.13/damlforge.egg-info/SOURCES.txt +390 -0
  13. damlforge-0.0.13/damlforge.egg-info/dependency_links.txt +1 -0
  14. damlforge-0.0.13/damlforge.egg-info/entry_points.txt +2 -0
  15. damlforge-0.0.13/damlforge.egg-info/requires.txt +12 -0
  16. damlforge-0.0.13/damlforge.egg-info/top_level.txt +1 -0
  17. damlforge-0.0.13/docs/guide/01-dev-environment.md +376 -0
  18. damlforge-0.0.13/docs/guide/02-language-fundamentals.md +733 -0
  19. damlforge-0.0.13/docs/guide/03-compiler-errors.md +765 -0
  20. damlforge-0.0.13/docs/guide/04-contract-templates.md +255 -0
  21. damlforge-0.0.13/docs/guide/05-choices.md +441 -0
  22. damlforge-0.0.13/docs/guide/06-design-patterns.md +413 -0
  23. damlforge-0.0.13/docs/guide/07-working-with-time.md +307 -0
  24. damlforge-0.0.13/docs/guide/08-contract-keys.md +254 -0
  25. damlforge-0.0.13/docs/guide/09-interfaces.md +216 -0
  26. damlforge-0.0.13/docs/guide/10-building-packaging.md +190 -0
  27. damlforge-0.0.13/docs/guide/11-variants.md +465 -0
  28. damlforge-0.0.13/examples/basic/interfaces.vy +11 -0
  29. damlforge-0.0.13/examples/basic/models.vy +30 -0
  30. damlforge-0.0.13/examples/basic/recursion.vy +21 -0
  31. damlforge-0.0.13/examples/basic/simple.vy +104 -0
  32. damlforge-0.0.13/examples/crowd_loans/daml.yaml +22 -0
  33. damlforge-0.0.13/examples/crowd_loans/funding_campaign.py +1359 -0
  34. damlforge-0.0.13/examples/crowd_loans/loan_terms.vy +581 -0
  35. damlforge-0.0.13/examples/splice-api-token-burn-mint-v1/daml/Splice/Api/Token/burn_mint_v1.vy +40 -0
  36. damlforge-0.0.13/examples/splice-api-token-burn-mint-v1/daml.yaml +20 -0
  37. damlforge-0.0.13/examples/splice-util-batched-markers/daml/Splice/Util/FeaturedApp/BatchedMarkersProxy.daml +188 -0
  38. damlforge-0.0.13/examples/splice-util-batched-markers/daml/Splice/Util/FeaturedApp/batched_markers_proxy.vy +163 -0
  39. damlforge-0.0.13/examples/splice-util-batched-markers/daml.yaml +12 -0
  40. damlforge-0.0.13/examples/splice-util-batched-markers-test/daml.yaml +18 -0
  41. damlforge-0.0.13/examples/splice-util-batched-markers-test/deps/splice-token-standard-v1-test-3.4.8.dar +0 -0
  42. damlforge-0.0.13/examples/splice-wallet/daml/Splice/Wallet/buy_traffic_request.vy +99 -0
  43. damlforge-0.0.13/examples/splice-wallet/daml/Splice/Wallet/install.vy +1144 -0
  44. damlforge-0.0.13/examples/splice-wallet/daml/Splice/Wallet/minting_delegation.vy +201 -0
  45. damlforge-0.0.13/examples/splice-wallet/daml/Splice/Wallet/top_up_state.vy +40 -0
  46. damlforge-0.0.13/examples/splice-wallet/daml/Splice/Wallet/transfer_offer.vy +206 -0
  47. damlforge-0.0.13/examples/splice-wallet/daml/Splice/Wallet/transfer_preapproval.vy +58 -0
  48. damlforge-0.0.13/examples/splice-wallet/daml.yaml +33 -0
  49. damlforge-0.0.13/examples/token_standard/token_standard.vy +159 -0
  50. damlforge-0.0.13/forge/__init__.py +39 -0
  51. damlforge-0.0.13/forge/__main__.py +21 -0
  52. damlforge-0.0.13/forge/ast/README.md +122 -0
  53. damlforge-0.0.13/forge/ast/__init__.py +31 -0
  54. damlforge-0.0.13/forge/ast/__init__.pyi +7 -0
  55. damlforge-0.0.13/forge/ast/grammar.lark +334 -0
  56. damlforge-0.0.13/forge/ast/grammar.py +52 -0
  57. damlforge-0.0.13/forge/ast/identifiers.py +91 -0
  58. damlforge-0.0.13/forge/ast/metadata.py +98 -0
  59. damlforge-0.0.13/forge/ast/nodes.py +1585 -0
  60. damlforge-0.0.13/forge/ast/nodes.pyi +318 -0
  61. damlforge-0.0.13/forge/ast/parse.py +568 -0
  62. damlforge-0.0.13/forge/ast/pre_parser.py +411 -0
  63. damlforge-0.0.13/forge/ast/utils.py +91 -0
  64. damlforge-0.0.13/forge/builtin_stubs.py +281 -0
  65. damlforge-0.0.13/forge/builtins/DA/Action/State/Class.vy +14 -0
  66. damlforge-0.0.13/forge/builtins/DA/Action/State.vy +17 -0
  67. damlforge-0.0.13/forge/builtins/DA/Assert.vy +36 -0
  68. damlforge-0.0.13/forge/builtins/DA/Crypto/Text.vy +178 -0
  69. damlforge-0.0.13/forge/builtins/DA/Date/Types.vy +31 -0
  70. damlforge-0.0.13/forge/builtins/DA/Date.vy +67 -0
  71. damlforge-0.0.13/forge/builtins/DA/Either.vy +61 -0
  72. damlforge-0.0.13/forge/builtins/DA/Exception/ArithmeticError.vy +6 -0
  73. damlforge-0.0.13/forge/builtins/DA/Exception/AssertionFailed.vy +6 -0
  74. damlforge-0.0.13/forge/builtins/DA/Exception/GeneralError.vy +6 -0
  75. damlforge-0.0.13/forge/builtins/DA/Exception/PreconditionFailed.vy +6 -0
  76. damlforge-0.0.13/forge/builtins/DA/Internal/Assert.vy +23 -0
  77. damlforge-0.0.13/forge/builtins/DA/Internal/Compatible.vy +57 -0
  78. damlforge-0.0.13/forge/builtins/DA/Internal/Date.vy +13 -0
  79. damlforge-0.0.13/forge/builtins/DA/Internal/Down.vy +10 -0
  80. damlforge-0.0.13/forge/builtins/DA/Internal/Erased.vy +8 -0
  81. damlforge-0.0.13/forge/builtins/DA/Internal/Exception.vy +12 -0
  82. damlforge-0.0.13/forge/builtins/DA/Internal/Fail.vy +11 -0
  83. damlforge-0.0.13/forge/builtins/DA/Internal/Interface/AnyView.vy +18 -0
  84. damlforge-0.0.13/forge/builtins/DA/Internal/Interface.vy +54 -0
  85. damlforge-0.0.13/forge/builtins/DA/Internal/LF.vy +28 -0
  86. damlforge-0.0.13/forge/builtins/DA/Internal/NatSyn.vy +12 -0
  87. damlforge-0.0.13/forge/builtins/DA/Internal/Prelude.vy +186 -0
  88. damlforge-0.0.13/forge/builtins/DA/Internal/PromotedText.vy +12 -0
  89. damlforge-0.0.13/forge/builtins/DA/Internal/Record.vy +16 -0
  90. damlforge-0.0.13/forge/builtins/DA/Internal/Template/Functions.vy +130 -0
  91. damlforge-0.0.13/forge/builtins/DA/Internal/Template.vy +6 -0
  92. damlforge-0.0.13/forge/builtins/DA/Internal/Time.vy +22 -0
  93. damlforge-0.0.13/forge/builtins/DA/List/BuiltinOrder.vy +22 -0
  94. damlforge-0.0.13/forge/builtins/DA/List/Total.vy +21 -0
  95. damlforge-0.0.13/forge/builtins/DA/List.vy +135 -0
  96. damlforge-0.0.13/forge/builtins/DA/Logic/Types.vy +35 -0
  97. damlforge-0.0.13/forge/builtins/DA/Logic.vy +57 -0
  98. damlforge-0.0.13/forge/builtins/DA/Map.vy +61 -0
  99. damlforge-0.0.13/forge/builtins/DA/Math.vy +66 -0
  100. damlforge-0.0.13/forge/builtins/DA/Maybe.vy +46 -0
  101. damlforge-0.0.13/forge/builtins/DA/Monoid/Types.vy +25 -0
  102. damlforge-0.0.13/forge/builtins/DA/NonEmpty/Types.vy +11 -0
  103. damlforge-0.0.13/forge/builtins/DA/NonEmpty.vy +37 -0
  104. damlforge-0.0.13/forge/builtins/DA/Numeric.vy +113 -0
  105. damlforge-0.0.13/forge/builtins/DA/Optional.vy +46 -0
  106. damlforge-0.0.13/forge/builtins/DA/Random/Types.vy +13 -0
  107. damlforge-0.0.13/forge/builtins/DA/Random.vy +19 -0
  108. damlforge-0.0.13/forge/builtins/DA/Semigroup/Types.vy +15 -0
  109. damlforge-0.0.13/forge/builtins/DA/Set/Types.vy +11 -0
  110. damlforge-0.0.13/forge/builtins/DA/Set.vy +81 -0
  111. damlforge-0.0.13/forge/builtins/DA/Stack/Types.vy +14 -0
  112. damlforge-0.0.13/forge/builtins/DA/Stack.vy +33 -0
  113. damlforge-0.0.13/forge/builtins/DA/Text.vy +192 -0
  114. damlforge-0.0.13/forge/builtins/DA/TextMap.vy +53 -0
  115. damlforge-0.0.13/forge/builtins/DA/Time/Types.vy +6 -0
  116. damlforge-0.0.13/forge/builtins/DA/Time.vy +72 -0
  117. damlforge-0.0.13/forge/builtins/DA/Tuple.vy +26 -0
  118. damlforge-0.0.13/forge/builtins/DA/Types.vy +329 -0
  119. damlforge-0.0.13/forge/builtins/DA/Validation/Types.vy +25 -0
  120. damlforge-0.0.13/forge/builtins/DA/Validation.vy +34 -0
  121. damlforge-0.0.13/forge/builtins/GHC/Base.vy +13 -0
  122. damlforge-0.0.13/forge/builtins/GHC/Classes.vy +43 -0
  123. damlforge-0.0.13/forge/builtins/GHC/Enum.vy +86 -0
  124. damlforge-0.0.13/forge/builtins/GHC/Err.vy +10 -0
  125. damlforge-0.0.13/forge/builtins/GHC/Num.vy +32 -0
  126. damlforge-0.0.13/forge/builtins/GHC/Show/Text.vy +72 -0
  127. damlforge-0.0.13/forge/builtins/GHC/Show.vy +38 -0
  128. damlforge-0.0.13/forge/builtins/GHC/Stack/Types.vy +53 -0
  129. damlforge-0.0.13/forge/builtins/GHC/Tuple.vy +10 -0
  130. damlforge-0.0.13/forge/builtins/GHC/Types.vy +10 -0
  131. damlforge-0.0.13/forge/builtins/Splice/Amulet/CryptoHash.vy +59 -0
  132. damlforge-0.0.13/forge/builtins/Splice/Amulet/RewardAccountingV2.vy +67 -0
  133. damlforge-0.0.13/forge/builtins/Splice/Amulet/TokenApiUtils.vy +217 -0
  134. damlforge-0.0.13/forge/builtins/Splice/Amulet/TwoStepTransfer.vy +43 -0
  135. damlforge-0.0.13/forge/builtins/Splice/Amulet.vy +442 -0
  136. damlforge-0.0.13/forge/builtins/Splice/AmuletAllocation.vy +54 -0
  137. damlforge-0.0.13/forge/builtins/Splice/AmuletAllocationV2.vy +53 -0
  138. damlforge-0.0.13/forge/builtins/Splice/AmuletConfig.vy +147 -0
  139. damlforge-0.0.13/forge/builtins/Splice/AmuletEventLog.vy +8 -0
  140. damlforge-0.0.13/forge/builtins/Splice/AmuletRules.vy +901 -0
  141. damlforge-0.0.13/forge/builtins/Splice/AmuletTransferInstruction.vy +37 -0
  142. damlforge-0.0.13/forge/builtins/Splice/Ans/AmuletConversionRateFeed.vy +42 -0
  143. damlforge-0.0.13/forge/builtins/Splice/Ans.vy +173 -0
  144. damlforge-0.0.13/forge/builtins/Splice/Api/FeaturedAppRightV1.vy +41 -0
  145. damlforge-0.0.13/forge/builtins/Splice/Api/FeaturedAppRightV2.vy +41 -0
  146. damlforge-0.0.13/forge/builtins/Splice/Api/RewardAssignmentV1.vy +36 -0
  147. damlforge-0.0.13/forge/builtins/Splice/Api/Token/AllocationInstructionV1.vy +92 -0
  148. damlforge-0.0.13/forge/builtins/Splice/Api/Token/AllocationInstructionV2.vy +132 -0
  149. damlforge-0.0.13/forge/builtins/Splice/Api/Token/AllocationRequestV1.vy +32 -0
  150. damlforge-0.0.13/forge/builtins/Splice/Api/Token/AllocationRequestV2.vy +96 -0
  151. damlforge-0.0.13/forge/builtins/Splice/Api/Token/AllocationV1.vy +91 -0
  152. damlforge-0.0.13/forge/builtins/Splice/Api/Token/AllocationV2.vy +210 -0
  153. damlforge-0.0.13/forge/builtins/Splice/Api/Token/BurnMintV1.vy +41 -0
  154. damlforge-0.0.13/forge/builtins/Splice/Api/Token/HoldingV1.vy +30 -0
  155. damlforge-0.0.13/forge/builtins/Splice/Api/Token/HoldingV2.vy +36 -0
  156. damlforge-0.0.13/forge/builtins/Splice/Api/Token/MetadataV1.vy +113 -0
  157. damlforge-0.0.13/forge/builtins/Splice/Api/Token/Test/DummyHolding.vy +10 -0
  158. damlforge-0.0.13/forge/builtins/Splice/Api/Token/Test/DummyTwoInterfaces.vy +13 -0
  159. damlforge-0.0.13/forge/builtins/Splice/Api/Token/TransferEventsV2.vy +42 -0
  160. damlforge-0.0.13/forge/builtins/Splice/Api/Token/TransferInstructionV1.vy +135 -0
  161. damlforge-0.0.13/forge/builtins/Splice/Api/Token/TransferInstructionV2.vy +159 -0
  162. damlforge-0.0.13/forge/builtins/Splice/AppManager/Store.vy +52 -0
  163. damlforge-0.0.13/forge/builtins/Splice/CometBft.vy +56 -0
  164. damlforge-0.0.13/forge/builtins/Splice/DSO/AmuletPrice.vy +24 -0
  165. damlforge-0.0.13/forge/builtins/Splice/DSO/DecentralizedSynchronizer.vy +100 -0
  166. damlforge-0.0.13/forge/builtins/Splice/DSO/SvState.vy +67 -0
  167. damlforge-0.0.13/forge/builtins/Splice/DecentralizedSynchronizer.vy +54 -0
  168. damlforge-0.0.13/forge/builtins/Splice/DsoBootstrap.vy +40 -0
  169. damlforge-0.0.13/forge/builtins/Splice/DsoRules.vy +1077 -0
  170. damlforge-0.0.13/forge/builtins/Splice/Expiry.vy +92 -0
  171. damlforge-0.0.13/forge/builtins/Splice/ExternalPartyAmuletRules.vy +146 -0
  172. damlforge-0.0.13/forge/builtins/Splice/ExternalPartyConfigState.vy +20 -0
  173. damlforge-0.0.13/forge/builtins/Splice/Fees.vy +125 -0
  174. damlforge-0.0.13/forge/builtins/Splice/Issuance.vy +79 -0
  175. damlforge-0.0.13/forge/builtins/Splice/RelRound.vy +16 -0
  176. damlforge-0.0.13/forge/builtins/Splice/Round.vy +80 -0
  177. damlforge-0.0.13/forge/builtins/Splice/Schedule.vy +54 -0
  178. damlforge-0.0.13/forge/builtins/Splice/Splitwell.vy +238 -0
  179. damlforge-0.0.13/forge/builtins/Splice/SvOnboarding.vy +53 -0
  180. damlforge-0.0.13/forge/builtins/Splice/Testing/Apps/TradingApp.vy +78 -0
  181. damlforge-0.0.13/forge/builtins/Splice/Testing/Apps/TradingAppV2.vy +159 -0
  182. damlforge-0.0.13/forge/builtins/Splice/Testing/Tokens/TestTokenV1.vy +50 -0
  183. damlforge-0.0.13/forge/builtins/Splice/Testing/Tokens/TestTokenV2/AccountConfig.vy +212 -0
  184. damlforge-0.0.13/forge/builtins/Splice/Testing/Tokens/TestTokenV2/Allocation.vy +140 -0
  185. damlforge-0.0.13/forge/builtins/Splice/Testing/Tokens/TestTokenV2/Holding.vy +20 -0
  186. damlforge-0.0.13/forge/builtins/Splice/Testing/Tokens/TestTokenV2/Transfer.vy +60 -0
  187. damlforge-0.0.13/forge/builtins/Splice/Testing/Tokens/TestTokenV2/Util.vy +47 -0
  188. damlforge-0.0.13/forge/builtins/Splice/Testing/Tokens/TestTokenV2.vy +40 -0
  189. damlforge-0.0.13/forge/builtins/Splice/TokenStandard/Utils/Internal/Allocations.vy +251 -0
  190. damlforge-0.0.13/forge/builtins/Splice/TokenStandard/Utils/Internal/Choices.vy +71 -0
  191. damlforge-0.0.13/forge/builtins/Splice/TokenStandard/Utils/Internal/Conversions.vy +229 -0
  192. damlforge-0.0.13/forge/builtins/Splice/TokenStandard/Utils/Internal/Events.vy +77 -0
  193. damlforge-0.0.13/forge/builtins/Splice/TokenStandard/Utils/Internal/Transfers.vy +50 -0
  194. damlforge-0.0.13/forge/builtins/Splice/TokenStandard/Utils.vy +5 -0
  195. damlforge-0.0.13/forge/builtins/Splice/Types.vy +25 -0
  196. damlforge-0.0.13/forge/builtins/Splice/Util/FeaturedApp/BatchedMarkersProxy.vy +47 -0
  197. damlforge-0.0.13/forge/builtins/Splice/Util/FeaturedApp/DelegateProxy.vy +68 -0
  198. damlforge-0.0.13/forge/builtins/Splice/Util/FeaturedApp/WalletUserProxy.vy +127 -0
  199. damlforge-0.0.13/forge/builtins/Splice/Util/Token/Wallet/BatchingUtilityV2.vy +270 -0
  200. damlforge-0.0.13/forge/builtins/Splice/Util/Token/Wallet/MergeDelegation.vy +130 -0
  201. damlforge-0.0.13/forge/builtins/Splice/Util.vy +116 -0
  202. damlforge-0.0.13/forge/builtins/Splice/ValidatorLicense.vy +164 -0
  203. damlforge-0.0.13/forge/builtins/Splice/ValidatorOnboarding.vy +42 -0
  204. damlforge-0.0.13/forge/builtins/Splice/Wallet/BuyTrafficRequest.vy +56 -0
  205. damlforge-0.0.13/forge/builtins/Splice/Wallet/Install.vy +469 -0
  206. damlforge-0.0.13/forge/builtins/Splice/Wallet/MintingDelegation.vy +83 -0
  207. damlforge-0.0.13/forge/builtins/Splice/Wallet/Payment.vy +160 -0
  208. damlforge-0.0.13/forge/builtins/Splice/Wallet/Subscriptions.vy +233 -0
  209. damlforge-0.0.13/forge/builtins/Splice/Wallet/TopUpState.vy +22 -0
  210. damlforge-0.0.13/forge/builtins/Splice/Wallet/TransferOffer.vy +114 -0
  211. damlforge-0.0.13/forge/builtins/Splice/Wallet/TransferPreapproval.vy +27 -0
  212. damlforge-0.0.13/forge/builtins/__init__.py +618 -0
  213. damlforge-0.0.13/forge/builtins/daml_lang.py +161 -0
  214. damlforge-0.0.13/forge/builtins/maps.py +78 -0
  215. damlforge-0.0.13/forge/cli/__init__.py +14 -0
  216. damlforge-0.0.13/forge/cli/forge_daml.py +95 -0
  217. damlforge-0.0.13/forge/cli/forge_dar.py +189 -0
  218. damlforge-0.0.13/forge/cli/forge_json.py +26 -0
  219. damlforge-0.0.13/forge/cli/main.py +207 -0
  220. damlforge-0.0.13/forge/codegen/__init__.py +19 -0
  221. damlforge-0.0.13/forge/codegen/doc.py +78 -0
  222. damlforge-0.0.13/forge/codegen/emit.py +1384 -0
  223. damlforge-0.0.13/forge/codegen/loops.py +24 -0
  224. damlforge-0.0.13/forge/codegen/maps.py +76 -0
  225. damlforge-0.0.13/forge/codegen/optional.py +54 -0
  226. damlforge-0.0.13/forge/codegen/self_mutation.py +358 -0
  227. damlforge-0.0.13/forge/codegen/sets.py +55 -0
  228. damlforge-0.0.13/forge/codegen/source_map.py +263 -0
  229. damlforge-0.0.13/forge/compiler/__init__.py +14 -0
  230. damlforge-0.0.13/forge/compiler/settings.py +92 -0
  231. damlforge-0.0.13/forge/daml_versions.py +112 -0
  232. damlforge-0.0.13/forge/damlforge_git_commithash.txt +1 -0
  233. damlforge-0.0.13/forge/exceptions.py +459 -0
  234. damlforge-0.0.13/forge/ir/__init__.py +18 -0
  235. damlforge-0.0.13/forge/ir/fields.py +84 -0
  236. damlforge-0.0.13/forge/ir/imports.py +217 -0
  237. damlforge-0.0.13/forge/ir/lower.py +904 -0
  238. damlforge-0.0.13/forge/ir/nodes.py +399 -0
  239. damlforge-0.0.13/forge/ir/normalize.py +853 -0
  240. damlforge-0.0.13/forge/models/__init__.py +53 -0
  241. damlforge-0.0.13/forge/models/decorators.py +48 -0
  242. damlforge-0.0.13/forge/models/error_codes.py +53 -0
  243. damlforge-0.0.13/forge/models/types.py +30 -0
  244. damlforge-0.0.13/forge/semantics/__init__.py +40 -0
  245. damlforge-0.0.13/forge/semantics/analysis/__init__.py +14 -0
  246. damlforge-0.0.13/forge/semantics/analysis/imports.py +453 -0
  247. damlforge-0.0.13/forge/semantics/analysis/intrinsics.py +480 -0
  248. damlforge-0.0.13/forge/semantics/analysis/module.py +360 -0
  249. damlforge-0.0.13/forge/semantics/analysis/primitive_values.py +320 -0
  250. damlforge-0.0.13/forge/semantics/analysis/structure.py +767 -0
  251. damlforge-0.0.13/forge/semantics/analysis/typecheck.py +947 -0
  252. damlforge-0.0.13/forge/semantics/analysis/types.py +1234 -0
  253. damlforge-0.0.13/forge/semantics/primitive_specs.py +277 -0
  254. damlforge-0.0.13/forge/stubgen/__init__.py +78 -0
  255. damlforge-0.0.13/forge/stubgen/dar.py +86 -0
  256. damlforge-0.0.13/forge/stubgen/exports.py +46 -0
  257. damlforge-0.0.13/forge/stubgen/lf2.py +88 -0
  258. damlforge-0.0.13/forge/stubgen/parties.py +128 -0
  259. damlforge-0.0.13/forge/stubgen/render.py +571 -0
  260. damlforge-0.0.13/forge/utils.py +713 -0
  261. damlforge-0.0.13/forge/version.py +4 -0
  262. damlforge-0.0.13/forge/warnings.py +75 -0
  263. damlforge-0.0.13/make.cmd +77 -0
  264. damlforge-0.0.13/pyproject.toml +140 -0
  265. damlforge-0.0.13/quicktest.sh +18 -0
  266. damlforge-0.0.13/setup.cfg +19 -0
  267. damlforge-0.0.13/setup.py +99 -0
  268. damlforge-0.0.13/tests/ast/test_call_dict_arg.py +54 -0
  269. damlforge-0.0.13/tests/ast/test_container_keywords.py +190 -0
  270. damlforge-0.0.13/tests/builtins/test_daml_lang.py +705 -0
  271. damlforge-0.0.13/tests/codegen/test_source_map.py +115 -0
  272. damlforge-0.0.13/tests/compiler/test_codegen.py +594 -0
  273. damlforge-0.0.13/tests/compiler/test_codegen_examples.py +151 -0
  274. damlforge-0.0.13/tests/compiler/test_contract_keys.py +132 -0
  275. damlforge-0.0.13/tests/compiler/test_daml_versions.py +65 -0
  276. damlforge-0.0.13/tests/compiler/test_diagnostics.py +34 -0
  277. damlforge-0.0.13/tests/compiler/test_fuzz_crash_regressions.py +400 -0
  278. damlforge-0.0.13/tests/compiler/test_loop_report_regressions.py +224 -0
  279. damlforge-0.0.13/tests/compiler/test_self_mutation.py +172 -0
  280. damlforge-0.0.13/tests/examples/test_token_standard.py +93 -0
  281. damlforge-0.0.13/tests/ir/test_lower.py +905 -0
  282. damlforge-0.0.13/tests/ir/test_lower_examples.py +53 -0
  283. damlforge-0.0.13/tests/models/test_containers.py +89 -0
  284. damlforge-0.0.13/tests/models/test_decorators.py +102 -0
  285. damlforge-0.0.13/tests/models/test_types.py +45 -0
  286. damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/as_import_not_allowed.vy +12 -0
  287. damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/bytes_type_not_allowed.vy +7 -0
  288. damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/choice_all_underscore_name_not_allowed.vy +10 -0
  289. damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/choice_double_leading_underscore_name_not_allowed.vy +10 -0
  290. damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/choice_leading_underscore_name_not_allowed.vy +10 -0
  291. damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/choice_missing_consuming.vy +10 -0
  292. damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/choice_missing_controller.vy +10 -0
  293. damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/choice_name_with_no_letter_not_allowed.vy +10 -0
  294. damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/choice_non_literal_consuming.vy +10 -0
  295. damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/choice_observer_references_non_field_self_attribute_not_allowed.vy +10 -0
  296. damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/choice_observer_references_unrelated_choice_arg_not_allowed.vy +15 -0
  297. damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/choice_postconsuming_on_instance.vy +22 -0
  298. damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/choice_preconsuming_on_interface.vy +8 -0
  299. damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/complex_type_not_allowed.vy +7 -0
  300. damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/create_used_without_import_not_allowed.vy +11 -0
  301. damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/daml_name_with_no_arguments_not_allowed.vy +12 -0
  302. damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/daml_name_with_non_literal_argument_not_allowed.vy +12 -0
  303. damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/decorator_used_without_import_not_allowed.vy +10 -0
  304. damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/dict_type_not_allowed.vy +7 -0
  305. damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/double_imports_not_allowed.vy +13 -0
  306. damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/enum_member_lowercase_not_allowed.vy +12 -0
  307. damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/enum_member_mixed_case_not_allowed.vy +12 -0
  308. damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/enum_member_value_not_allowed.vy +5 -0
  309. damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/enum_value_access_unknown_member.vy +16 -0
  310. damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/exercise_by_key_without_template_not_allowed.vy +20 -0
  311. damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/function_call_with_incompatible_argument_type_not_allowed.vy +15 -0
  312. damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/function_call_with_mismatched_list_element_type_not_allowed.vy +17 -0
  313. damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/function_call_with_wrong_argument_count_not_allowed.vy +14 -0
  314. damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/hidden_ledger_effect.vy +9 -0
  315. damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/hidden_ledger_effect_top_level.vy +16 -0
  316. damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/ledger_effect_with_args.vy +9 -0
  317. damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/missing_import.vy +10 -0
  318. damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/multiple_violations.vy +11 -0
  319. damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/recursion_single_func.vy +22 -0
  320. damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/self_reference_via_template_name_not_allowed.vy +11 -0
  321. damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/template_choice_and_method_same_name.vy +18 -0
  322. damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/template_duplicate_reserved_declarations.vy +15 -0
  323. damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/template_empty_observer.vy +13 -0
  324. damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/template_empty_signatory.vy +12 -0
  325. damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/template_ensure_arithmetic_expression.vy +8 -0
  326. damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/template_ensure_non_boolean_literal.vy +8 -0
  327. damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/template_ensure_without_value.vy +7 -0
  328. damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/template_key_without_annotation_not_allowed.vy +11 -0
  329. damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/template_key_without_maintainer.vy +8 -0
  330. damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/template_maintainer_from_field_not_allowed.vy +11 -0
  331. damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/template_maintainer_without_key.vy +8 -0
  332. damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/template_method_without_choice.vy +14 -0
  333. damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/template_missing_signatory.vy +11 -0
  334. damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/template_via_decorator_missing_signatory.vy +8 -0
  335. damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/to_interface_contract_id_used_without_import_not_allowed.vy +20 -0
  336. damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/unknown_decorator_not_allowed.vy +13 -0
  337. damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/unknown_map_type_not_allowed.vy +7 -0
  338. damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/unresolvable_bare_import_not_allowed.vy +12 -0
  339. damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/unresolvable_import_not_allowed.vy +12 -0
  340. damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/unresolved_name_used_as_attribute_base_not_allowed.vy +11 -0
  341. damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/unresolved_name_used_as_call_target_not_allowed.vy +11 -0
  342. damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/view_in_template.vy +10 -0
  343. damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/view_used_without_import_not_allowed.vy +17 -0
  344. damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/view_with_args.vy +8 -0
  345. damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/visible_by_key_on_template_without_key_not_allowed.vy +13 -0
  346. damlforge-0.0.13/tests/semantics/fixtures/structure/invalid/wildcard_missing_import_not_allowed.vy +12 -0
  347. damlforge-0.0.13/tests/semantics/fixtures/structure/valid/choice_body_ledger_effect_is_allowed.vy +13 -0
  348. damlforge-0.0.13/tests/semantics/fixtures/structure/valid/choice_postconsuming_on_template_is_allowed.vy +13 -0
  349. damlforge-0.0.13/tests/semantics/fixtures/structure/valid/choice_preconsuming_on_template_is_allowed.vy +13 -0
  350. damlforge-0.0.13/tests/semantics/fixtures/structure/valid/choice_string_consuming_on_template_is_allowed.vy +13 -0
  351. damlforge-0.0.13/tests/semantics/fixtures/structure/valid/choice_with_observer_is_allowed.vy +13 -0
  352. damlforge-0.0.13/tests/semantics/fixtures/structure/valid/compatible_function_call_argument_types_are_allowed.vy +17 -0
  353. damlforge-0.0.13/tests/semantics/fixtures/structure/valid/contract_key_builtins_are_allowed.vy +55 -0
  354. damlforge-0.0.13/tests/semantics/fixtures/structure/valid/daml_name_overrides_choice_name_is_allowed.vy +14 -0
  355. damlforge-0.0.13/tests/semantics/fixtures/structure/valid/enum_value_access_is_allowed.vy +18 -0
  356. damlforge-0.0.13/tests/semantics/fixtures/structure/valid/frozenset_field_is_allowed.vy +9 -0
  357. damlforge-0.0.13/tests/semantics/fixtures/structure/valid/genmap_field_is_allowed.vy +9 -0
  358. damlforge-0.0.13/tests/semantics/fixtures/structure/valid/imported_ledger_builtins_are_allowed.vy +37 -0
  359. damlforge-0.0.13/tests/semantics/fixtures/structure/valid/interface_choice_controller_uses_view_is_allowed.vy +9 -0
  360. damlforge-0.0.13/tests/semantics/fixtures/structure/valid/known_builtin_and_struct_constructor_call_targets_are_allowed.vy +18 -0
  361. damlforge-0.0.13/tests/semantics/fixtures/structure/valid/ledger_effect_marked_is_allowed.vy +12 -0
  362. damlforge-0.0.13/tests/semantics/fixtures/structure/valid/local_variable_used_as_attribute_base_is_allowed.vy +14 -0
  363. damlforge-0.0.13/tests/semantics/fixtures/structure/valid/self_reference_via_another_template_name_is_allowed.vy +23 -0
  364. damlforge-0.0.13/tests/semantics/fixtures/structure/valid/set_field_is_allowed.vy +9 -0
  365. damlforge-0.0.13/tests/semantics/fixtures/structure/valid/template_ensure_boolop_is_allowed.vy +11 -0
  366. damlforge-0.0.13/tests/semantics/fixtures/structure/valid/template_ensure_call_is_allowed.vy +11 -0
  367. damlforge-0.0.13/tests/semantics/fixtures/structure/valid/template_ensure_compare_is_allowed.vy +11 -0
  368. damlforge-0.0.13/tests/semantics/fixtures/structure/valid/template_key_with_maintainer_is_allowed.vy +12 -0
  369. damlforge-0.0.13/tests/semantics/fixtures/structure/valid/template_with_ellipsis.vy +13 -0
  370. damlforge-0.0.13/tests/semantics/fixtures/structure/valid/template_without_ensure_is_allowed.vy +9 -0
  371. damlforge-0.0.13/tests/semantics/fixtures/structure/valid/template_without_key_or_maintainer_is_allowed.vy +9 -0
  372. damlforge-0.0.13/tests/semantics/fixtures/structure/valid/textmap_field_is_allowed.vy +10 -0
  373. damlforge-0.0.13/tests/semantics/fixtures/structure/valid/valid_template.vy +13 -0
  374. damlforge-0.0.13/tests/semantics/fixtures/structure/valid/valid_template_via_decorator.vy +13 -0
  375. damlforge-0.0.13/tests/semantics/fixtures/structure/valid/view_in_interface_is_allowed.vy +11 -0
  376. damlforge-0.0.13/tests/semantics/fixtures/type_annotations/invalid/choice_arg_unknown_type.vy +11 -0
  377. damlforge-0.0.13/tests/semantics/fixtures/type_annotations/invalid/choice_return_unknown_type.vy +11 -0
  378. damlforge-0.0.13/tests/semantics/fixtures/type_annotations/invalid/function_arg_unknown_type.vy +3 -0
  379. damlforge-0.0.13/tests/semantics/fixtures/type_annotations/invalid/interface_view_unknown_type.vy +3 -0
  380. damlforge-0.0.13/tests/semantics/fixtures/type_annotations/invalid/nested_generic_unknown_type.vy +9 -0
  381. damlforge-0.0.13/tests/semantics/fixtures/type_annotations/invalid/struct_field_unknown_type.vy +3 -0
  382. damlforge-0.0.13/tests/semantics/fixtures/type_annotations/invalid/template_field_unknown_type.vy +7 -0
  383. damlforge-0.0.13/tests/semantics/fixtures/type_annotations/valid/generic_field_types_are_allowed.vy +8 -0
  384. damlforge-0.0.13/tests/semantics/fixtures/type_annotations/valid/local_struct_reference_is_allowed.vy +7 -0
  385. damlforge-0.0.13/tests/semantics/fixtures/type_annotations/valid/primitive_field_types_are_allowed.vy +11 -0
  386. damlforge-0.0.13/tests/semantics/test_primitive_policies.py +150 -0
  387. damlforge-0.0.13/tests/semantics/test_structure.py +378 -0
  388. damlforge-0.0.13/tests/semantics/test_type_annotations.py +79 -0
  389. damlforge-0.0.13/tests/semantics/test_type_checking.py +194 -0
  390. damlforge-0.0.13/tests/stubgen/test_lf2.py +100 -0
  391. damlforge-0.0.13/tests/test_utils.py +26 -0
@@ -0,0 +1,83 @@
1
+ ---
2
+ name: damlforge-vy-lang
3
+ description: Use when writing, reading, or reviewing .vy source files in the DamlForge compiler (this repo) - a Python/Vyper-syntax DSL that compiles to real Daml/Canton smart contracts. Applies whenever asked to author a Daml template/choice/interface in .vy, translate a .daml file to .vy, or explain DF12xx compiler errors.
4
+ ---
5
+
6
+ # DamlForge .vy Language
7
+
8
+ ## Overview
9
+
10
+ DamlForge compiles `.vy` files (Python syntax, Vyper-flavored keywords) into real `.daml` source. It is NOT Vyper (no EVM/gas/storage concepts survive) and NOT Python (nothing executes - it's an AST that lowers straight to Daml). Full detail: [reference.md](reference.md).
11
+
12
+ ## Current project workflow
13
+
14
+ - Use `python -m forge daml <file-or-directory> -o <directory>` for source generation. A file input produces one `.daml` file and a `.map.json` source map; a directory input covers only `.vy` files directly in that directory.
15
+ - Use `python -m forge dar <project-directory> -o <file.dar>` for a real package build. The project must already have a valid `daml.yaml`; DamlForge recursively compiles `.vy` files below its `source` directory and then invokes DPM.
16
+ - Use `python -m forge stubs <file.dar> -o <directory>` to reconstruct supported declarations as `.vy`. Stub generation requires `pip install 'damlforge[stubgen]'`; a project directory can be supplied instead of a DAR and will be built with DPM.
17
+ - Use `daml test --all` when test coverage must include templates and choices imported from data-dependency DARs. Plain `daml test` can report only the package-local definitions.
18
+ - DPM is resolved from `PATH`, then `~/.dpm/bin/dpm`; pass `--dpm PATH` when necessary. Add `--traceback` while diagnosing compiler failures. `forge daml --no-i` makes the default error-tolerant multi-file compile fail on the first error.
19
+
20
+ ## Before writing any .vy file
21
+
22
+ 1. Every field/type name in the file must resolve to one of: a Python-native type (including `date`, `datetime`, and `timedelta` imported from Python's `datetime` module), a DamlForge builtin type (`Party`, `Decimal`, `Int`, `ContractId[T]`, `GenMap[K,V]`, `TextMap[T]`), or a `struct`/`template`/`interface`/`flag`/`variant` declared/imported in scope. See reference.md § Type System.
23
+ 2. Function and method decorators (`@choice`, `@view`, `@variant_record`, `@DamlName`) must be imported from `forge.models` or `forge.builtins`. The `@template` and `@variant` class markers must be imported from `forge.models` too. Ledger operations (`create`, `fetch`, `exercise`, `archive`, the by-key functions, interface conversions) must be imported from `forge.builtins.daml_lang`. See reference.md § Decorators and § Ledger primitives.
24
+ 3. Every `template` needs `signatory`. `key` requires `maintainer` and vice versa; `key` needs a type annotation, `maintainer` is computed from `key` only (`DF1236`), and keys need SDK 3.5 with `--target=2.3` (`DF1234`). Annotate the result of `fetch_by_key`/`lookup_by_key`/`lookup_all_by_key`/`lookup_n_by_key` so Daml can infer the template; `exercise_by_key(T, key, T.Choice(...))` and `visible_by_key(T, key)` take the template first (`DF1235`). `ensure` (if present) must be a `bool`-typed comparison/boolop/call, never bare arithmetic. See reference.md § Template Fields.
25
+ 4. Daml update effects are inferred automatically from calls to `fetch`/`exercise`/`create`/`archive`/`*_by_key` and from transitive calls to functions containing those operations. Choices are already update contexts. See reference.md § Ledger Effects.
26
+ 5. Never put a `def` inside a `struct` - it is silently dropped, no error. Use a free top-level function instead.
27
+
28
+ Generated stubs may also contain `@no_derive` from `forge.builtins` when the DAR
29
+ does not expose the equality/show instances needed for normal DamlForge derivation.
30
+ Keep that marker when editing a generated stub unless you intentionally want to
31
+ change the generated Daml derivations.
32
+
33
+ ## Quick Reference
34
+
35
+ | Concept | `.vy` syntax |
36
+ |---|---|
37
+ | Record type | `struct Foo:` |
38
+ | Contract type | `@template\nclass Foo:` |
39
+ | Interface | `interface Foo(view=FooView):` |
40
+ | Interface impl | `@template\nclass Bar(Foo):` (subclass the interface directly - no `instance` keyword) |
41
+ | Payload variant | `@variant\nclass Result:\n def Ok(value: int): pass` |
42
+ | Named-field variant constructor | `@variant_record` on a constructor method; emits Daml `Constructor with ...` |
43
+ | Payload-free enum | `flag Status:\n PENDING\n PAID` (members MUST be `SCREAMING_CASE`) |
44
+ | Choice | `@choice(controller=..., consuming=True)` |
45
+ | Fetch/exercise/create/archive | `from forge.builtins.daml_lang import create, fetch, ...` - required, `DF1219` otherwise |
46
+ | Optional field | `Optional[X]` - never write `Some(...)`/`from_some(...)` yourself, the compiler inserts it |
47
+ | Current ledger time | `datetime.now()` from Python's `datetime`; DamlForge infers the enclosing function as an update |
48
+ | Calendar date | `date(year, month, day)` from Python's `datetime`; integer months are `1..12` |
49
+ | Date and time | `datetime.combine(date_value, time(hour, minute, second))`; lowers to `DA.Time.time` |
50
+ | Add relative time | `timestamp + timedelta(...)`; lowers to `DA.Time.addRelTime` |
51
+ | Time difference | `later - earlier`; typed datetimes lower to `DA.Time.subTime` |
52
+ | Unix timestamp | `datetime.fromtimestamp(seconds, timezone.utc)`; lowers to `DA.Time.fromUnixMicroseconds` |
53
+ | Relative time | `timedelta(days=..., hours=...)` from Python's `datetime`; lowers to `DA.Time` |
54
+ | Map | `GenMap[K, V]` / `TextMap[V]`, dict literal `{...}`, `m[k]`, `k in m` |
55
+ | Typed for-loop | `for x: T in xs:` (annotation is optional when the iterable type is known) |
56
+
57
+ For date/time values, import Python's standard types directly:
58
+
59
+ ```python
60
+ from datetime import date, datetime, time, timedelta, timezone
61
+ ```
62
+
63
+ Never import `Date`, `Timestamp`, or `RelTime` from `forge.models`. They are
64
+ represented by `date`, `datetime`, and `timedelta`. Use `datetime.now()` only
65
+ in Daml update contexts. See reference.md § Type System for constructors,
66
+ arithmetic, and Unix timestamp conversion.
67
+
68
+ ## Common Mistakes
69
+
70
+ | Mistake | Fix |
71
+ |---|---|
72
+ | Using `@template`/`@variant`/`@choice`/`@view`/`@variant_record` without importing it | Import it from `forge.models` (`DF1219` otherwise) |
73
+ | Calling `create`/`fetch`/`exercise`/`to_interface_contract_id`/... without importing it | Import it from `forge.builtins.daml_lang` (`DF1219` otherwise); only `len`/`range`/`ceil`/`floor` are import-free |
74
+ | Using `@variant_record` for every constructor | Use it only for Daml named-field (`with`) constructors; omit it for positional constructors |
75
+ | Calling a custom `days(...)` helper | Import `timedelta` from `datetime` and use `timedelta(days=...)`; `years=` is not a Python or Daml fixed-duration unit |
76
+ | Writing `def helper(): ...` inside a `struct` | Move it to a top-level `def`; structs are plain data records |
77
+ | `controller=`/`observer=` referencing a name that isn't a with-arg, a template field, or `self.<field>` | Only reference the choice's own arguments/fields - anything else either resolves to an unrelated same-named field or fails `damlc` with "Ambiguous occurrence" (`DF1224`) |
78
+ | `key` without `maintainer` (or vice versa) | Always declare both together (`DF1210`/`DF1211`) |
79
+ | A bare `def` calling `archive(self)`/`fetch(...)` etc. | No marker is needed; DamlForge infers the function as an update |
80
+ | `from X import Y as Z` | Aliased from-imports are banned; use `import X as Y` (module alias) instead if disambiguation is needed |
81
+ | `dict[K, V]` or a hand-rolled `Map[...]` field | Use `GenMap[K, V]` / `TextMap[V]` |
82
+
83
+ Full syntax, decorator/builtin tables, type system, error-code index, and a worked example: [reference.md](reference.md).
@@ -0,0 +1,445 @@
1
+ # DamlForge `.vy` Language Reference
2
+
3
+ `.vy` files are tokenized Python, re-keyworded by a pre-parser, then lowered straight to Daml source (`forge/ir`, `forge/codegen`). There is no runtime: nothing in a `.vy` file is ever executed by Python. Compile with:
4
+
5
+ ```
6
+ python -m forge daml <file_or_dir> -o <out_dir> # .vy -> .daml
7
+ python -m forge dar <project_dir> -o <out.dar> # .vy -> .daml -> real .dar via dpm build
8
+ python -m forge json <file> # .vy -> JSON AST (or read stdin)
9
+ python -m forge stubs <file.dar> -o <out_dir> # DAR -> supported .vy declarations
10
+ # `python -m forge <file_or_dir> -o <out_dir>` (no subcommand) is shorthand for `daml`
11
+ ```
12
+
13
+ `forge daml` writes both `<Module>.daml` and `<Module>.map.json`. Directory input
14
+ compiles only `.vy` files directly in that directory. `forge dar` requires an existing
15
+ Daml project with `daml.yaml` fields `name`, `source`, `version`, and a non-empty
16
+ `dependencies` list; it recursively compiles `.vy` files below `source`, writes the
17
+ generated `.daml` files into that source tree, and runs `dpm build`. DPM is resolved
18
+ from `PATH`, then `~/.dpm/bin/dpm`, or can be supplied with `--dpm PATH`.
19
+
20
+ Use `forge daml --no-i` to fail on the first file error instead of continuing with
21
+ the remaining files. Use `--traceback` on any command for the Python traceback.
22
+
23
+ Stub generation accepts a DAR or a Daml project directory. It requires the optional
24
+ `damlforge[stubgen]` extra (for Daml-LF decoding), and `--module MODULE` may be repeated
25
+ to select modules from the main package or any dependency. Unsupported declarations
26
+ are skipped and reported.
27
+
28
+ For Daml tests that need coverage from data-dependency packages, run `daml test --all`;
29
+ the package-local test mode does not include those external definitions in its report.
30
+
31
+ ## 1. Container keywords
32
+
33
+ The pre-parser translates these container forms into Python `class` declarations:
34
+
35
+ | `.vy` keyword | Compiles to | Real Daml shape |
36
+ |---|---|---|
37
+ | `struct Foo:` | plain data record | `data Foo = Foo with ...` |
38
+ | `@template` then `class Foo:` | contract template | `template Foo where ...` |
39
+ | `interface Foo(view=V):` | interface | `interface Foo where viewtype V` |
40
+ | `@template` then `class Foo(Bar):` | template implementing interface `Bar` | `template Foo with ... where ... interface instance Bar for Foo where ...` |
41
+ | `flag Foo:` / `enum Foo:` | sum type of nullary constructors | `data Foo = A \| B \| ...` |
42
+ | `@variant` then `class Foo:` | sum type with payload constructors | `data Foo = A Type \| B with ...` |
43
+
44
+ `@template\nclass Foo:` is the only template spelling; bare `template Foo:` is not supported. Likewise, `@variant\nclass Foo:` is the only spelling for a payload variant. Neither class marker needs an import because the pre-parser consumes it before decorator-name analysis. No other decorator combination with bare `class` is legal - plain `class Foo:` and `@anything_else\nclass Foo:` both raise a hard `SyntaxException` at tokenize time.
45
+
46
+ `struct`/`interface`/`event`/`enum` (but not `template`/`flag`) are also reserved identifiers - you cannot name a variable or field `struct`, etc. There is no `instance` keyword - a template declares which interface(s) it implements directly via base classes, like real Python subclassing/ABCs (see §11).
47
+
48
+ `event`/`error` (`EventDef`/`ErrorDef`) parse but are not wired into codegen; the `exception` decorator explicitly raises `NotImplementedError` - none of these three are usable yet.
49
+
50
+ ## 2. Type system
51
+
52
+ **Native Python types - always available, no import:** `str`, `int`, `float`, `bool`, `None`, `list[T]`, `tuple[T, ...]`, `set[T]`, `frozenset[T]`. `Optional[T]` needs `from typing import Optional` for the file to remain valid-looking Python, but the compiler itself doesn't require the import.
53
+
54
+ **DamlForge builtin types - recognized unconditionally by the type checker, but conventionally still imported from `forge.models` for readability:** `Party`, `Decimal`, `Int` (a distinct `Int` for real Daml `Int`, vs. Python `int`), `ContractId[T]`, `GenMap[K, V]`, `TextMap[V]`.
55
+
56
+ ```python
57
+ from datetime import datetime
58
+
59
+ from forge.models import ContractId, Decimal, Optional, Party, TextMap, choice
60
+ ```
61
+
62
+ **Banned field types:** `dict[...]` and any unrecognized generic like `Map[...]` (`DF1213` - use `GenMap`/`TextMap`), and `bytes`/`bytearray`/`memoryview`/`complex`/`type`/`object`/`slice` (`DF1222` - no Daml equivalent).
63
+
64
+ **Type synonyms the checker treats as equal** when checking call-argument compatibility: `int`↔`Int`, `str`↔`Text`, `float`↔`Decimal`. A bare `X` is compatible where `Optional[X]` is expected (auto-wrapped, see §6). Generic args are checked recursively - `list[A]` is never compatible with `list[B]` unless `A`/`B` match.
65
+
66
+ **Your own types**: any `struct`/`template`/`interface`/`flag` declared in a reachable module is automatically a valid type name - no import needed within the same module, real `from X import Y` needed across `.vy` files.
67
+
68
+ Python's `datetime`, `date`, and `timedelta` map to Daml `Time`, `Date`, and
69
+ `RelTime`:
70
+
71
+ ```python
72
+ from datetime import date, datetime, time, timedelta, timezone
73
+ def current_time() -> datetime:
74
+ return datetime.now()
75
+
76
+ def epoch() -> date:
77
+ return date(1970, 1, 1)
78
+
79
+ def start_of_epoch() -> datetime:
80
+ return datetime.combine(epoch(), time())
81
+
82
+ def cooldown(months: int) -> timedelta:
83
+ return timedelta(days=30 * months, hours=12)
84
+
85
+ def deadline(start: datetime) -> datetime:
86
+ return start + timedelta(days=7)
87
+
88
+ def elapsed(later: datetime, earlier: datetime) -> timedelta:
89
+ return later - earlier
90
+
91
+ def from_seconds(seconds: int) -> datetime:
92
+ return datetime.fromtimestamp(seconds, timezone.utc)
93
+ ```
94
+
95
+ `datetime.now()` lowers to the Daml update operation `getTime`; DamlForge
96
+ automatically infers the enclosing function as an update. `date(...)` accepts
97
+ Python's integer month numbering (`1` through `12`) and automatically imports
98
+ `DA.Date`. `datetime.combine(date_value, time(...))` lowers to DAML's pure
99
+ `DA.Time.time`; a standalone `time(...)` has no DAML equivalent.
100
+
101
+ Adding a `timedelta` to a `datetime` uses normal Python arithmetic and lowers to
102
+ DAML `addRelTime`; subtracting two datetimes lowers to `subTime`.
103
+ `datetime.fromtimestamp(...)` requires an explicit `timezone.utc` and lowers
104
+ seconds to DAML's microsecond-based `fromUnixMicroseconds`.
105
+
106
+ The compiler supports Python's fixed units: `weeks`, `days`, `hours`, `minutes`,
107
+ `seconds`, `milliseconds`, and `microseconds`. Weeks lower to seven days. Python
108
+ does not support `years=` because a calendar year is not a fixed duration; use
109
+ explicit date/calendar logic when that distinction matters.
110
+
111
+ **Qualified module imports** - use when two real Daml packages export a same-named type (Daml itself would raise "Ambiguous occurrence" on an unqualified double-import):
112
+
113
+ ```python
114
+ import Splice.Api.FeaturedAppRightV1 as FeaturedAppRightV1
115
+ import Splice.Api.FeaturedAppRightV2 as FeaturedAppRightV2
116
+ ...
117
+ def f(x: FeaturedAppRightV1.FeaturedAppRight): ...
118
+ ```
119
+
120
+ `from X import Y as Z` (aliased *from*-import) is banned outright, as is `from X import *`, importing the same name twice, and importing a module/name that doesn't actually resolve - all raise `DF1213`.
121
+
122
+ ## 3. Decorators
123
+
124
+ Function and method decorators are ordinary Python objects and must be imported before use. An unimported decorator fails like any other unresolved name (`DF1219`, "not defined"). This includes the `@template` and `@variant` class markers, which are imported from `forge.models`.
125
+
126
+ ```python
127
+ from forge.models import choice, variant_record, view
128
+ from forge.builtins import DamlName
129
+ ```
130
+
131
+ | Decorator | Where legal | Rules |
132
+ |---|---|---|
133
+ | `@choice(controller=..., consuming=..., observer=...)` | method inside `template`/`interface` | `controller` required (`DF1203`); `consuming` required, must be a literal `True`/`False` or one of `"preconsuming"`/`"consuming"`/`"nonconsuming"`/`"postconsuming"` (`DF1203`); name can't start with `_` (`DF1218`); `"preconsuming"`/`"postconsuming"` banned on interface choice declarations, and on a template's implementation of an interface choice (`DF1208`) |
134
+ | `@view` | method inside `interface`, or a `template` that implements one | no args (`DF1206`); banned inside a `template` with no interface bases (`DF1207`) |
135
+ | `@variant_record` | constructor method inside an `@variant` class | bare only; emits a named-field Daml constructor using `with` instead of a positional payload |
136
+ | `@DamlName("RealName")` | any function/choice | exactly one string-literal positional arg (`DF1221`); overrides the auto-derived Daml-side name |
137
+ | `@template` | immediately before `class Foo:`, nothing else | class marker imported from `forge.models`; see §1 |
138
+ | `@variant` | immediately before `class Foo:`, nothing else | class marker imported from `forge.models`; see §1 and §9 |
139
+
140
+ ### `controller=`/`observer=` name rules (`DF1224`)
141
+
142
+ Every bare name inside a choice's `controller=`/`observer=` expression must be one of: that choice's own `with`-arguments, one of the template's own declared fields, or `self`. `self.<attr>` is further checked to be a real field (not `self.signatory` - `signatory` is a Daml typeclass function, not a stored field). This exists because Daml's own name resolution would otherwise silently pick an unrelated same-named field elsewhere in the module, or fail with a confusing `damlc`-time "Ambiguous occurrence" error. This check runs for `template` choices, including a template's implementation of an interface choice (since it lives directly in the template body and has real field access) - a bare `interface`'s own abstract choice declarations are skipped (they have no fields, no `self`, only their own with-arguments).
143
+
144
+ ```python
145
+ @choice(controller=owner, consuming=True) # owner: template field - OK
146
+ def transfer(self, new_owner: Party) -> bool: ...
147
+
148
+ @choice(controller=owner, consuming=True, observer=new_owner) # new_owner is `transfer`'s
149
+ def rename(self, label: str) -> bool: ... # arg, not `rename`'s - DF1224
150
+ ```
151
+
152
+ ## 4. Ledger primitives - must be imported
153
+
154
+ `fetch`, `exercise`, `create`, `archive`, `lookup_by_key`, `fetch_by_key`, `exercise_by_key`, `visible_by_key`, `lookup_n_by_key`, `lookup_all_by_key`, `view` (interface view extraction, distinct from the `@view` decorator), `from_interface_contract_id`, `to_interface_contract_id`, `to_interface`, `coerce_interface_contract_id`, `stakeholder`, `error`, `reverse` (every `@DamlName` function in `forge/builtins/daml_lang.py`) must be imported from `forge.builtins.daml_lang`. Calling one without importing it fails with `DF1219` ("not defined"). Only `len`/`range`/`ceil`/`floor` are import-free.
155
+
156
+ ```python
157
+ from forge.builtins.daml_lang import fetch
158
+
159
+ def f(cid: ContractId[Asset]) -> Asset:
160
+ return fetch(cid)
161
+ ```
162
+
163
+ Inside an `interface` body, a bare `view` in `controller=`/`observer=` (for example `controller=view.provider`) is the interface's own view value, bound by the compiler like `self`. It needs no import.
164
+
165
+ ### Ledger-effect inference
166
+
167
+ DamlForge automatically infers a plain function as an update when its body
168
+ calls an update operation such as `fetch`, `exercise`, `create`, `archive`, or
169
+ `fetch_by_key`. The inference is transitive, so a function that calls another
170
+ inferred update function is also emitted with an update return type:
171
+
172
+ ```python
173
+ def replace(new_owner: Party) -> bool:
174
+ archive(self)
175
+ ```
176
+
177
+ ```python
178
+ def move(new_owner: Party) -> bool:
179
+ replace(new_owner) # also inferred as an update
180
+ ```
181
+
182
+ Choice bodies are already update contexts and may call ledger operations
183
+ directly. Imported Daml update helpers and declaration-only stubs carry
184
+ compiler metadata so inference can recognize them even though their `.vy`
185
+ declarations have no body to inspect.
186
+
187
+ ## 5. Template fields
188
+
189
+ ```python
190
+ @template
191
+ class Asset:
192
+ owner: Party
193
+ asset_id: Text
194
+
195
+ signatory: list[Party] = [owner] # required (DF1201 if missing)
196
+ observer: list[Party] = [...] # optional
197
+ key: tuple[Party, Text] = (owner, asset_id) # optional, but...
198
+ maintainer: list[Party] = [owner] # ...requires key, and vice versa (DF1210/DF1211)
199
+ ensure: bool = amount > Decimal(0) # optional; must be bool-typed comparison/boolop/call
200
+ # (not bare arithmetic, not missing a value - DF1212)
201
+ ```
202
+
203
+ `signatory`/`observer`/`key`/`maintainer`/`ensure` are special clause names, not ordinary fields - don't reference them via `self.signatory` etc. in choice logic (the compiler flags this as `DF1224`).
204
+
205
+ ## 6. `Optional`, `Some`, auto-unwrapping
206
+
207
+ Never write `Some(...)` or `from_some(...)` by hand. Based on a field/return's declared `Optional[X]` type, the compiler automatically wraps a plain `X` value into `Some(X)` on assignment/return, and unwraps `Optional[X]` into `X` where a plain `X` is required. Just write the plain values:
208
+
209
+ ```python
210
+ lock: Optional[Lock] = None
211
+ ...
212
+ return HoldingView(..., lock=None, ...) # compiler emits `None`
213
+ return HoldingView(..., lock=existing_lock, ...) # if existing_lock: Lock, compiler emits `Some existing_lock`
214
+ ```
215
+
216
+ ## 7. Maps
217
+
218
+ ```python
219
+ from forge.models import GenMap, TextMap
220
+
221
+ balances: GenMap[Party, Decimal] = {alice: Decimal(0), bob: Decimal(0)}
222
+ values: TextMap[str] = {}
223
+
224
+ balances[alice] # lookup
225
+ balances[alice] = Decimal(5) # insert/update
226
+ alice in balances # membership
227
+ ```
228
+
229
+ `GenMap`/`TextMap` also expose `.insert(k, v)`, `.lookup(k)`, `.member(k)`, `.delete(k)`, `.keys()`, `.values()` if you prefer explicit method calls over subscript/`in` sugar.
230
+
231
+ ## 8. Flags (sum types)
232
+
233
+ ```python
234
+ flag PeriodPaymentStatus:
235
+ PERIOD_PENDING
236
+ PERIOD_PAID
237
+ ```
238
+
239
+ Members **must** be `SCREAMING_CASE` (`DF1217` on lowercase or mixed case). Access via `PeriodPaymentStatus.PERIOD_PAID`, compare with `==`/`!=`. Flags have no payload and no methods.
240
+
241
+ ## 9. Variants (payload sum types)
242
+
243
+ Use `@variant` when constructors carry values. Each method declares a
244
+ constructor and its parameters declare the payload:
245
+
246
+ ```python
247
+ from datetime import datetime
248
+
249
+ from forge.models import Party, variant_record
250
+
251
+ @variant
252
+ class Result:
253
+ def Accepted(value: Party): pass
254
+ def Cancelled(): pass
255
+
256
+ @variant_record
257
+ def Deferred(reason: str, retry_at: datetime): pass
258
+ ```
259
+
260
+ This generates:
261
+
262
+ ```daml
263
+ data Result
264
+ = Accepted Party
265
+ | Cancelled
266
+ | Deferred with
267
+ reason : Text
268
+ retry_at : Time
269
+ deriving (Eq, Show, Serializable)
270
+ ```
271
+
272
+ An ordinary constructor method is positional: its parameter names are not part
273
+ of the generated Daml API. Mark a constructor with `@variant_record` when the
274
+ original Daml shape uses named `with` fields and those field names must be
275
+ preserved. This distinction applies even to a single-field constructor. A
276
+ constructor with no parameters needs no `@variant_record`.
277
+
278
+ Constructor methods are declarations only and should have `pass` bodies.
279
+ `@variant` and `@variant_record` must both be imported from
280
+ `forge.models`.
281
+
282
+ ## 10. Structs
283
+
284
+ Plain data records - fields only:
285
+
286
+ ```python
287
+ struct InstrumentId:
288
+ admin: Party
289
+ id: str
290
+ ```
291
+
292
+ **No methods.** A `def` inside a `struct` body is currently silently dropped (no error raised) - this mirrors a real gap relative to Vyper, which explicitly rejects struct methods with `StructureException`. Treat "structs can't have methods" as a hard rule and use a free top-level `def` instead:
293
+
294
+ ```python
295
+ def update_milestone_if_due(paid_amount: Decimal, milestone: RepaymentMilestone) -> RepaymentMilestone:
296
+ if milestone.paid or paid_amount < milestone.amount:
297
+ return milestone
298
+ return RepaymentMilestone(due_date=milestone.due_date, amount=milestone.amount,
299
+ paid=True, paid_date=milestone.paid_date)
300
+ ```
301
+
302
+ ## 11. Interfaces - a template implements one via real subclassing
303
+
304
+ There is no `instance` keyword. A `template` declares it implements an `interface` the same way Python declares a class implements an ABC - by listing it as a base:
305
+
306
+ ```python
307
+ struct HoldingView:
308
+ owner: Party
309
+
310
+ interface Holding(view=HoldingView):
311
+ @choice(controller=actors, consuming="nonconsuming")
312
+ def withdraw(self, actors: list[Party], extra_args: ExtraArgs) -> bool:
313
+ pass # interface choices are declared once, with `pass` bodies
314
+
315
+ @template
316
+ class SimpleHolding(Holding):
317
+ owner: Party
318
+ issuer: Party
319
+ signatory: list[Party] = [owner, issuer]
320
+
321
+ @view
322
+ def get_view(self) -> HoldingView:
323
+ return HoldingView(owner=self.owner)
324
+
325
+ @choice(controller=actors, consuming="nonconsuming")
326
+ def withdraw(self, actors: list[Party], extra_args: ExtraArgs) -> bool:
327
+ ... # real implementation - same field/self access as any other choice
328
+ ```
329
+
330
+ Any method inside the template whose name matches one of the interface's own `@choice`-declared names is treated as that interface's implementation (not a separate template choice); everything else stays a normal template choice. A template can implement more than one interface (`@template` followed by `class Foo(A, B):`) - a `@view` method is matched to the right interface by its return type, so implementing two interfaces needs two `@view` methods, one per interface's declared `view=` type.
331
+
332
+ **Compile-time completeness check (`DF1228`)**: a template that lists an interface as a base must implement every one of that interface's `@choice`-declared members by name, and have exactly one `@view` method whose return type matches the interface's `view=` type - both are checked before codegen, not left to fail later inside `damlc`. The base itself must resolve to a real `interface` declaration (`DF1227` otherwise).
333
+
334
+ Under the hood, this compiles to Daml's real interface-choice-delegation mechanism: the `interface` emits the choice once plus an abstract "impl" method signature, and each implementing `template`'s `interface instance ... for ... where` block provides just that method's body - matching how real Daml (and the Splice token standard) actually structures this, not a per-template redeclared choice.
335
+
336
+ If you build interface+implementation in the same `.vy` module (the common case for a self-contained example), add `-Wno-upgrade-interfaces` to your project's `daml.yaml` `build-options` - real Daml warns-as-error about interfaces and implementations sharing a package, since it affects upgradability; this is a project-level Daml build setting, not something `.vy` can express.
337
+
338
+ ## 12. Functions, loops, calls
339
+
340
+ Free top-level functions are plain `def`s; call-argument arity (`DF1225`) and type-compatibility (`DF1226`, only for `Name` arguments with a known declared type) are checked for any call to a known top-level `.vy` function.
341
+
342
+ Direct self-recursion is banned (`DF1209`) - a function/choice cannot call itself.
343
+
344
+ For-loops may include a type annotation on the loop variable before `in` (this is `.vy`-specific sugar the pre-parser slurps out, since bare PEP-526 annotations aren't legal there in real Python). The annotation is optional when the iterable type is known:
345
+
346
+ ```python
347
+ for milestone: RepaymentMilestone in milestones:
348
+ ...
349
+ for _index: int in range(0, count):
350
+ ...
351
+ ```
352
+
353
+ `len`, `range`, `ceil`, `floor` are always-available builtins (no import) and rename on the Daml side (`len`→`length`, `ceil`→`ceiling`; `floor`/`range` pass through).
354
+
355
+ ## 13. Error code index
356
+
357
+ | Code | Meaning |
358
+ |---|---|
359
+ | DF1201 | template missing `signatory` |
360
+ | DF1203 | `@choice` missing `controller` or missing/invalid `consuming` |
361
+ | DF1206 | `@view` given arguments |
362
+ | DF1207 | `@view` used inside a `template` with no interface base |
363
+ | DF1208 | `"preconsuming"`/`"postconsuming"` on an interface choice declaration or implementation |
364
+ | DF1209 | direct self-recursion |
365
+ | DF1210 | `key` without `maintainer` |
366
+ | DF1211 | `maintainer` without `key` |
367
+ | DF1212 | `ensure` missing a value, or not a bool-typed comparison/boolop/call |
368
+ | DF1213 | import errors (wildcard, aliased from-import, duplicate, unresolvable) or a banned field type (`dict`, unknown map) |
369
+ | DF1216 | unknown flag member accessed |
370
+ | DF1217 | flag member not `SCREAMING_CASE` |
371
+ | DF1218 | choice name starts with `_` |
372
+ | DF1219 | name not defined / not in scope |
373
+ | DF1220 | unknown/unrecognized decorator |
374
+ | DF1221 | `@DamlName` given the wrong argument shape |
375
+ | DF1222 | field type with no Daml equivalent (`bytes`, `complex`, ...) |
376
+ | DF1224 | `controller=`/`observer=` references a name that isn't a with-arg/field/`self` |
377
+ | DF1225 | wrong argument count on a known function call |
378
+ | DF1226 | argument type incompatible with a known function's declared parameter type |
379
+ | DF1227 | a `template`'s interface base isn't a plain name, or doesn't resolve to a known `interface` |
380
+ | DF1228 | a `template` implementing an interface is missing a required choice or `@view` implementation |
381
+
382
+ ## 14. Worked example
383
+
384
+ ```python
385
+ from datetime import datetime
386
+
387
+ from forge.models import ContractId, Decimal, Optional, Party, TextMap, choice, view
388
+ from forge.builtins.daml_lang import archive, create
389
+
390
+ struct InstrumentId:
391
+ admin: Party
392
+ id: str
393
+
394
+ struct Metadata:
395
+ values: TextMap[str]
396
+
397
+ struct HoldingView:
398
+ owner: Party
399
+ instrument_id: InstrumentId
400
+ amount: Decimal
401
+ meta: Metadata
402
+
403
+ interface Holding(view=HoldingView):
404
+ pass
405
+
406
+ @template
407
+ class SimpleHolding(Holding):
408
+ owner: Party
409
+ issuer: Party
410
+ amount: Decimal
411
+ instrument_id: InstrumentId
412
+
413
+ signatory: list[Party] = [owner, issuer]
414
+
415
+ @view
416
+ def get_view(self) -> HoldingView:
417
+ return HoldingView(
418
+ owner=self.owner,
419
+ instrument_id=self.instrument_id,
420
+ amount=self.amount,
421
+ meta=Metadata(values={}),
422
+ )
423
+
424
+ @template
425
+ class PendingTransfer:
426
+ sender: Party
427
+ receiver: Party
428
+ amount: Decimal
429
+ instrument_id: InstrumentId
430
+
431
+ signatory: list[Party] = [sender]
432
+ observer: list[Party] = [receiver]
433
+
434
+ @choice(controller=receiver, consuming=True)
435
+ def accept(self) -> ContractId[SimpleHolding]:
436
+ assert self.amount > Decimal(0), "transfer amount must be positive"
437
+ return create(SimpleHolding(
438
+ owner=self.receiver,
439
+ issuer=self.sender,
440
+ amount=self.amount,
441
+ instrument_id=self.instrument_id,
442
+ ))
443
+ ```
444
+
445
+ Full source: `examples/token_standard/token_standard.vy` (verified against real `dpm build`). `examples/crowd_loans/` is the largest real example, exercising `flag`, `GenMap`, nested `for` loops, and cross-package Splice imports.
@@ -0,0 +1,50 @@
1
+ name: Build wheel on tag
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - 'v*.*.*'
7
+
8
+ permissions:
9
+ contents: write
10
+
11
+ jobs:
12
+ build:
13
+ runs-on: ubuntu-latest
14
+ steps:
15
+ - uses: actions/checkout@v4
16
+ with:
17
+ fetch-depth: 0
18
+ fetch-tags: true
19
+
20
+ - uses: actions/setup-python@v5
21
+ with:
22
+ python-version: '3.12'
23
+
24
+ - name: Install build tooling
25
+ run: python -m pip install --upgrade pip build twine
26
+
27
+ - name: Build sdist and wheel
28
+ run: python -m build
29
+
30
+ - name: Verify package metadata
31
+ run: twine check dist/*
32
+
33
+ - name: Upload build artifact
34
+ uses: actions/upload-artifact@v4
35
+ with:
36
+ name: forge-${{ github.ref_name }}
37
+ path: dist/*
38
+ retention-days: 90
39
+
40
+ - name: Attach wheel to GitHub Release
41
+ env:
42
+ GH_TOKEN: ${{ github.token }}
43
+ run: |
44
+ gh release create "${{ github.ref_name }}" dist/* \
45
+ --repo "${{ github.repository }}" \
46
+ --title "${{ github.ref_name }}" \
47
+ --generate-notes \
48
+ || gh release upload "${{ github.ref_name }}" dist/* \
49
+ --repo "${{ github.repository }}" \
50
+ --clobber
@@ -0,0 +1,19 @@
1
+ name: License header
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - main
7
+ pull_request:
8
+
9
+ permissions:
10
+ contents: read
11
+
12
+ jobs:
13
+ license-check:
14
+ runs-on: ubuntu-latest
15
+ steps:
16
+ - uses: actions/checkout@v4
17
+
18
+ - name: Check Apache-2.0 license headers
19
+ run: make license-check
@@ -0,0 +1,66 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ workflow_dispatch:
5
+ inputs:
6
+ version:
7
+ description: 'Version to publish, for example 0.1.0'
8
+ required: true
9
+ type: string
10
+
11
+ permissions:
12
+ contents: read
13
+
14
+ jobs:
15
+ build:
16
+ runs-on: ubuntu-latest
17
+ steps:
18
+ - name: Validate version
19
+ env:
20
+ VERSION: ${{ inputs.version }}
21
+ run: |
22
+ if ! echo "$VERSION" | grep -Eq '^[0-9]+\.[0-9]+\.[0-9]+((a|b|rc)[0-9]+|\.post[0-9]+|\.dev[0-9]+)?$'; then
23
+ echo "Invalid PEP 440 version: $VERSION"
24
+ exit 1
25
+ fi
26
+
27
+ - uses: actions/checkout@v4
28
+ with:
29
+ fetch-depth: 0
30
+
31
+ - uses: actions/setup-python@v5
32
+ with:
33
+ python-version: '3.12'
34
+
35
+ - name: Install build tooling
36
+ run: python -m pip install --upgrade pip build twine
37
+
38
+ - name: Build sdist and wheel
39
+ env:
40
+ SETUPTOOLS_SCM_PRETEND_VERSION: ${{ inputs.version }}
41
+ run: python -m build
42
+
43
+ - name: Verify package metadata
44
+ run: twine check --strict dist/*
45
+
46
+ - uses: actions/upload-artifact@v4
47
+ with:
48
+ name: damlforge-${{ inputs.version }}
49
+ path: dist/*
50
+
51
+ publish:
52
+ needs: build
53
+ runs-on: ubuntu-latest
54
+ environment:
55
+ name: pypi
56
+ url: https://pypi.org/project/damlforge/${{ inputs.version }}/
57
+ permissions:
58
+ id-token: write
59
+ steps:
60
+ - uses: actions/download-artifact@v4
61
+ with:
62
+ name: damlforge-${{ inputs.version }}
63
+ path: dist/
64
+
65
+ - name: Publish to PyPI
66
+ uses: pypa/gh-action-pypi-publish@release/v1