codeplain 0.2.2__tar.gz → 0.2.4__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 (195) hide show
  1. codeplain-0.2.4/.flake8 +28 -0
  2. codeplain-0.2.4/.github/workflows/lint-and-test.yml +126 -0
  3. codeplain-0.2.4/.github/workflows/nofity-slack-on-main-merge.yml +22 -0
  4. codeplain-0.2.4/.github/workflows/publish-install-script.yml +30 -0
  5. codeplain-0.2.4/.github/workflows/publish-to-pypi.yml +109 -0
  6. codeplain-0.2.4/.gitignore +32 -0
  7. codeplain-0.2.4/.vscode/launch.json +21 -0
  8. codeplain-0.2.4/.vscode/settings.json +32 -0
  9. {codeplain-0.2.2 → codeplain-0.2.4}/PKG-INFO +15 -16
  10. {codeplain-0.2.2 → codeplain-0.2.4}/codeplain_REST_api.py +0 -6
  11. codeplain-0.2.4/docs/generate_cli.py +20 -0
  12. codeplain-0.2.4/docs/plain2code_cli.md +66 -0
  13. codeplain-0.2.4/docs/plain_language_specification.md +250 -0
  14. codeplain-0.2.4/docs/starting_a_plain_project_from_scratch.md +94 -0
  15. codeplain-0.2.4/examples/example_hello_world_golang/config.yaml +3 -0
  16. codeplain-0.2.4/examples/example_hello_world_golang/harness_tests/hello_world_test.go +30 -0
  17. codeplain-0.2.4/examples/example_hello_world_golang/hello_world_golang.plain +13 -0
  18. codeplain-0.2.4/examples/example_hello_world_golang/run.sh +35 -0
  19. codeplain-0.2.4/examples/example_hello_world_python/config.yaml +3 -0
  20. codeplain-0.2.4/examples/example_hello_world_python/harness_tests/hello_world_display/test_hello_world.py +17 -0
  21. codeplain-0.2.4/examples/example_hello_world_python/hello_world_python.plain +19 -0
  22. codeplain-0.2.4/examples/example_hello_world_python/run.sh +20 -0
  23. codeplain-0.2.4/examples/example_hello_world_react/harness_tests/hello_world_display/cypress/e2e/hello_world.cy.ts +6 -0
  24. codeplain-0.2.4/examples/example_hello_world_react/harness_tests/hello_world_display/cypress/support/e2e.ts +8 -0
  25. codeplain-0.2.4/examples/example_hello_world_react/harness_tests/hello_world_display/cypress.config.ts +12 -0
  26. codeplain-0.2.4/examples/example_hello_world_react/harness_tests/hello_world_display/package.json +44 -0
  27. codeplain-0.2.4/examples/example_hello_world_react/harness_tests/hello_world_display/tsconfig.json +10 -0
  28. codeplain-0.2.4/examples/example_hello_world_react/hello_world_react.plain +11 -0
  29. codeplain-0.2.4/examples/example_hello_world_react/run.sh +29 -0
  30. codeplain-0.2.4/examples/run.sh +39 -0
  31. {codeplain-0.2.2 → codeplain-0.2.4}/git_utils.py +1 -6
  32. codeplain-0.2.4/install.sh +136 -0
  33. {codeplain-0.2.2 → codeplain-0.2.4}/plain2code.py +5 -12
  34. {codeplain-0.2.2 → codeplain-0.2.4}/plain2code_exceptions.py +16 -6
  35. {codeplain-0.2.2 → codeplain-0.2.4}/plain_file.py +14 -36
  36. {codeplain-0.2.2 → codeplain-0.2.4}/plain_modules.py +1 -4
  37. {codeplain-0.2.2 → codeplain-0.2.4}/plain_spec.py +2 -4
  38. {codeplain-0.2.2 → codeplain-0.2.4}/pyproject.toml +14 -53
  39. codeplain-0.2.4/pytest.ini +7 -0
  40. codeplain-0.2.2/codeplain.egg-info/requires.txt → codeplain-0.2.4/requirements.txt +7 -6
  41. codeplain-0.2.4/resources/codeplain_overview.png +0 -0
  42. codeplain-0.2.4/resources/plain_example.png +0 -0
  43. codeplain-0.2.4/test_scripts/run_conformance_tests_cypress.sh +255 -0
  44. codeplain-0.2.4/test_scripts/run_conformance_tests_golang.sh +87 -0
  45. codeplain-0.2.4/test_scripts/run_conformance_tests_python.sh +79 -0
  46. codeplain-0.2.4/test_scripts/run_unittests_golang.sh +49 -0
  47. codeplain-0.2.4/test_scripts/run_unittests_python.sh +73 -0
  48. codeplain-0.2.4/test_scripts/run_unittests_react.sh +66 -0
  49. codeplain-0.2.4/tests/__init__.py +1 -0
  50. codeplain-0.2.4/tests/conftest.py +34 -0
  51. codeplain-0.2.4/tests/data/imports/circular_imports_1.plain +8 -0
  52. codeplain-0.2.4/tests/data/imports/circular_imports_2.plain +8 -0
  53. codeplain-0.2.4/tests/data/imports/circular_imports_main.plain +12 -0
  54. codeplain-0.2.4/tests/data/imports/diamond_import_1.plain +16 -0
  55. codeplain-0.2.4/tests/data/imports/diamond_import_2.plain +16 -0
  56. codeplain-0.2.4/tests/data/imports/diamond_import_common.plain +11 -0
  57. codeplain-0.2.4/tests/data/imports/diamond_imports_main.plain +13 -0
  58. codeplain-0.2.4/tests/data/imports/non_existent_import.plain +12 -0
  59. codeplain-0.2.4/tests/data/plainfile/duplicate_specification_heading.plain +7 -0
  60. codeplain-0.2.4/tests/data/plainfile/invalid_specification_order.plain +7 -0
  61. codeplain-0.2.4/tests/data/plainfile/missing_non_functional_requirements.plain +5 -0
  62. codeplain-0.2.4/tests/data/plainfile/plain_source_with_absolute_link.plain +9 -0
  63. codeplain-0.2.4/tests/data/plainfile/plain_source_with_url_link.plain +9 -0
  64. codeplain-0.2.4/tests/data/plainfile/task_manager_with_reference_links.plain +40 -0
  65. codeplain-0.2.4/tests/data/plainfile/without_non_functional_requirement.plain +5 -0
  66. codeplain-0.2.4/tests/data/plainfileparser/concept_validation_acceptance_tests.plain +20 -0
  67. codeplain-0.2.4/tests/data/plainfileparser/concept_validation_acceptance_tests_nondefined.plain +20 -0
  68. codeplain-0.2.4/tests/data/plainfileparser/concept_validation_defined_nondefined.plain +18 -0
  69. codeplain-0.2.4/tests/data/plainfileparser/concept_validation_defined_nondefined_2.plain +18 -0
  70. codeplain-0.2.4/tests/data/plainfileparser/concept_validation_definition.plain +16 -0
  71. codeplain-0.2.4/tests/data/plainfileparser/concept_validation_noconcepts.plain +18 -0
  72. codeplain-0.2.4/tests/data/plainfileparser/concept_validation_nonconcept.plain +15 -0
  73. codeplain-0.2.4/tests/data/plainfileparser/concept_validation_nondefined.plain +18 -0
  74. codeplain-0.2.4/tests/data/plainfileparser/concept_validation_redefinition.plain +19 -0
  75. codeplain-0.2.4/tests/data/plainfileparser/concept_validation_several_concepts.plain +13 -0
  76. codeplain-0.2.4/tests/data/plainfileparser/concept_validation_valid.plain +16 -0
  77. codeplain-0.2.4/tests/data/plainfileparser/exported_concepts.plain +13 -0
  78. codeplain-0.2.4/tests/data/plainfileparser/exported_concepts_base.plain +2 -0
  79. codeplain-0.2.4/tests/data/plainfileparser/exported_concepts_example.plain +13 -0
  80. codeplain-0.2.4/tests/data/plainfileparser/exported_concepts_missing.plain +8 -0
  81. codeplain-0.2.4/tests/data/plainfileparser/exported_concepts_missing_example.plain +13 -0
  82. codeplain-0.2.4/tests/data/plainfileparser/exported_concepts_nested.plain +15 -0
  83. codeplain-0.2.4/tests/data/plainfileparser/exported_concepts_nested_example.plain +13 -0
  84. codeplain-0.2.4/tests/data/plainfileparser/exported_concepts_transitive_example.plain +13 -0
  85. codeplain-0.2.4/tests/data/plainfileparser/exported_concepts_transitive_l1.plain +13 -0
  86. codeplain-0.2.4/tests/data/plainfileparser/exported_concepts_transitive_l2.plain +13 -0
  87. codeplain-0.2.4/tests/data/plainfileparser/plain_file_parser_with_comments.plain +8 -0
  88. codeplain-0.2.4/tests/data/plainfileparser/plain_file_with_comments_indented.plain +10 -0
  89. codeplain-0.2.4/tests/data/plainfileparser/regular_plain_source.plain +11 -0
  90. codeplain-0.2.4/tests/data/plainfileparser/required_concepts.plain +7 -0
  91. codeplain-0.2.4/tests/data/plainfileparser/required_concepts_defs.plain +2 -0
  92. codeplain-0.2.4/tests/data/plainfileparser/required_concepts_example.plain +13 -0
  93. codeplain-0.2.4/tests/data/plainfileparser/required_concepts_l1.plain +7 -0
  94. codeplain-0.2.4/tests/data/plainfileparser/required_concepts_l2.plain +5 -0
  95. codeplain-0.2.4/tests/data/plainfileparser/required_concepts_missing.plain +10 -0
  96. codeplain-0.2.4/tests/data/plainfileparser/required_concepts_module.plain +11 -0
  97. codeplain-0.2.4/tests/data/plainfileparser/required_concepts_partial.plain +13 -0
  98. codeplain-0.2.4/tests/data/plainfileparser/required_concepts_partial_duplicate.plain +14 -0
  99. codeplain-0.2.4/tests/data/plainfileparser/topological_sort.plain +14 -0
  100. codeplain-0.2.4/tests/data/plainfileparser/topological_sort_not_referenced.plain +22 -0
  101. codeplain-0.2.4/tests/data/requires/circular_requires_main.plain +18 -0
  102. codeplain-0.2.4/tests/data/requires/circular_requires_sub.plain +12 -0
  103. codeplain-0.2.4/tests/data/requires/diamond_requires_1.plain +12 -0
  104. codeplain-0.2.4/tests/data/requires/diamond_requires_2.plain +12 -0
  105. codeplain-0.2.4/tests/data/requires/diamond_requires_common.plain +7 -0
  106. codeplain-0.2.4/tests/data/requires/diamond_requires_main.plain +19 -0
  107. codeplain-0.2.4/tests/data/requires/independent_requires_1.plain +7 -0
  108. codeplain-0.2.4/tests/data/requires/independent_requires_2.plain +7 -0
  109. codeplain-0.2.4/tests/data/requires/independent_requires_main.plain +19 -0
  110. codeplain-0.2.4/tests/data/requires/non_existent_require.plain +18 -0
  111. codeplain-0.2.4/tests/data/requires/normal_requires_1.plain +12 -0
  112. codeplain-0.2.4/tests/data/requires/normal_requires_2.plain +12 -0
  113. codeplain-0.2.4/tests/data/requires/normal_requires_common.plain +7 -0
  114. codeplain-0.2.4/tests/data/requires/normal_requires_main.plain +19 -0
  115. codeplain-0.2.4/tests/data/simple.plain +7 -0
  116. codeplain-0.2.4/tests/data/templates/block_level_include.plain +12 -0
  117. codeplain-0.2.4/tests/data/templates/code_variables.plain +10 -0
  118. codeplain-0.2.4/tests/data/templates/header.plain +7 -0
  119. codeplain-0.2.4/tests/data/templates/implement.plain +3 -0
  120. codeplain-0.2.4/tests/data/templates/implement_2.plain +3 -0
  121. codeplain-0.2.4/tests/data/templates/template_include.plain +4 -0
  122. codeplain-0.2.4/tests/data/templates/test_hardest_problem.plain +2 -0
  123. {codeplain-0.2.2 → codeplain-0.2.4}/tests/test_plainfile.py +1 -1
  124. {codeplain-0.2.2 → codeplain-0.2.4}/tests/test_requires.py +2 -1
  125. codeplain-0.2.2/codeplain.egg-info/PKG-INFO +0 -123
  126. codeplain-0.2.2/codeplain.egg-info/SOURCES.txt +0 -81
  127. codeplain-0.2.2/codeplain.egg-info/dependency_links.txt +0 -1
  128. codeplain-0.2.2/codeplain.egg-info/entry_points.txt +0 -2
  129. codeplain-0.2.2/codeplain.egg-info/top_level.txt +0 -41
  130. codeplain-0.2.2/setup.cfg +0 -4
  131. {codeplain-0.2.2 → codeplain-0.2.4}/LICENSE +0 -0
  132. {codeplain-0.2.2 → codeplain-0.2.4}/README.md +0 -0
  133. {codeplain-0.2.2 → codeplain-0.2.4}/concept_utils.py +0 -0
  134. {codeplain-0.2.2 → codeplain-0.2.4}/config/__init__.py +0 -0
  135. {codeplain-0.2.2 → codeplain-0.2.4}/config/system_config.yaml +0 -0
  136. {codeplain-0.2.2 → codeplain-0.2.4}/diff_utils.py +0 -0
  137. {codeplain-0.2.2 → codeplain-0.2.4}/event_bus.py +0 -0
  138. {codeplain-0.2.2 → codeplain-0.2.4}/file_utils.py +0 -0
  139. {codeplain-0.2.2 → codeplain-0.2.4}/hash_key.py +0 -0
  140. {codeplain-0.2.2 → codeplain-0.2.4}/memory_management.py +0 -0
  141. {codeplain-0.2.2 → codeplain-0.2.4}/module_renderer.py +0 -0
  142. {codeplain-0.2.2 → codeplain-0.2.4}/plain2code_arguments.py +0 -0
  143. {codeplain-0.2.2 → codeplain-0.2.4}/plain2code_console.py +0 -0
  144. {codeplain-0.2.2 → codeplain-0.2.4}/plain2code_events.py +0 -0
  145. {codeplain-0.2.2 → codeplain-0.2.4}/plain2code_logger.py +0 -0
  146. {codeplain-0.2.2 → codeplain-0.2.4}/plain2code_nodes.py +0 -0
  147. {codeplain-0.2.2 → codeplain-0.2.4}/plain2code_read_config.py +0 -0
  148. {codeplain-0.2.2 → codeplain-0.2.4}/plain2code_state.py +0 -0
  149. {codeplain-0.2.2 → codeplain-0.2.4}/plain2code_utils.py +0 -0
  150. {codeplain-0.2.2 → codeplain-0.2.4}/render_machine/__init__.py +0 -0
  151. {codeplain-0.2.2 → codeplain-0.2.4}/render_machine/actions/analyze_specification_ambiguity.py +0 -0
  152. {codeplain-0.2.2 → codeplain-0.2.4}/render_machine/actions/base_action.py +0 -0
  153. {codeplain-0.2.2 → codeplain-0.2.4}/render_machine/actions/commit_conformance_tests_changes.py +0 -0
  154. {codeplain-0.2.2 → codeplain-0.2.4}/render_machine/actions/commit_implementation_code_changes.py +0 -0
  155. {codeplain-0.2.2 → codeplain-0.2.4}/render_machine/actions/create_dist.py +0 -0
  156. {codeplain-0.2.2 → codeplain-0.2.4}/render_machine/actions/exit_with_error.py +0 -0
  157. {codeplain-0.2.2 → codeplain-0.2.4}/render_machine/actions/finish_functional_requirement.py +0 -0
  158. {codeplain-0.2.2 → codeplain-0.2.4}/render_machine/actions/fix_conformance_test.py +0 -0
  159. {codeplain-0.2.2 → codeplain-0.2.4}/render_machine/actions/fix_unit_tests.py +0 -0
  160. {codeplain-0.2.2 → codeplain-0.2.4}/render_machine/actions/prepare_repositories.py +0 -0
  161. {codeplain-0.2.2 → codeplain-0.2.4}/render_machine/actions/prepare_testing_environment.py +0 -0
  162. {codeplain-0.2.2 → codeplain-0.2.4}/render_machine/actions/refactor_code.py +0 -0
  163. {codeplain-0.2.2 → codeplain-0.2.4}/render_machine/actions/render_conformance_tests.py +0 -0
  164. {codeplain-0.2.2 → codeplain-0.2.4}/render_machine/actions/render_functional_requirement.py +0 -0
  165. {codeplain-0.2.2 → codeplain-0.2.4}/render_machine/actions/run_conformance_tests.py +0 -0
  166. {codeplain-0.2.2 → codeplain-0.2.4}/render_machine/actions/run_unit_tests.py +0 -0
  167. {codeplain-0.2.2 → codeplain-0.2.4}/render_machine/actions/summarize_conformance_tests.py +0 -0
  168. {codeplain-0.2.2 → codeplain-0.2.4}/render_machine/code_renderer.py +0 -0
  169. {codeplain-0.2.2 → codeplain-0.2.4}/render_machine/conformance_test_helpers.py +0 -0
  170. {codeplain-0.2.2 → codeplain-0.2.4}/render_machine/conformance_tests.py +0 -0
  171. {codeplain-0.2.2 → codeplain-0.2.4}/render_machine/implementation_code_helpers.py +0 -0
  172. {codeplain-0.2.2 → codeplain-0.2.4}/render_machine/render_context.py +0 -0
  173. {codeplain-0.2.2 → codeplain-0.2.4}/render_machine/render_types.py +0 -0
  174. {codeplain-0.2.2 → codeplain-0.2.4}/render_machine/render_utils.py +0 -0
  175. {codeplain-0.2.2 → codeplain-0.2.4}/render_machine/state_machine_config.py +0 -0
  176. {codeplain-0.2.2 → codeplain-0.2.4}/render_machine/states.py +0 -0
  177. {codeplain-0.2.2 → codeplain-0.2.4}/render_machine/triggers.py +0 -0
  178. {codeplain-0.2.2 → codeplain-0.2.4}/spinner.py +0 -0
  179. {codeplain-0.2.2 → codeplain-0.2.4}/standard_template_library/__init__.py +0 -0
  180. {codeplain-0.2.2 → codeplain-0.2.4}/standard_template_library/golang-console-app-template.plain +0 -0
  181. {codeplain-0.2.2 → codeplain-0.2.4}/standard_template_library/python-console-app-template.plain +0 -0
  182. {codeplain-0.2.2 → codeplain-0.2.4}/standard_template_library/typescript-react-app-boilerplate.plain +0 -0
  183. {codeplain-0.2.2 → codeplain-0.2.4}/standard_template_library/typescript-react-app-template.plain +0 -0
  184. {codeplain-0.2.2 → codeplain-0.2.4}/system_config.py +0 -0
  185. {codeplain-0.2.2 → codeplain-0.2.4}/tests/test_git_utils.py +0 -0
  186. {codeplain-0.2.2 → codeplain-0.2.4}/tests/test_imports.py +0 -0
  187. {codeplain-0.2.2 → codeplain-0.2.4}/tests/test_plainfileparser.py +0 -0
  188. {codeplain-0.2.2 → codeplain-0.2.4}/tests/test_plainspec.py +0 -0
  189. {codeplain-0.2.2 → codeplain-0.2.4}/tui/__init__.py +0 -0
  190. {codeplain-0.2.2 → codeplain-0.2.4}/tui/components.py +0 -0
  191. {codeplain-0.2.2 → codeplain-0.2.4}/tui/models.py +0 -0
  192. {codeplain-0.2.2 → codeplain-0.2.4}/tui/plain2code_tui.py +0 -0
  193. {codeplain-0.2.2 → codeplain-0.2.4}/tui/state_handlers.py +0 -0
  194. {codeplain-0.2.2 → codeplain-0.2.4}/tui/styles.css +0 -0
  195. {codeplain-0.2.2 → codeplain-0.2.4}/tui/widget_helpers.py +0 -0
