codeplain 0.2.10__tar.gz → 0.2.12__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.
- codeplain-0.2.12/.github/workflows/publish-install-script.yml +56 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/PKG-INFO +1 -1
- codeplain-0.2.12/_version.py +1 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/config/system_config.yaml +0 -2
- {codeplain-0.2.10 → codeplain-0.2.12}/docs/plain_language_specification.md +30 -67
- {codeplain-0.2.10 → codeplain-0.2.12}/file_utils.py +24 -1
- {codeplain-0.2.10/install → codeplain-0.2.12/install/bash}/install.sh +6 -2
- codeplain-0.2.12/install/powershell/examples.ps1 +99 -0
- codeplain-0.2.12/install/powershell/install.ps1 +270 -0
- codeplain-0.2.12/install/powershell/walkthrough.ps1 +173 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/memory_management.py +25 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/module_renderer.py +1 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/plain2code.py +0 -2
- {codeplain-0.2.10 → codeplain-0.2.12}/plain2code_arguments.py +7 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/plain2code_console.py +1 -1
- {codeplain-0.2.10 → codeplain-0.2.12}/pyproject.toml +4 -1
- {codeplain-0.2.10 → codeplain-0.2.12}/render_machine/actions/analyze_specification_ambiguity.py +5 -2
- {codeplain-0.2.10 → codeplain-0.2.12}/render_machine/actions/prepare_testing_environment.py +1 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/render_machine/actions/run_conformance_tests.py +3 -4
- {codeplain-0.2.10 → codeplain-0.2.12}/render_machine/actions/run_unit_tests.py +1 -0
- codeplain-0.2.12/render_machine/implementation_code_helpers.py +49 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/render_machine/render_context.py +2 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/render_machine/render_utils.py +28 -8
- {codeplain-0.2.10 → codeplain-0.2.12}/standard_template_library/python-console-app-template.plain +1 -3
- {codeplain-0.2.10 → codeplain-0.2.12}/system_config.py +2 -3
- {codeplain-0.2.10 → codeplain-0.2.12}/tests/data/imports/circular_imports_2.plain +1 -1
- codeplain-0.2.10/.github/workflows/publish-install-script.yml +0 -39
- codeplain-0.2.10/render_machine/implementation_code_helpers.py +0 -26
- {codeplain-0.2.10 → codeplain-0.2.12}/.flake8 +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/.github/workflows/lint-and-test.yml +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/.github/workflows/nofity-slack-on-main-merge.yml +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/.github/workflows/publish-to-pypi.yml +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/.gitignore +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/.vscode/launch.json +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/.vscode/settings.json +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/LICENSE +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/README.md +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/codeplain_REST_api.py +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/concept_utils.py +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/config/__init__.py +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/diff_utils.py +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/docs/generate_cli.py +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/docs/plain2code_cli.md +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/docs/starting_a_plain_project_from_scratch.md +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/event_bus.py +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/examples/example_hello_world_golang/config.yaml +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/examples/example_hello_world_golang/harness_tests/hello_world_test.go +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/examples/example_hello_world_golang/hello_world_golang.plain +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/examples/example_hello_world_golang/run.sh +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/examples/example_hello_world_python/config.yaml +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/examples/example_hello_world_python/harness_tests/hello_world_display/test_hello_world.py +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/examples/example_hello_world_python/hello_world_python.plain +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/examples/example_hello_world_python/run.sh +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/examples/example_hello_world_react/config.yaml +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/examples/example_hello_world_react/harness_tests/hello_world_display/cypress/e2e/hello_world.cy.ts +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/examples/example_hello_world_react/harness_tests/hello_world_display/cypress/support/e2e.ts +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/examples/example_hello_world_react/harness_tests/hello_world_display/cypress.config.ts +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/examples/example_hello_world_react/harness_tests/hello_world_display/package.json +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/examples/example_hello_world_react/harness_tests/hello_world_display/tsconfig.json +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/examples/example_hello_world_react/hello_world_react.plain +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/examples/example_hello_world_react/run.sh +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/examples/run.sh +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/git_utils.py +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/hash_key.py +0 -0
- {codeplain-0.2.10/install → codeplain-0.2.12/install/bash}/examples.sh +0 -0
- {codeplain-0.2.10/install → codeplain-0.2.12/install/bash}/walkthrough.sh +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/plain2code_events.py +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/plain2code_exceptions.py +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/plain2code_logger.py +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/plain2code_nodes.py +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/plain2code_read_config.py +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/plain2code_state.py +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/plain2code_utils.py +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/plain_file.py +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/plain_modules.py +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/plain_spec.py +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/pytest.ini +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/render_machine/__init__.py +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/render_machine/actions/base_action.py +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/render_machine/actions/commit_conformance_tests_changes.py +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/render_machine/actions/commit_implementation_code_changes.py +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/render_machine/actions/create_dist.py +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/render_machine/actions/exit_with_error.py +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/render_machine/actions/finish_functional_requirement.py +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/render_machine/actions/fix_conformance_test.py +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/render_machine/actions/fix_unit_tests.py +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/render_machine/actions/prepare_repositories.py +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/render_machine/actions/refactor_code.py +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/render_machine/actions/render_conformance_tests.py +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/render_machine/actions/render_functional_requirement.py +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/render_machine/actions/summarize_conformance_tests.py +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/render_machine/code_renderer.py +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/render_machine/conformance_test_helpers.py +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/render_machine/conformance_tests.py +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/render_machine/render_types.py +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/render_machine/state_machine_config.py +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/render_machine/states.py +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/render_machine/triggers.py +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/requirements.txt +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/resources/codeplain_overview.png +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/resources/plain_example.png +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/standard_template_library/__init__.py +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/standard_template_library/golang-console-app-template.plain +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/standard_template_library/typescript-react-app-boilerplate.plain +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/standard_template_library/typescript-react-app-template.plain +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/test_scripts/run_conformance_tests_cypress.sh +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/test_scripts/run_conformance_tests_golang.sh +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/test_scripts/run_conformance_tests_python.sh +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/test_scripts/run_unittests_golang.sh +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/test_scripts/run_unittests_python.sh +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/test_scripts/run_unittests_react.sh +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/tests/__init__.py +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/tests/conftest.py +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/tests/data/imports/circular_imports_1.plain +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/tests/data/imports/circular_imports_main.plain +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/tests/data/imports/diamond_import_1.plain +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/tests/data/imports/diamond_import_2.plain +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/tests/data/imports/diamond_import_common.plain +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/tests/data/imports/diamond_imports_main.plain +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/tests/data/imports/non_existent_import.plain +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/tests/data/plainfile/duplicate_specification_heading.plain +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/tests/data/plainfile/invalid_specification_order.plain +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/tests/data/plainfile/missing_non_functional_requirements.plain +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/tests/data/plainfile/plain_source_with_absolute_link.plain +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/tests/data/plainfile/plain_source_with_url_link.plain +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/tests/data/plainfile/task_manager_with_reference_links.plain +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/tests/data/plainfile/without_non_functional_requirement.plain +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/tests/data/plainfileparser/concept_validation_acceptance_tests.plain +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/tests/data/plainfileparser/concept_validation_acceptance_tests_nondefined.plain +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/tests/data/plainfileparser/concept_validation_defined_nondefined.plain +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/tests/data/plainfileparser/concept_validation_defined_nondefined_2.plain +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/tests/data/plainfileparser/concept_validation_definition.plain +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/tests/data/plainfileparser/concept_validation_noconcepts.plain +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/tests/data/plainfileparser/concept_validation_nonconcept.plain +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/tests/data/plainfileparser/concept_validation_nondefined.plain +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/tests/data/plainfileparser/concept_validation_redefinition.plain +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/tests/data/plainfileparser/concept_validation_several_concepts.plain +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/tests/data/plainfileparser/concept_validation_valid.plain +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/tests/data/plainfileparser/exported_concepts.plain +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/tests/data/plainfileparser/exported_concepts_base.plain +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/tests/data/plainfileparser/exported_concepts_example.plain +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/tests/data/plainfileparser/exported_concepts_missing.plain +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/tests/data/plainfileparser/exported_concepts_missing_example.plain +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/tests/data/plainfileparser/exported_concepts_nested.plain +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/tests/data/plainfileparser/exported_concepts_nested_example.plain +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/tests/data/plainfileparser/exported_concepts_transitive_example.plain +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/tests/data/plainfileparser/exported_concepts_transitive_l1.plain +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/tests/data/plainfileparser/exported_concepts_transitive_l2.plain +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/tests/data/plainfileparser/plain_file_parser_with_comments.plain +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/tests/data/plainfileparser/plain_file_with_comments_indented.plain +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/tests/data/plainfileparser/regular_plain_source.plain +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/tests/data/plainfileparser/required_concepts.plain +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/tests/data/plainfileparser/required_concepts_defs.plain +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/tests/data/plainfileparser/required_concepts_example.plain +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/tests/data/plainfileparser/required_concepts_l1.plain +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/tests/data/plainfileparser/required_concepts_l2.plain +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/tests/data/plainfileparser/required_concepts_missing.plain +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/tests/data/plainfileparser/required_concepts_module.plain +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/tests/data/plainfileparser/required_concepts_partial.plain +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/tests/data/plainfileparser/required_concepts_partial_duplicate.plain +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/tests/data/plainfileparser/topological_sort.plain +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/tests/data/plainfileparser/topological_sort_not_referenced.plain +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/tests/data/requires/circular_requires_main.plain +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/tests/data/requires/circular_requires_sub.plain +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/tests/data/requires/diamond_requires_1.plain +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/tests/data/requires/diamond_requires_2.plain +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/tests/data/requires/diamond_requires_common.plain +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/tests/data/requires/diamond_requires_main.plain +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/tests/data/requires/independent_requires_1.plain +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/tests/data/requires/independent_requires_2.plain +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/tests/data/requires/independent_requires_main.plain +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/tests/data/requires/non_existent_require.plain +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/tests/data/requires/normal_requires_1.plain +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/tests/data/requires/normal_requires_2.plain +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/tests/data/requires/normal_requires_common.plain +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/tests/data/requires/normal_requires_main.plain +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/tests/data/simple.plain +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/tests/data/templates/block_level_include.plain +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/tests/data/templates/code_variables.plain +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/tests/data/templates/header.plain +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/tests/data/templates/implement.plain +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/tests/data/templates/implement_2.plain +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/tests/data/templates/template_include.plain +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/tests/data/templates/test_hardest_problem.plain +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/tests/test_git_utils.py +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/tests/test_imports.py +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/tests/test_plainfile.py +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/tests/test_plainfileparser.py +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/tests/test_plainspec.py +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/tests/test_requires.py +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/tui/__init__.py +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/tui/components.py +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/tui/models.py +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/tui/plain2code_tui.py +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/tui/spinner.py +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/tui/state_handlers.py +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/tui/styles.css +0 -0
- {codeplain-0.2.10 → codeplain-0.2.12}/tui/widget_helpers.py +0 -0
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
name: Publish Install Scripts to R2
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches:
|
|
6
|
+
- main
|
|
7
|
+
paths:
|
|
8
|
+
- 'install/bash/*.sh'
|
|
9
|
+
- 'install/powershell/*.ps1'
|
|
10
|
+
workflow_dispatch:
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
publish:
|
|
14
|
+
name: Upload to Cloudflare R2
|
|
15
|
+
runs-on: ubuntu-latest
|
|
16
|
+
|
|
17
|
+
steps:
|
|
18
|
+
- uses: actions/checkout@v4
|
|
19
|
+
|
|
20
|
+
- name: Upload install scripts to R2
|
|
21
|
+
env:
|
|
22
|
+
AWS_ACCESS_KEY_ID: ${{ secrets.R2_ACCESS_KEY_ID }}
|
|
23
|
+
AWS_SECRET_ACCESS_KEY: ${{ secrets.R2_SECRET_ACCESS_KEY }}
|
|
24
|
+
R2_ENDPOINT: ${{ secrets.R2_ENDPOINT }}
|
|
25
|
+
R2_BUCKET: ${{ secrets.R2_BUCKET }}
|
|
26
|
+
run: |
|
|
27
|
+
aws s3 cp install/bash/install.sh s3://${R2_BUCKET}/install/install.sh \
|
|
28
|
+
--endpoint-url "${R2_ENDPOINT}" \
|
|
29
|
+
--content-type "text/plain"
|
|
30
|
+
echo "✓ install.sh uploaded to R2"
|
|
31
|
+
|
|
32
|
+
aws s3 cp install/bash/walkthrough.sh s3://${R2_BUCKET}/install/walkthrough.sh \
|
|
33
|
+
--endpoint-url "${R2_ENDPOINT}" \
|
|
34
|
+
--content-type "text/plain"
|
|
35
|
+
echo "✓ walkthrough.sh uploaded to R2"
|
|
36
|
+
|
|
37
|
+
aws s3 cp install/bash/examples.sh s3://${R2_BUCKET}/install/examples.sh \
|
|
38
|
+
--endpoint-url "${R2_ENDPOINT}" \
|
|
39
|
+
--content-type "text/plain"
|
|
40
|
+
echo "✓ examples.sh uploaded to R2"
|
|
41
|
+
|
|
42
|
+
aws s3 cp install/powershell/install.ps1 s3://${R2_BUCKET}/install/install.ps1 \
|
|
43
|
+
--endpoint-url "${R2_ENDPOINT}" \
|
|
44
|
+
--content-type "text/plain"
|
|
45
|
+
echo "✓ install.ps1 uploaded to R2"
|
|
46
|
+
|
|
47
|
+
aws s3 cp install/powershell/walkthrough.ps1 s3://${R2_BUCKET}/install/walkthrough.ps1 \
|
|
48
|
+
--endpoint-url "${R2_ENDPOINT}" \
|
|
49
|
+
--content-type "text/plain"
|
|
50
|
+
echo "✓ walkthrough.ps1 uploaded to R2"
|
|
51
|
+
|
|
52
|
+
aws s3 cp install/powershell/examples.ps1 s3://${R2_BUCKET}/install/examples.ps1 \
|
|
53
|
+
--endpoint-url "${R2_ENDPOINT}" \
|
|
54
|
+
--content-type "text/plain"
|
|
55
|
+
echo "✓ examples.ps1 uploaded to R2"
|
|
56
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.2.12"
|
|
@@ -13,68 +13,31 @@
|
|
|
13
13
|
Here's an example of a "hello, world" program in ***plain.
|
|
14
14
|
|
|
15
15
|
```plain
|
|
16
|
-
***
|
|
16
|
+
***implementation reqs***
|
|
17
17
|
|
|
18
18
|
- :Implementation: should be in Python.
|
|
19
19
|
|
|
20
|
-
***
|
|
20
|
+
***functional specs***
|
|
21
21
|
|
|
22
22
|
- Display "hello, world"
|
|
23
23
|
```
|
|
24
24
|
|
|
25
|
-
# Source structure
|
|
26
|
-
|
|
27
|
-
## Source organization
|
|
28
|
-
|
|
29
|
-
***plain source can be organized in sections and subsection using markdown headers.
|
|
30
|
-
|
|
31
|
-
```plain
|
|
32
|
-
# Section 1
|
|
33
|
-
|
|
34
|
-
# Section 2
|
|
35
|
-
|
|
36
|
-
***Non-Functional Requirements:***
|
|
37
|
-
|
|
38
|
-
- First simple non-functional requirement
|
|
39
|
-
|
|
40
|
-
***Functional Requirements:***
|
|
41
|
-
|
|
42
|
-
- First simple functional requirement
|
|
43
|
-
|
|
44
|
-
## Section 2.1
|
|
45
|
-
|
|
46
|
-
***Non-Functional Requirements:***
|
|
47
|
-
|
|
48
|
-
- Second simple non-functional requirement
|
|
49
|
-
|
|
50
|
-
***Functional Requirements:***
|
|
51
|
-
|
|
52
|
-
- Second simple functional requirement
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
This enables hierarchical organization of the specification.
|
|
56
|
-
|
|
57
|
-
In example above:
|
|
58
|
-
|
|
59
|
-
- While rendering the "First simple functional requirement", the renderer will not have access to the "Second simple non-functional requirement".
|
|
60
|
-
- While rendering the "Second simple functional requirement", the renderer will not have access to the "First simple non-functional requirement".
|
|
61
|
-
|
|
62
25
|
### Specifications
|
|
63
26
|
|
|
64
27
|
There are four types of specifications:
|
|
65
28
|
|
|
66
|
-
- `***
|
|
67
|
-
- `***
|
|
68
|
-
- `***
|
|
69
|
-
- `***
|
|
29
|
+
- `***definitions***`
|
|
30
|
+
- `***implementation reqs***`
|
|
31
|
+
- `***functional specs***`
|
|
32
|
+
- `***test reqs***`
|
|
70
33
|
|
|
71
|
-
Every plain source file requires at least one functional
|
|
34
|
+
Every plain source file requires at least one functional spec and an associated implementation req.
|
|
72
35
|
|
|
73
|
-
Functional
|
|
36
|
+
Functional specs must reside in leaf sections while other specifications can be placed also in non-leaf sections. Specifications in non-leaf sections apply not just to the section itself but to all of its subsections.
|
|
74
37
|
|
|
75
38
|
## Definitions
|
|
76
39
|
|
|
77
|
-
The `***
|
|
40
|
+
The `***definitions***` specification is a list of definitions of new concepts.
|
|
78
41
|
|
|
79
42
|
Here's an example of a simple definiton.
|
|
80
43
|
|
|
@@ -89,9 +52,9 @@ While providing definitions, you should adhere to the following 4 rules:
|
|
|
89
52
|
- Every definition must start with the name of the concept you are defining.
|
|
90
53
|
- Each concept name must be enclosed in colons (`:`) at both the beginning and end.
|
|
91
54
|
- Valid characters for concept name include: Plus sign (`+`), Minus sign (`-`), Dot sign (`.`), Digits (`0`-`9`), Uppercase letters (`A`-`Z`), Underscore (`_`), Lowercase letters (`a`-`z`)
|
|
92
|
-
- Examples: `:App:`, `:Tasks:`, `:ListOfUsers:`, `:CLI:`.
|
|
55
|
+
- Examples: `:App:`, `:Tasks:`, `:ListOfUsers:`, `:CLI:`.
|
|
93
56
|
- Concept names must be globally unique (meaning, you cannot provide two definitions with the same concept name).
|
|
94
|
-
- When referencing concepts in ***
|
|
57
|
+
- When referencing concepts in ***test reqs***, ***functional specs***, ***implementation reqs*** and ***acceptance tests***, the concept name must exist in the ***definitions*** section.
|
|
95
58
|
|
|
96
59
|
Furthermore, there are special concepts that are already defined and are ready to use. They should not be redefined:
|
|
97
60
|
|
|
@@ -111,9 +74,9 @@ Definitions are the mechanism for definining data structures in ***plain. Here's
|
|
|
111
74
|
- Due Date - optional date by which :User: is supposed to complete :Task:.
|
|
112
75
|
```
|
|
113
76
|
|
|
114
|
-
##
|
|
77
|
+
## Implementation Reqs
|
|
115
78
|
|
|
116
|
-
The `***
|
|
79
|
+
The `***implementation reqs***` specification is a list of instructions that steer software code implementation and provide details of execution environment.
|
|
117
80
|
|
|
118
81
|
Here's an example of a simple instruction specifying only that the ***plain specification should be rendered to Python software code.
|
|
119
82
|
|
|
@@ -133,9 +96,9 @@ Here's an example of more complex instructions.
|
|
|
133
96
|
- The main executable file of :App: should be called hello_world.py
|
|
134
97
|
```
|
|
135
98
|
|
|
136
|
-
## Functional
|
|
99
|
+
## Functional Specs
|
|
137
100
|
|
|
138
|
-
The `***
|
|
101
|
+
The `***functional specs***` specification provides a description of functionality that should be rendered to software code. The descriptions should be provided in natural language as a markdown list.
|
|
139
102
|
|
|
140
103
|
Here's an example of a simple description of the functionality of the "hello, world" application.
|
|
141
104
|
|
|
@@ -143,7 +106,7 @@ Here's an example of a simple description of the functionality of the "hello, wo
|
|
|
143
106
|
- Display "hello, world"
|
|
144
107
|
```
|
|
145
108
|
|
|
146
|
-
Each functional
|
|
109
|
+
Each functional spec must be limited in complexity. For example, for the functional spec
|
|
147
110
|
|
|
148
111
|
```plain
|
|
149
112
|
- :App: should implement a task manager application.
|
|
@@ -152,10 +115,10 @@ Each functional requirement must be limited in complexity. For example, for the
|
|
|
152
115
|
the renderer of ***plain source to software code should respond with
|
|
153
116
|
|
|
154
117
|
```
|
|
155
|
-
Functional
|
|
118
|
+
Functional spec too complex!
|
|
156
119
|
```
|
|
157
120
|
|
|
158
|
-
In such case you need to break down the functioanlity into smaller, less-complex functional
|
|
121
|
+
In such case you need to break down the functioanlity into smaller, less-complex functional specs.
|
|
159
122
|
|
|
160
123
|
Here's an example how to do such a break down in the case of a task manager application.
|
|
161
124
|
|
|
@@ -173,38 +136,38 @@ Here's an example how to do such a break down in the case of a task manager appl
|
|
|
173
136
|
- :User: should be able to mark :Task: as completed.
|
|
174
137
|
```
|
|
175
138
|
|
|
176
|
-
Functional
|
|
139
|
+
Functional specs are rendered incrementally one by one. Consequently earlier functional specs cannot reference later functional specs.
|
|
177
140
|
|
|
178
141
|
### Acceptance Tests
|
|
179
142
|
|
|
180
|
-
Acceptance tests can be used to further refine the functional
|
|
143
|
+
Acceptance tests can be used to further refine the functional spec and especially to incorporate constraints on the implementation.
|
|
181
144
|
|
|
182
|
-
Acceptance tests are specified with a keyword `***
|
|
145
|
+
Acceptance tests are specified with a keyword `***acceptance tests***` as a subsection within `***functional specs***` section. Each acceptance tests must be an item in a list.
|
|
183
146
|
|
|
184
147
|
Here's an example of a "Hello, World" application with one acceptance test.
|
|
185
148
|
|
|
186
149
|
```plain
|
|
187
|
-
***
|
|
150
|
+
***functional specs***
|
|
188
151
|
|
|
189
152
|
- Display "hello, world"
|
|
190
153
|
|
|
191
|
-
***
|
|
192
|
-
|
|
154
|
+
***acceptance tests***
|
|
155
|
+
|
|
193
156
|
- :App: shouldn't show logging output in the console output (neither in stdout nor stderr).
|
|
194
157
|
```
|
|
195
158
|
|
|
196
|
-
Acceptance tests extend **conformance tests**. The acceptance tests are implemented according to the ***
|
|
159
|
+
Acceptance tests extend **conformance tests**. The acceptance tests are implemented according to the ***test reqs*** specification (see below).
|
|
197
160
|
|
|
198
|
-
## Test
|
|
161
|
+
## Test Reqs
|
|
199
162
|
|
|
200
|
-
The `***
|
|
163
|
+
The `***test reqs***` specification is a list of instructions that steer implementation of conformance tests and provide details of testing environment.
|
|
201
164
|
|
|
202
|
-
**Conformance tests** is the generated code used to verify that the functional
|
|
165
|
+
**Conformance tests** is the generated code used to verify that the functional spec is implemented according to the specification.
|
|
203
166
|
|
|
204
|
-
Here's an example specification of test
|
|
167
|
+
Here's an example specification of test reqs.
|
|
205
168
|
|
|
206
169
|
```plain
|
|
207
|
-
- :ConformanceTests: of :App: should be implemented in Python using Unittest framework.
|
|
170
|
+
- :ConformanceTests: of :App: should be implemented in Python using Unittest framework.
|
|
208
171
|
```
|
|
209
172
|
|
|
210
173
|
# Extended Syntax
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import os
|
|
2
2
|
import shutil
|
|
3
|
+
import stat
|
|
3
4
|
from pathlib import Path
|
|
4
5
|
|
|
5
6
|
from liquid2 import Environment, FileSystemLoader, StrictUndefined
|
|
@@ -46,6 +47,11 @@ FILE_EXTENSION_MAPPING = {
|
|
|
46
47
|
SYSTEM_FOLDERS = [".git", CODEPLAIN_METADATA_FOLDER, CODEPLAIN_MEMORY_SUBFOLDER]
|
|
47
48
|
|
|
48
49
|
|
|
50
|
+
def is_system_folder_path(file_path: str) -> bool:
|
|
51
|
+
parts = Path(file_path).parts
|
|
52
|
+
return bool(parts) and parts[0] in SYSTEM_FOLDERS
|
|
53
|
+
|
|
54
|
+
|
|
49
55
|
def get_file_type(file_name):
|
|
50
56
|
|
|
51
57
|
# Extract the file extension
|
|
@@ -94,7 +100,22 @@ def list_folders_in_directory(directory):
|
|
|
94
100
|
# delete a folder and all its subfolders and files
|
|
95
101
|
def delete_folder(folder_name):
|
|
96
102
|
if os.path.exists(folder_name):
|
|
97
|
-
|
|
103
|
+
# Use writable-aware deletion so read-only files (e.g. .git objects on Windows) don't cause PermissionError
|
|
104
|
+
delete_files_and_subfolders(folder_name)
|
|
105
|
+
_make_writable(folder_name)
|
|
106
|
+
os.rmdir(folder_name)
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def _make_writable(path: str) -> None:
|
|
110
|
+
"""On Windows, clear read-only so deletion can succeed."""
|
|
111
|
+
# TODO - Check if this can be done in a cleaner way.
|
|
112
|
+
is_windows = os.name == "nt"
|
|
113
|
+
if is_windows:
|
|
114
|
+
try:
|
|
115
|
+
mode = os.stat(path).st_mode
|
|
116
|
+
os.chmod(path, mode | stat.S_IWRITE)
|
|
117
|
+
except OSError:
|
|
118
|
+
pass
|
|
98
119
|
|
|
99
120
|
|
|
100
121
|
def delete_files_and_subfolders(directory):
|
|
@@ -106,12 +127,14 @@ def delete_files_and_subfolders(directory):
|
|
|
106
127
|
# Delete files
|
|
107
128
|
for file in files:
|
|
108
129
|
file_path = os.path.join(root, file)
|
|
130
|
+
_make_writable(file_path)
|
|
109
131
|
os.remove(file_path)
|
|
110
132
|
total_files_deleted += 1
|
|
111
133
|
|
|
112
134
|
# Delete directories
|
|
113
135
|
for dir_ in dirs:
|
|
114
136
|
dir_path = os.path.join(root, dir_)
|
|
137
|
+
_make_writable(dir_path)
|
|
115
138
|
os.rmdir(dir_path)
|
|
116
139
|
total_folders_deleted += 1
|
|
117
140
|
|
|
@@ -219,9 +219,13 @@ echo -e "${GRAY}─────────────────────
|
|
|
219
219
|
echo -e " ${YELLOW}${BOLD}You're all set!${NC}"
|
|
220
220
|
echo -e "${GRAY}────────────────────────────────────────────${NC}"
|
|
221
221
|
echo ""
|
|
222
|
-
echo -e " thank you for using *codeplain
|
|
222
|
+
echo -e " thank you for using ${YELLOW}*codeplain!${NC}"
|
|
223
223
|
echo ""
|
|
224
|
-
echo -e "
|
|
224
|
+
echo -e " ${BOLD}next steps:${NC}"
|
|
225
|
+
echo ""
|
|
226
|
+
echo -e " join our Discord community: ${YELLOW}https://discord.gg/4qQJaMu7Y${NC}"
|
|
227
|
+
echo ""
|
|
228
|
+
echo -e " learn more about ${YELLOW}***plain${NC} at ${YELLOW}https://plainlang.org/${NC}"
|
|
225
229
|
echo ""
|
|
226
230
|
echo -e " ${GREEN}happy development!${NC} 🚀"
|
|
227
231
|
echo ""
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
$ErrorActionPreference = 'Stop'
|
|
2
|
+
|
|
3
|
+
# Brand Colors (use exported colors if available, otherwise define them)
|
|
4
|
+
if (-not $env:YELLOW) { $YELLOW = "$([char]27)[38;2;224;255;110m" } else { $YELLOW = $env:YELLOW }
|
|
5
|
+
if (-not $env:GREEN) { $GREEN = "$([char]27)[38;2;121;252;150m" } else { $GREEN = $env:GREEN }
|
|
6
|
+
if (-not $env:RED) { $RED = "$([char]27)[38;2;239;68;68m" } else { $RED = $env:RED }
|
|
7
|
+
if (-not $env:GRAY) { $GRAY = "$([char]27)[38;2;128;128;128m" } else { $GRAY = $env:GRAY }
|
|
8
|
+
if (-not $env:BOLD) { $BOLD = "$([char]27)[1m" } else { $BOLD = $env:BOLD }
|
|
9
|
+
if (-not $env:NC) { $NC = "$([char]27)[0m" } else { $NC = $env:NC }
|
|
10
|
+
|
|
11
|
+
# Examples configuration
|
|
12
|
+
$EXAMPLES_FOLDER_NAME = "plainlang-examples"
|
|
13
|
+
$EXAMPLES_DOWNLOAD_URL = "https://github.com/Codeplain-ai/plainlang-examples/archive/refs/tags/0.1.zip"
|
|
14
|
+
|
|
15
|
+
# Show current directory and ask for extraction path
|
|
16
|
+
$CURRENT_DIR = Get-Location
|
|
17
|
+
Write-Host " current folder: ${YELLOW}${CURRENT_DIR}${NC}"
|
|
18
|
+
Write-Host ""
|
|
19
|
+
Write-Host " extract examples here, or enter a different path:"
|
|
20
|
+
Write-Host ""
|
|
21
|
+
$EXTRACT_PATH = Read-Host " [Enter for current, or type path]"
|
|
22
|
+
Write-Host ""
|
|
23
|
+
|
|
24
|
+
# Use current directory if empty
|
|
25
|
+
if (-not $EXTRACT_PATH) {
|
|
26
|
+
$EXTRACT_PATH = "$CURRENT_DIR"
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
# Expand ~ to home directory
|
|
30
|
+
if ($EXTRACT_PATH.StartsWith("~")) {
|
|
31
|
+
$EXTRACT_PATH = $EXTRACT_PATH -replace "^~", $HOME
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
$SKIP_DOWNLOAD = $false
|
|
35
|
+
|
|
36
|
+
# Check if directory exists, create if not
|
|
37
|
+
if (-not (Test-Path $EXTRACT_PATH -PathType Container)) {
|
|
38
|
+
Write-Host " ${GRAY}creating directory...${NC}"
|
|
39
|
+
try {
|
|
40
|
+
New-Item -ItemType Directory -Path $EXTRACT_PATH -Force | Out-Null
|
|
41
|
+
} catch {
|
|
42
|
+
Write-Host " ${RED}✗${NC} failed to create directory: ${EXTRACT_PATH}"
|
|
43
|
+
Write-Host " ${GRAY}skipping example download.${NC}"
|
|
44
|
+
$SKIP_DOWNLOAD = $true
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if (-not $SKIP_DOWNLOAD) {
|
|
49
|
+
Write-Host " ${GRAY}downloading examples...${NC}"
|
|
50
|
+
|
|
51
|
+
$TEMP_ZIP = Join-Path ([System.IO.Path]::GetTempPath()) "plainlang-examples.zip"
|
|
52
|
+
|
|
53
|
+
try {
|
|
54
|
+
Invoke-WebRequest -Uri $EXAMPLES_DOWNLOAD_URL -OutFile $TEMP_ZIP -UseBasicParsing
|
|
55
|
+
|
|
56
|
+
if (Test-Path $TEMP_ZIP) {
|
|
57
|
+
Write-Host " ${GRAY}extracting to ${EXTRACT_PATH}...${NC}"
|
|
58
|
+
|
|
59
|
+
try {
|
|
60
|
+
Expand-Archive -Path $TEMP_ZIP -DestinationPath $EXTRACT_PATH -Force
|
|
61
|
+
|
|
62
|
+
# Find and rename extracted directory to remove version number
|
|
63
|
+
$EXTRACTED_DIR = Join-Path $EXTRACT_PATH $EXAMPLES_FOLDER_NAME
|
|
64
|
+
$VERSIONED_DIR = Get-ChildItem -Path $EXTRACT_PATH -Directory -Filter "${EXAMPLES_FOLDER_NAME}-*" | Select-Object -First 1
|
|
65
|
+
|
|
66
|
+
if ($VERSIONED_DIR) {
|
|
67
|
+
if (Test-Path $EXTRACTED_DIR) {
|
|
68
|
+
Remove-Item -Path $EXTRACTED_DIR -Recurse -Force -ErrorAction SilentlyContinue
|
|
69
|
+
}
|
|
70
|
+
Rename-Item -Path $VERSIONED_DIR.FullName -NewName $EXAMPLES_FOLDER_NAME
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
# Remove the .gitignore file from the root of the extracted directory
|
|
74
|
+
$GITIGNORE_PATH = Join-Path $EXTRACTED_DIR ".gitignore"
|
|
75
|
+
if (Test-Path $GITIGNORE_PATH) {
|
|
76
|
+
Remove-Item -Path $GITIGNORE_PATH -Force
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
Write-Host ""
|
|
80
|
+
Write-Host " ${GREEN}✓${NC} examples downloaded successfully!"
|
|
81
|
+
Write-Host ""
|
|
82
|
+
Write-Host " examples are in: ${YELLOW}${EXTRACTED_DIR}${NC}"
|
|
83
|
+
Write-Host ""
|
|
84
|
+
} catch {
|
|
85
|
+
Write-Host " ${RED}✗${NC} failed to extract examples."
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
Remove-Item -Path $TEMP_ZIP -Force -ErrorAction SilentlyContinue
|
|
89
|
+
} else {
|
|
90
|
+
Write-Host " ${RED}✗${NC} failed to download examples."
|
|
91
|
+
}
|
|
92
|
+
} catch {
|
|
93
|
+
Write-Host " ${RED}✗${NC} failed to download examples."
|
|
94
|
+
Remove-Item -Path $TEMP_ZIP -Force -ErrorAction SilentlyContinue
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
Write-Host ""
|
|
98
|
+
Read-Host " press [Enter] to continue..."
|
|
99
|
+
}
|