@@ -0,0 +1,28 @@
1
+ [flake8]
2
+ max-line-length = 120
3
+ # E203 is ignored because it conflicts with Black's formatting of slice notation
4
+ # Black formats slices like `a[1 : 2]` but flake8 expects `a[1:2]`
5
+ # E501 is ignored because we handle line length with Black's formatter
6
+ # B001 is ignored because we also check it with check E722
7
+ # N... is ignored because it's just naming conventions
8
+ # U101 is ignored because leading underscores signal that the argument is not used
9
+ extend-ignore = E203, E501, B001, N803, N806, N813, U101, U101
10
+ exclude =
11
+ .git,
12
+ __pycache__,
13
+ .venv,
14
+ .env,
15
+ .conda,
16
+ build,
17
+ dist,
18
+ tests,
19
+ examples
20
+ per-file-ignores =
21
+ __init__.py: F401
22
+ tests/*: U100
23
+ max-complexity = 15
24
+ enable-extensions = U100
25
+ # Plugin-specific configuration
26
+ unused-arguments-ignore-args = self,cls,_
27
+ # don't show warnings for unused *args and **kwargs.
28
+ unused-arguments-ignore-variadic-names = True
@@ -0,0 +1,126 @@
1
+ name: Code Quality & Tests
2
+
3
+ on:
4
+ push:
5
+ pull_request:
6
+
7
+ env:
8
+ PYTHON_VERSION: "3.11"
9
+
10
+ jobs:
11
+ black:
12
+ name: Black Formatting
13
+ runs-on: ubuntu-latest
14
+ steps:
15
+ - uses: actions/checkout@v4
16
+ - name: Set up Python
17
+ uses: actions/setup-python@v5
18
+ with:
19
+ python-version: ${{ env.PYTHON_VERSION }}
20
+ - name: Cache pip
21
+ uses: actions/cache@v4
22
+ with:
23
+ path: ~/.cache/pip
24
+ key: ${{ runner.os }}-pip-${{ hashFiles('requirements.txt') }}
25
+ - name: Install dependencies
26
+ run: |
27
+ python -m pip install --upgrade pip
28
+ pip install -r requirements.txt
29
+ - name: Check formatting with Black
30
+ run: black . --check
31
+
32
+ isort:
33
+ name: Import Sorting
34
+ runs-on: ubuntu-latest
35
+ steps:
36
+ - uses: actions/checkout@v4
37
+ - name: Set up Python
38
+ uses: actions/setup-python@v5
39
+ with:
40
+ python-version: ${{ env.PYTHON_VERSION }}
41
+ - name: Cache pip
42
+ uses: actions/cache@v4
43
+ with:
44
+ path: ~/.cache/pip
45
+ key: ${{ runner.os }}-pip-${{ hashFiles('requirements.txt') }}
46
+ - name: Install dependencies
47
+ run: |
48
+ python -m pip install --upgrade pip
49
+ pip install isort
50
+ - name: Sort imports with isort
51
+ run: isort . --check-only --diff
52
+
53
+ flake8:
54
+ name: Flake8 Linting
55
+ runs-on: ubuntu-latest
56
+ steps:
57
+ - uses: actions/checkout@v4
58
+ - name: Set up Python
59
+ uses: actions/setup-python@v5
60
+ with:
61
+ python-version: ${{ env.PYTHON_VERSION }}
62
+ - name: Cache pip
63
+ uses: actions/cache@v4
64
+ with:
65
+ path: ~/.cache/pip
66
+ key: ${{ runner.os }}-pip-${{ hashFiles('requirements.txt') }}
67
+ - name: Install dependencies
68
+ run: |
69
+ python -m pip install --upgrade pip
70
+ pip install flake8
71
+ - name: Lint with flake8
72
+ run: flake8 .
73
+
74
+ mypy:
75
+ name: MyPy Type Checking
76
+ runs-on: ubuntu-latest
77
+ steps:
78
+ - uses: actions/checkout@v4
79
+ - name: Set up Python
80
+ uses: actions/setup-python@v5
81
+ with:
82
+ python-version: ${{ env.PYTHON_VERSION }}
83
+ - name: Cache pip
84
+ uses: actions/cache@v4
85
+ with:
86
+ path: ~/.cache/pip
87
+ key: ${{ runner.os }}-pip-${{ hashFiles('requirements.txt') }}
88
+ - name: Install dependencies
89
+ run: |
90
+ python -m pip install --upgrade pip
91
+ pip install -r requirements.txt
92
+ - name: Type check with mypy
93
+ run: mypy . --check-untyped-defs
94
+
95
+ tests:
96
+ name: Run Tests
97
+ runs-on: ubuntu-latest
98
+ steps:
99
+ - uses: actions/checkout@v4
100
+ - name: Set up Python
101
+ uses: actions/setup-python@v5
102
+ with:
103
+ python-version: ${{ env.PYTHON_VERSION }}
104
+ - name: Configure git for tests
105
+ run: |
106
+ git config --global user.email "test@example.com"
107
+ git config --global user.name "Test Runner"
108
+ git config --global init.defaultBranch main
109
+ - name: Cache pip
110
+ uses: actions/cache@v4
111
+ with:
112
+ path: ~/.cache/pip
113
+ key: ${{ runner.os }}-pip-${{ hashFiles('requirements.txt') }}
114
+ - name: Install dependencies
115
+ run: |
116
+ python -m pip install --upgrade pip
117
+ pip install -r requirements.txt
118
+ pip install coverage
119
+ - name: Run tests with coverage
120
+ run: |
121
+ export $(cat .env.dev.example | xargs)
122
+ coverage run -m pytest tests/ -v
123
+ coverage xml
124
+ coverage report
125
+ - name: Upload coverage reports
126
+ uses: codecov/codecov-action@v3
@@ -0,0 +1,22 @@
1
+ name: Notify Slack on Merge to Main
2
+
3
+ on:
4
+ pull_request:
5
+ types: [closed]
6
+ branches:
7
+ - main
8
+
9
+ jobs:
10
+ notify:
11
+ runs-on: ubuntu-latest
12
+ if: github.event.pull_request.merged == true
13
+ steps:
14
+ - name: Send notification to Slack
15
+ uses: slackapi/slack-github-action@v1.24.0
16
+ with:
17
+ payload: |
18
+ {
19
+ "text": ${{ toJSON(format('[Codeplain Client] PR <{0}|#{1}: {2}> was merged to main by `{3}`.', github.event.pull_request.html_url, github.event.pull_request.number, github.event.pull_request.title, github.actor)) }}
20
+ }
21
+ env:
22
+ SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
@@ -0,0 +1,30 @@
1
+ name: Publish Install Script to R2
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - main
7
+ paths:
8
+ - 'install.sh'
9
+ workflow_dispatch:
10
+
11
+ jobs:
12
+ publish:
13
+ name: Upload to Cloudflare R2
14
+ runs-on: ubuntu-latest
15
+
16
+ steps:
17
+ - uses: actions/checkout@v4
18
+
19
+ - name: Upload install.sh to R2
20
+ env:
21
+ AWS_ACCESS_KEY_ID: ${{ secrets.R2_ACCESS_KEY_ID }}
22
+ AWS_SECRET_ACCESS_KEY: ${{ secrets.R2_SECRET_ACCESS_KEY }}
23
+ R2_ENDPOINT: ${{ secrets.R2_ENDPOINT }}
24
+ R2_BUCKET: ${{ secrets.R2_BUCKET }}
25
+ run: |
26
+ aws s3 cp install.sh s3://${R2_BUCKET}/install/install.sh \
27
+ --endpoint-url "${R2_ENDPOINT}" \
28
+ --content-type "text/plain"
29
+
30
+ echo "✓ install.sh uploaded to R2"
@@ -0,0 +1,109 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ release:
5
+ types: [published]
6
+ workflow_dispatch:
7
+ inputs:
8
+ version:
9
+ description: "Version to build (e.g., 0.2.1)"
10
+ required: true
11
+ type: string
12
+ publish_to_pypi:
13
+ description: "Actually publish to PyPI?"
14
+ required: true
15
+ default: false
16
+ type: boolean
17
+
18
+ jobs:
19
+ build:
20
+ name: Build distribution
21
+ runs-on: ubuntu-latest
22
+ permissions:
23
+ contents: write
24
+
25
+ steps:
26
+ - uses: actions/checkout@v4
27
+
28
+ - name: Set up Python
29
+ uses: actions/setup-python@v5
30
+ with:
31
+ python-version: "3.11"
32
+
33
+ - name: Extract version
34
+ id: get_version
35
+ run: |
36
+ if [ "${{ github.event_name }}" = "release" ]; then
37
+ # Strip 'v' prefix from tag (v0.2.1 -> 0.2.1)
38
+ VERSION=${GITHUB_REF_NAME#v}
39
+ else
40
+ # Use manual input
41
+ VERSION="${{ github.event.inputs.version }}"
42
+ fi
43
+ echo "VERSION=$VERSION" >> $GITHUB_OUTPUT
44
+ echo "Extracted version: $VERSION"
45
+
46
+ - name: Update version in pyproject.toml
47
+ run: |
48
+ sed -i "s/^version = .*/version = \"${{ steps.get_version.outputs.VERSION }}\"/" pyproject.toml
49
+ echo "Updated pyproject.toml:"
50
+ grep "^version" pyproject.toml
51
+
52
+ - name: Commit version update to repo
53
+ if: github.event_name == 'release'
54
+ run: |
55
+ git config user.name "github-actions[bot]"
56
+ git config user.email "github-actions[bot]@users.noreply.github.com"
57
+ git add pyproject.toml
58
+ git commit -m "Bump version to ${{ steps.get_version.outputs.VERSION }}"
59
+ git push origin HEAD:main
60
+
61
+ - name: Install uv
62
+ run: |
63
+ curl -LsSf https://astral.sh/uv/install.sh | sh
64
+ echo "$HOME/.local/bin" >> $GITHUB_PATH
65
+
66
+ - name: Build package
67
+ run: |
68
+ uv build
69
+
70
+ - name: Store the distribution packages
71
+ uses: actions/upload-artifact@v4
72
+ with:
73
+ name: python-package-distributions
74
+ path: dist/
75
+
76
+ - name: Upload assets to GitHub Release
77
+ if: github.event_name == 'release'
78
+ env:
79
+ GH_TOKEN: ${{ github.token }}
80
+ run: |
81
+ gh release upload ${{ github.ref_name }} dist/* --clobber
82
+
83
+ publish-to-pypi:
84
+ name: Publish to PyPI
85
+ needs: build
86
+ if: github.event_name == 'release' || github.event.inputs.publish_to_pypi == 'true'
87
+ runs-on: ubuntu-latest
88
+ environment:
89
+ name: pypi
90
+ url: https://pypi.org/p/codeplain
91
+
92
+ steps:
93
+ - name: Download distribution packages
94
+ uses: actions/download-artifact@v4
95
+ with:
96
+ name: python-package-distributions
97
+ path: dist/
98
+
99
+ - name: Install uv
100
+ run: |
101
+ curl -LsSf https://astral.sh/uv/install.sh | sh
102
+ echo "$HOME/.local/bin" >> $GITHUB_PATH
103
+
104
+ - name: Publish to PyPI
105
+ env:
106
+ TWINE_USERNAME: __token__
107
+ TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
108
+ run: |
109
+ uv tool run twine upload dist/*
@@ -0,0 +1,32 @@
1
+ __pycache__
2
+ .DS_Store
3
+
4
+ # Plain
5
+ examples/**/build*/
6
+ examples/**/conformance_tests/
7
+ examples/**/conformance_tests.backup/
8
+ examples/**/node_build/
9
+ examples/**/node_conformance_tests/
10
+ examples/**/package-lock.json
11
+ examples/**/node_modules/
12
+ examples/**/node_harness_tests/
13
+ examples/**/plain_modules/
14
+
15
+ examples/**/go_build/
16
+ examples/**/python_build/
17
+
18
+ examples/**/go_plain_modules/
19
+ examples/**/python_plain_modules/
20
+ examples/**/node_plain_modules/
21
+
22
+
23
+ *.log
24
+
25
+ .venv
26
+ build
27
+ dist
28
+ *.egg-info
29
+
30
+ .env
31
+
32
+ .coverage
@@ -0,0 +1,21 @@
1
+ {
2
+ "version": "0.2.0",
3
+ "configurations": [
4
+ {
5
+ "name": "Debug plain2code.py for file hello_world_python.plain",
6
+ "type": "debugpy",
7
+ "request": "launch",
8
+ "program": "${workspaceFolder}/plain2code.py",
9
+ "args": [
10
+ "${workspaceFolder}/examples/example_hello_world_python/hello_world_python.plain",
11
+ ],
12
+ "subProcess": false,
13
+ "cwd": "${workspaceFolder}/examples/example_hello_world_python",
14
+ "console": "integratedTerminal",
15
+ "justMyCode": false,
16
+ "env": {
17
+ "PYTHONPATH": "${workspaceFolder}"
18
+ }
19
+ }
20
+ ]
21
+ }
@@ -0,0 +1,32 @@
1
+ {
2
+ "editor.formatOnSave": true,
3
+ "editor.insertSpaces": true,
4
+ "editor.detectIndentation": false,
5
+ "editor.codeActionsOnSave": {
6
+ "source.organizeImports": "explicit"
7
+ },
8
+ "[python]": {
9
+ "editor.defaultFormatter": "ms-python.black-formatter",
10
+ "editor.formatOnSave": true,
11
+ "editor.rulers": [120],
12
+ "editor.insertSpaces": true,
13
+ "editor.tabSize": 4
14
+ },
15
+ "editor.defaultFormatter": "ms-python.black-formatter",
16
+ "notebook.defaultFormatter": "ms-python.black-formatter",
17
+ "python.testing.unittestEnabled": true,
18
+ "python.testing.pytestEnabled": false,
19
+ "python.testing.unittestArgs": [
20
+ "-v",
21
+ "-p",
22
+ "test_*.py",
23
+ "-t",
24
+ "${workspaceFolder}"
25
+ ],
26
+ "python.analysis.extraPaths": [
27
+ "${workspaceFolder}"
28
+ ],
29
+ "files.associations": {
30
+ "**/tests/data/*": "text"
31
+ }
32
+ }
@@ -1,32 +1,31 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: codeplain
3
- Version: 0.2.2
3
+ Version: 0.2.4
4
4
  Summary: Transform plain language specifications into working code
5
+ License-File: LICENSE
5
6
  Classifier: Environment :: Console
6
7
  Classifier: Intended Audience :: Developers
7
8
  Classifier: Operating System :: OS Independent
8
9
  Classifier: Topic :: Software Development :: Code Generators
9
10
  Requires-Python: >=3.11
10
- Description-Content-Type: text/markdown
11
- License-File: LICENSE
12
- Requires-Dist: python-liquid2==0.3.0
11
+ Requires-Dist: gitpython==3.1.42
13
12
  Requires-Dist: mistletoe==1.3.0
13
+ Requires-Dist: networkx==3.6.1
14
+ Requires-Dist: python-frontmatter==1.1.0
15
+ Requires-Dist: python-liquid2==0.3.0
16
+ Requires-Dist: pyyaml==6.0.2
14
17
  Requires-Dist: requests==2.32.3
18
+ Requires-Dist: rich==14.2.0
19
+ Requires-Dist: textual==1.0.0
15
20
  Requires-Dist: tiktoken==0.12.0
16
- Requires-Dist: PyYAML==6.0.2
17
- Requires-Dist: gitpython==3.1.42
18
21
  Requires-Dist: transitions==0.9.3
19
- Requires-Dist: textual==1.0.0
20
- Requires-Dist: rich==14.2.0
21
- Requires-Dist: python-frontmatter==1.1.0
22
- Requires-Dist: networkx==3.6.1
23
22
  Provides-Extra: dev
24
- Requires-Dist: pytest==8.3.5; extra == "dev"
25
- Requires-Dist: flake8==7.0.0; extra == "dev"
26
- Requires-Dist: black==24.2.0; extra == "dev"
27
- Requires-Dist: isort==5.13.2; extra == "dev"
28
- Requires-Dist: mypy==1.11.2; extra == "dev"
29
- Dynamic: license-file
23
+ Requires-Dist: black==24.2.0; extra == 'dev'
24
+ Requires-Dist: flake8==7.0.0; extra == 'dev'
25
+ Requires-Dist: isort==5.13.2; extra == 'dev'
26
+ Requires-Dist: mypy==1.11.2; extra == 'dev'
27
+ Requires-Dist: pytest==8.3.5; extra == 'dev'
28
+ Description-Content-Type: text/markdown
30
29
 
31
30
  # Codeplain plain2code renderer
32
31
 
@@ -65,12 +65,6 @@ class CodeplainAPI:
65
65
  if response_json["error_code"] == "PlainSyntaxError":
66
66
  raise plain2code_exceptions.PlainSyntaxError(response_json["message"])
67
67
 
68
- if response_json["error_code"] == "OnlyRelativeLinksAllowed":
69
- raise plain2code_exceptions.OnlyRelativeLinksAllowed(response_json["message"])
70
-
71
- if response_json["error_code"] == "LinkMustHaveTextSpecified":
72
- raise plain2code_exceptions.LinkMustHaveTextSpecified(response_json["message"])
73
-
74
68
  if response_json["error_code"] == "NoRenderFound":
75
69
  raise plain2code_exceptions.NoRenderFound(response_json["message"])
76
70
 
@@ -0,0 +1,20 @@
1
+ import os
2
+ import sys
3
+
4
+ from plain2code_arguments import create_parser
5
+
6
+ # Add the parent directory to the path so we can import plain2code_arguments
7
+ sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
8
+
9
+
10
+ # Get the parser and generate help text
11
+ parser = create_parser()
12
+ help_text = parser.format_help()
13
+
14
+ # Create markdown
15
+ md = "# Plain2Code CLI Reference\n\n```text\n" + help_text + "\n```"
16
+
17
+ # Run generate_cli.py in the docs folder
18
+
19
+ with open("plain2code_cli.md", "w", encoding="utf-8") as f:
20
+ f.write(md)
@@ -0,0 +1,66 @@
1
+ # Plain2Code CLI Reference
2
+
3
+ ```text
4
+ usage: generate_cli.py [-h] [--verbose] [--base-folder BASE_FOLDER] [--build-folder BUILD_FOLDER] [--config-name CONFIG_NAME]
5
+ [--render-range RENDER_RANGE | --render-from RENDER_FROM] [--unittests-script UNITTESTS_SCRIPT]
6
+ [--conformance-tests-folder CONFORMANCE_TESTS_FOLDER] [--conformance-tests-script CONFORMANCE_TESTS_SCRIPT]
7
+ [--api [API]] [--api-key API_KEY] [--full-plain] [--dry-run] [--replay-with REPLAY_WITH]
8
+ [--template-dir TEMPLATE_DIR] [--copy-build] [--build-dest BUILD_DEST] [--copy-conformance-tests]
9
+ [--conformance-tests-dest CONFORMANCE_TESTS_DEST]
10
+ filename
11
+
12
+ Render plain code to target code.
13
+
14
+ positional arguments:
15
+ filename Path to the plain file to render. The directory containing this file has highest precedence for template
16
+ loading, so you can place custom templates here to override the defaults. See --template-dir for more
17
+ details about template loading.
18
+
19
+ options:
20
+ -h, --help show this help message and exit
21
+ --verbose, -v Enable verbose output
22
+ --base-folder BASE_FOLDER
23
+ Base folder for the build files
24
+ --build-folder BUILD_FOLDER
25
+ Folder for build files
26
+ --render-range RENDER_RANGE
27
+ Specify a range of functional requirements to render (e.g. '1.1,2.3'). Use comma to separate start and end
28
+ IDs. If only one ID is provided, only that requirement is rendered. Range is inclusive of both start and
29
+ end IDs.
30
+ --render-from RENDER_FROM
31
+ Continue generation starting from this specific functional requirement (e.g. '2.1'). The requirement with
32
+ this ID will be included in the output. The ID must match one of the functional requirements in your plain
33
+ file.
34
+ --unittests-script UNITTESTS_SCRIPT
35
+ Shell script to run unit tests on generated code. Receives the build folder path as its first argument
36
+ (default: 'build').
37
+ --conformance-tests-folder CONFORMANCE_TESTS_FOLDER
38
+ Folder for conformance test files
39
+ --conformance-tests-script CONFORMANCE_TESTS_SCRIPT
40
+ Path to conformance tests shell script. The conformance tests shell script should accept the build folder
41
+ path (containing generated source code) as its first argument and the conformance tests folder path
42
+ (containing test files) as its second argument.
43
+ --api [API] Alternative base URL for the API. Default: `https://api.codeplain.ai`
44
+ --api-key API_KEY API key used to access the API. If not provided, the CLAUDE_API_KEY environment variable is used.
45
+ --full-plain Display the complete plain specification before code generation. This shows your plain file with any
46
+ included template content expanded. Useful for understanding what content is being processed.
47
+ --dry-run Preview of what Codeplain would do without actually making any changes.
48
+ --replay-with REPLAY_WITH
49
+ --template-dir TEMPLATE_DIR
50
+ Path to a custom template directory. Templates are searched in the following order: 1) directory containing
51
+ the plain file, 2) this custom template directory (if provided), 3) built-in standard_template_library
52
+ directory
53
+ --copy-build If set, copy the build folder to `--build-dest` after every successful rendering.
54
+ --build-dest BUILD_DEST
55
+ Target folder to copy build output to (used only if --copy-build is set).
56
+ --copy-conformance-tests
57
+ If set, copy the conformance tests folder to `--conformance-tests-dest` after every successful rendering.
58
+ Requires --conformance-tests-script.
59
+ --conformance-tests-dest CONFORMANCE_TESTS_DEST
60
+ Target folder to copy conformance tests output to (used only if --copy-conformance-tests is set).
61
+
62
+ configuration:
63
+ --config-name CONFIG_NAME
64
+ Path to the config file, defaults to config.yaml
65
+
66
+ ```