codeplain 0.3.1__tar.gz → 0.3.2__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.3.1 → codeplain-0.3.2}/.claude/settings.json +5 -0
- codeplain-0.3.2/.zed/settings.json +46 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/PKG-INFO +20 -24
- {codeplain-0.3.1 → codeplain-0.3.2}/README.md +18 -22
- codeplain-0.3.2/_version.py +1 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/cli_output/render_summary.py +6 -1
- {codeplain-0.3.1 → codeplain-0.3.2}/codeplain_REST_api.py +1 -1
- {codeplain-0.3.1 → codeplain-0.3.2}/concept_utils.py +0 -1
- {codeplain-0.3.1 → codeplain-0.3.2}/examples/example_hello_world_python/hello_world_python.plain +3 -3
- codeplain-0.3.2/examples/example_hello_world_python/text.txt +1 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/file_utils.py +18 -62
- {codeplain-0.3.1 → codeplain-0.3.2}/plain2code.py +7 -3
- {codeplain-0.3.1 → codeplain-0.3.2}/plain2code_exceptions.py +6 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/plain2code_state.py +4 -7
- codeplain-0.3.2/plain2code_utils.py +22 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/plain_file.py +6 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/plain_modules.py +6 -2
- {codeplain-0.3.1 → codeplain-0.3.2}/pyproject.toml +1 -1
- {codeplain-0.3.1 → codeplain-0.3.2}/render_machine/actions/run_conformance_tests.py +4 -2
- {codeplain-0.3.1 → codeplain-0.3.2}/render_machine/actions/run_unit_tests.py +2 -2
- {codeplain-0.3.1 → codeplain-0.3.2}/render_machine/render_context.py +7 -2
- {codeplain-0.3.1 → codeplain-0.3.2}/render_machine/render_types.py +0 -10
- {codeplain-0.3.1 → codeplain-0.3.2}/system_config.py +0 -6
- codeplain-0.3.2/tests/data/plainfile/add_new_task_modal_specification.yaml +1 -0
- codeplain-0.3.2/tests/data/plainfile/task_list_ui_specification.yaml +1 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/tests/data/plainfile/task_manager_with_reference_links.plain +3 -3
- {codeplain-0.3.1 → codeplain-0.3.2}/tests/test_cli_output.py +9 -13
- {codeplain-0.3.1 → codeplain-0.3.2}/tests/test_plainfileparser.py +4 -4
- {codeplain-0.3.1 → codeplain-0.3.2}/tui/components.py +0 -6
- {codeplain-0.3.1 → codeplain-0.3.2}/tui/plain2code_tui.py +4 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/tui/plain_module_render_choice_tui.py +9 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/tui/styles.css +1 -1
- {codeplain-0.3.1 → codeplain-0.3.2}/tui/widget_helpers.py +0 -18
- codeplain-0.3.1/_version.py +0 -1
- codeplain-0.3.1/hash_key.py +0 -29
- codeplain-0.3.1/plain2code_utils.py +0 -56
- codeplain-0.3.1/render_machine/conformance_test_helpers.py +0 -68
- {codeplain-0.3.1 → codeplain-0.3.2}/.claude/settings.local.json +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/.flake8 +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/.github/dependabot.yml +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/.github/workflows/e2e.yml +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/.github/workflows/lint-and-test.yml +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/.github/workflows/nofity-slack-on-main-merge.yml +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/.github/workflows/publish-install-script.yml +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/.github/workflows/publish-to-pypi.yml +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/.gitignore +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/.vscode/launch.json +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/.vscode/settings.json +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/CLAUDE.md +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/LICENSE +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/cli_output/__init__.py +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/cli_output/dry_run.py +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/cli_output/status.py +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/config/__init__.py +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/config/system_config.yaml +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/diff_utils.py +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/docs/generate_cli.py +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/docs/plain2code_cli.md +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/docs/starting_a_plain_project_from_scratch.md +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/event_bus.py +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/examples/example_hello_world_golang/config.yaml +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/examples/example_hello_world_golang/harness_tests/hello_world_test.go +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/examples/example_hello_world_golang/hello_world_golang.plain +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/examples/example_hello_world_golang/run.sh +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/examples/example_hello_world_python/config.yaml +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/examples/example_hello_world_python/harness_tests/hello_world_display/test_hello_world.py +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/examples/example_hello_world_python/run.sh +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/examples/example_hello_world_react/config.yaml +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/examples/example_hello_world_react/harness_tests/hello_world_display/cypress/e2e/hello_world.cy.ts +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/examples/example_hello_world_react/harness_tests/hello_world_display/cypress/support/e2e.ts +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/examples/example_hello_world_react/harness_tests/hello_world_display/cypress.config.ts +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/examples/example_hello_world_react/harness_tests/hello_world_display/package.json +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/examples/example_hello_world_react/harness_tests/hello_world_display/tsconfig.json +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/examples/example_hello_world_react/hello_world_react.plain +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/examples/example_hello_world_react/run.sh +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/examples/run.sh +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/git_utils.py +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/install/bash/examples.sh +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/install/bash/install.sh +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/install/bash/walkthrough.sh +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/install/powershell/examples.ps1 +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/install/powershell/install.ps1 +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/install/powershell/walkthrough.ps1 +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/memory_management.py +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/module_renderer.py +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/partial_rendering.py +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/plain2code_arguments.py +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/plain2code_console.py +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/plain2code_events.py +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/plain2code_logger.py +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/plain2code_nodes.py +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/plain2code_read_config.py +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/plain_spec.py +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/pytest.ini +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/render_machine/__init__.py +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/render_machine/actions/analyze_specification_ambiguity.py +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/render_machine/actions/base_action.py +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/render_machine/actions/commit_conformance_tests_changes.py +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/render_machine/actions/commit_implementation_code_changes.py +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/render_machine/actions/create_dist.py +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/render_machine/actions/exit_with_error.py +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/render_machine/actions/finish_functional_requirement.py +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/render_machine/actions/fix_conformance_test.py +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/render_machine/actions/fix_unit_tests.py +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/render_machine/actions/prepare_repositories.py +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/render_machine/actions/prepare_testing_environment.py +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/render_machine/actions/refactor_code.py +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/render_machine/actions/render_conformance_tests.py +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/render_machine/actions/render_functional_requirement.py +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/render_machine/actions/summarize_conformance_tests.py +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/render_machine/code_renderer.py +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/render_machine/conformance_tests.py +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/render_machine/implementation_code_helpers.py +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/render_machine/render_utils.py +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/render_machine/state_machine_config.py +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/render_machine/states.py +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/render_machine/triggers.py +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/requirements.txt +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/resources/codeplain_overview.png +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/resources/plain_example.png +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/standard_template_library/__init__.py +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/standard_template_library/golang-console-app-template.plain +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/standard_template_library/python-console-app-template.plain +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/standard_template_library/typescript-react-app-boilerplate.plain +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/standard_template_library/typescript-react-app-template.plain +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/test_scripts/run_conformance_tests_cypress.ps1 +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/test_scripts/run_conformance_tests_cypress.sh +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/test_scripts/run_conformance_tests_golang.ps1 +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/test_scripts/run_conformance_tests_golang.sh +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/test_scripts/run_conformance_tests_python.ps1 +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/test_scripts/run_conformance_tests_python.sh +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/test_scripts/run_unittests_flutter.ps1 +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/test_scripts/run_unittests_golang.ps1 +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/test_scripts/run_unittests_golang.sh +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/test_scripts/run_unittests_python.ps1 +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/test_scripts/run_unittests_python.sh +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/test_scripts/run_unittests_react.ps1 +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/test_scripts/run_unittests_react.sh +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/tests/__init__.py +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/tests/conftest.py +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/tests/data/imports/circular_imports_1.plain +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/tests/data/imports/circular_imports_2.plain +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/tests/data/imports/circular_imports_main.plain +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/tests/data/imports/diamond_import_1.plain +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/tests/data/imports/diamond_import_2.plain +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/tests/data/imports/diamond_import_common.plain +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/tests/data/imports/diamond_imports_main.plain +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/tests/data/imports/non_existent_import.plain +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/tests/data/partial_rendering/pr_leaf.plain +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/tests/data/partial_rendering/pr_middle.plain +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/tests/data/partial_rendering/pr_root.plain +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/tests/data/partial_rendering/pr_solo.plain +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/tests/data/plainfile/duplicate_specification_heading.plain +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/tests/data/plainfile/invalid_specification_order.plain +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/tests/data/plainfile/missing_non_functional_requirements.plain +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/tests/data/plainfile/plain_source_with_absolute_link.plain +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/tests/data/plainfile/plain_source_with_url_link.plain +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/tests/data/plainfile/without_non_functional_requirement.plain +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/tests/data/plainfileparser/concept_validation_acceptance_tests.plain +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/tests/data/plainfileparser/concept_validation_acceptance_tests_nondefined.plain +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/tests/data/plainfileparser/concept_validation_defined_nondefined.plain +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/tests/data/plainfileparser/concept_validation_defined_nondefined_2.plain +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/tests/data/plainfileparser/concept_validation_definition.plain +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/tests/data/plainfileparser/concept_validation_noconcepts.plain +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/tests/data/plainfileparser/concept_validation_nonconcept.plain +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/tests/data/plainfileparser/concept_validation_nondefined.plain +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/tests/data/plainfileparser/concept_validation_redefinition.plain +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/tests/data/plainfileparser/concept_validation_several_concepts.plain +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/tests/data/plainfileparser/concept_validation_valid.plain +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/tests/data/plainfileparser/exported_concepts.plain +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/tests/data/plainfileparser/exported_concepts_base.plain +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/tests/data/plainfileparser/exported_concepts_example.plain +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/tests/data/plainfileparser/exported_concepts_missing.plain +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/tests/data/plainfileparser/exported_concepts_missing_example.plain +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/tests/data/plainfileparser/exported_concepts_nested.plain +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/tests/data/plainfileparser/exported_concepts_nested_example.plain +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/tests/data/plainfileparser/exported_concepts_transitive_example.plain +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/tests/data/plainfileparser/exported_concepts_transitive_l1.plain +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/tests/data/plainfileparser/exported_concepts_transitive_l2.plain +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/tests/data/plainfileparser/plain_file_parser_with_comments.plain +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/tests/data/plainfileparser/plain_file_with_comments_indented.plain +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/tests/data/plainfileparser/regular_plain_source.plain +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/tests/data/plainfileparser/required_concepts.plain +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/tests/data/plainfileparser/required_concepts_defs.plain +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/tests/data/plainfileparser/required_concepts_example.plain +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/tests/data/plainfileparser/required_concepts_l1.plain +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/tests/data/plainfileparser/required_concepts_l2.plain +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/tests/data/plainfileparser/required_concepts_missing.plain +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/tests/data/plainfileparser/required_concepts_module.plain +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/tests/data/plainfileparser/required_concepts_partial.plain +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/tests/data/plainfileparser/required_concepts_partial_duplicate.plain +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/tests/data/plainfileparser/topological_sort.plain +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/tests/data/plainfileparser/topological_sort_not_referenced.plain +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/tests/data/requires/circular_requires_main.plain +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/tests/data/requires/circular_requires_sub.plain +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/tests/data/requires/diamond_requires_1.plain +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/tests/data/requires/diamond_requires_2.plain +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/tests/data/requires/diamond_requires_common.plain +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/tests/data/requires/diamond_requires_main.plain +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/tests/data/requires/independent_requires_1.plain +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/tests/data/requires/independent_requires_2.plain +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/tests/data/requires/independent_requires_main.plain +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/tests/data/requires/non_existent_require.plain +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/tests/data/requires/normal_requires_1.plain +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/tests/data/requires/normal_requires_2.plain +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/tests/data/requires/normal_requires_common.plain +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/tests/data/requires/normal_requires_main.plain +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/tests/data/simple.plain +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/tests/data/templates/block_level_include.plain +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/tests/data/templates/code_variables.plain +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/tests/data/templates/header.plain +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/tests/data/templates/implement.plain +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/tests/data/templates/implement_2.plain +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/tests/data/templates/template_include.plain +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/tests/data/templates/test_hardest_problem.plain +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/tests/e2e/Dockerfile +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/tests/e2e/conftest.py +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/tests/e2e/test_hello_world_python.py +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/tests/e2e/test_hello_world_python_windows.py +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/tests/test_file_utils.py +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/tests/test_git_utils.py +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/tests/test_imports.py +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/tests/test_partial_rendering.py +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/tests/test_plain_modules.py +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/tests/test_plainfile.py +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/tests/test_plainspec.py +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/tests/test_requires.py +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/tests/test_resolve_config_file.py +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/tui/__init__.py +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/tui/models.py +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/tui/spinner.py +0 -0
- {codeplain-0.3.1 → codeplain-0.3.2}/tui/state_handlers.py +0 -0
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
// Zed project-local settings, converted from .vscode/settings.json.
|
|
2
|
+
// Docs: https://zed.dev/docs/configuring-zed
|
|
3
|
+
{
|
|
4
|
+
"format_on_save": "on",
|
|
5
|
+
"languages": {
|
|
6
|
+
"Python": {
|
|
7
|
+
"tab_size": 4,
|
|
8
|
+
"hard_tabs": false,
|
|
9
|
+
"preferred_line_length": 120,
|
|
10
|
+
"wrap_guides": [120],
|
|
11
|
+
"format_on_save": "on",
|
|
12
|
+
// Run isort first (organize imports), then black (format).
|
|
13
|
+
// Matches `source.organizeImports: explicit` + black-formatter from VS Code.
|
|
14
|
+
"formatter": [
|
|
15
|
+
{
|
|
16
|
+
"external": {
|
|
17
|
+
"command": "isort",
|
|
18
|
+
"arguments": ["--profile", "black", "--filename", "{buffer_path}", "-"]
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
"external": {
|
|
23
|
+
"command": "black",
|
|
24
|
+
"arguments": ["--quiet", "--stdin-filename", "{buffer_path}", "-"]
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
]
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
// Treat fixture files under tests/data as plain text (matches files.associations).
|
|
31
|
+
"file_types": {
|
|
32
|
+
"Plain Text": ["tests/data/**"]
|
|
33
|
+
},
|
|
34
|
+
// python.analysis.extraPaths -> Pyright (Zed's default Python LSP).
|
|
35
|
+
"lsp": {
|
|
36
|
+
"pyright": {
|
|
37
|
+
"settings": {
|
|
38
|
+
"python": {
|
|
39
|
+
"analysis": {
|
|
40
|
+
"extraPaths": ["."]
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: codeplain
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.2
|
|
4
4
|
Summary: Transform plain language specifications into working code
|
|
5
5
|
License-File: LICENSE
|
|
6
6
|
Classifier: Environment :: Console
|
|
7
7
|
Classifier: Intended Audience :: Developers
|
|
8
8
|
Classifier: Operating System :: OS Independent
|
|
9
9
|
Classifier: Topic :: Software Development :: Code Generators
|
|
10
|
-
Requires-Python:
|
|
10
|
+
Requires-Python: >=3.11
|
|
11
11
|
Requires-Dist: gitpython==3.1.50
|
|
12
12
|
Requires-Dist: mistletoe==1.3.0
|
|
13
13
|
Requires-Dist: networkx==3.6.1
|
|
@@ -29,31 +29,28 @@ Description-Content-Type: text/markdown
|
|
|
29
29
|
|
|
30
30
|
# Codeplain plain2code renderer
|
|
31
31
|
|
|
32
|
-
Render
|
|
32
|
+
Render \*\*\*plain source to software code using the Codeplain API.
|
|
33
33
|
|
|
34
34
|
## Codeplain.ai - Code Generation as a Service
|
|
35
35
|
|
|
36
|
-
Codeplain is a platform that generates software code using large language models based on requirements you specify in
|
|
36
|
+
Codeplain is a platform that generates software code using large language models based on requirements you specify in \*\*\*plain specification language.
|
|
37
37
|
|
|
38
38
|
Schematic overview of the Codeplain's code generation service
|
|
39
39
|
|
|
40
40
|
<img src="https://raw.githubusercontent.com/Codeplain-ai/plain2code_client/main/resources/codeplain_overview.png">
|
|
41
41
|
|
|
42
|
-
### Abstracting Away Code Generation Complexity with
|
|
42
|
+
### Abstracting Away Code Generation Complexity with \*\*\*plain
|
|
43
43
|
|
|
44
|
+
\*\*\*plain is a novel specification language that helps abstracting away complexity of using large language models for code generation.
|
|
44
45
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
An example application in ***plain
|
|
46
|
+
An example application in \*\*\*plain
|
|
48
47
|
|
|
49
48
|
<img src="resources/plain_example.png" width="70%" height="70%">
|
|
50
49
|
|
|
51
|
-
|
|
52
50
|
## Getting started
|
|
53
51
|
|
|
54
52
|
### Prerequisites
|
|
55
53
|
|
|
56
|
-
|
|
57
54
|
#### System requirements
|
|
58
55
|
|
|
59
56
|
To run the plain2code client, you need Python 3.11 or a later version.
|
|
@@ -92,18 +89,19 @@ export CODEPLAIN_API_KEY="your_actual_api_key_here"
|
|
|
92
89
|
After completing the installation steps above, you can immediately test the system with a simple "Hello World" example:
|
|
93
90
|
|
|
94
91
|
- Change to the example folder and run the example:
|
|
95
|
-
```
|
|
96
|
-
cd examples/example_hello_world_python
|
|
97
|
-
python ../../plain2code.py hello_world_python.plain
|
|
98
|
-
```
|
|
99
92
|
|
|
100
|
-
|
|
93
|
+
```
|
|
94
|
+
cd examples/example_hello_world_python
|
|
95
|
+
python ../../plain2code.py hello_world_python.plain
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
_Note: Rendering will take a few minutes to complete._
|
|
101
99
|
|
|
102
100
|
- The system will generate a Python application in the `build` directory. You can run it with:
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
101
|
+
```
|
|
102
|
+
cd build
|
|
103
|
+
python hello_world.py
|
|
104
|
+
```
|
|
107
105
|
|
|
108
106
|
## Releasing
|
|
109
107
|
|
|
@@ -112,7 +110,7 @@ Releases are built and published with [uv](https://docs.astral.sh/uv/). The vers
|
|
|
112
110
|
1. Bump the version in `_version.py` and commit/tag (`git tag v<version>`).
|
|
113
111
|
2. Build the distributions:
|
|
114
112
|
```bash
|
|
115
|
-
uv build
|
|
113
|
+
uv build --python 3.11
|
|
116
114
|
```
|
|
117
115
|
This produces `dist/codeplain-<version>-py3-none-any.whl` and `dist/codeplain-<version>.tar.gz`.
|
|
118
116
|
3. (Optional) Smoke-test the wheel:
|
|
@@ -135,13 +133,11 @@ Releases are built and published with [uv](https://docs.astral.sh/uv/). The vers
|
|
|
135
133
|
### Examples and Sample Projects
|
|
136
134
|
|
|
137
135
|
- See the [examples](examples) folder for sample projects in Golang, Python, and React.
|
|
138
|
-
- For example application how to implement task manager in
|
|
139
|
-
- For example application how to implement SaaS connectors in
|
|
136
|
+
- For example application how to implement task manager in \*\*\*plain see [example-task-manager](https://github.com/Codeplain-ai/example-task-manager) repository.
|
|
137
|
+
- For example application how to implement SaaS connectors in \*\*\*plain see [example-saas-connectors](https://github.com/Codeplain-ai/example-saas-connectors) repository.
|
|
140
138
|
|
|
141
139
|
### Documentation
|
|
142
140
|
|
|
143
141
|
- For more details on the ***plain format, see the [***plain language specification](https://www.plainlang.org/docs/).
|
|
144
142
|
- For step-by-step instructions for creating your first ***plain project see the [Kickstart your ***plain project](docs/starting_a_plain_project_from_scratch.md).
|
|
145
143
|
- For complete CLI documentation and usage examples, see [plain2code CLI documentation](docs/plain2code_cli.md).
|
|
146
|
-
|
|
147
|
-
|
|
@@ -1,30 +1,27 @@
|
|
|
1
1
|
# Codeplain plain2code renderer
|
|
2
2
|
|
|
3
|
-
Render
|
|
3
|
+
Render \*\*\*plain source to software code using the Codeplain API.
|
|
4
4
|
|
|
5
5
|
## Codeplain.ai - Code Generation as a Service
|
|
6
6
|
|
|
7
|
-
Codeplain is a platform that generates software code using large language models based on requirements you specify in
|
|
7
|
+
Codeplain is a platform that generates software code using large language models based on requirements you specify in \*\*\*plain specification language.
|
|
8
8
|
|
|
9
9
|
Schematic overview of the Codeplain's code generation service
|
|
10
10
|
|
|
11
11
|
<img src="https://raw.githubusercontent.com/Codeplain-ai/plain2code_client/main/resources/codeplain_overview.png">
|
|
12
12
|
|
|
13
|
-
### Abstracting Away Code Generation Complexity with
|
|
13
|
+
### Abstracting Away Code Generation Complexity with \*\*\*plain
|
|
14
14
|
|
|
15
|
+
\*\*\*plain is a novel specification language that helps abstracting away complexity of using large language models for code generation.
|
|
15
16
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
An example application in ***plain
|
|
17
|
+
An example application in \*\*\*plain
|
|
19
18
|
|
|
20
19
|
<img src="resources/plain_example.png" width="70%" height="70%">
|
|
21
20
|
|
|
22
|
-
|
|
23
21
|
## Getting started
|
|
24
22
|
|
|
25
23
|
### Prerequisites
|
|
26
24
|
|
|
27
|
-
|
|
28
25
|
#### System requirements
|
|
29
26
|
|
|
30
27
|
To run the plain2code client, you need Python 3.11 or a later version.
|
|
@@ -63,18 +60,19 @@ export CODEPLAIN_API_KEY="your_actual_api_key_here"
|
|
|
63
60
|
After completing the installation steps above, you can immediately test the system with a simple "Hello World" example:
|
|
64
61
|
|
|
65
62
|
- Change to the example folder and run the example:
|
|
66
|
-
```
|
|
67
|
-
cd examples/example_hello_world_python
|
|
68
|
-
python ../../plain2code.py hello_world_python.plain
|
|
69
|
-
```
|
|
70
63
|
|
|
71
|
-
|
|
64
|
+
```
|
|
65
|
+
cd examples/example_hello_world_python
|
|
66
|
+
python ../../plain2code.py hello_world_python.plain
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
_Note: Rendering will take a few minutes to complete._
|
|
72
70
|
|
|
73
71
|
- The system will generate a Python application in the `build` directory. You can run it with:
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
72
|
+
```
|
|
73
|
+
cd build
|
|
74
|
+
python hello_world.py
|
|
75
|
+
```
|
|
78
76
|
|
|
79
77
|
## Releasing
|
|
80
78
|
|
|
@@ -83,7 +81,7 @@ Releases are built and published with [uv](https://docs.astral.sh/uv/). The vers
|
|
|
83
81
|
1. Bump the version in `_version.py` and commit/tag (`git tag v<version>`).
|
|
84
82
|
2. Build the distributions:
|
|
85
83
|
```bash
|
|
86
|
-
uv build
|
|
84
|
+
uv build --python 3.11
|
|
87
85
|
```
|
|
88
86
|
This produces `dist/codeplain-<version>-py3-none-any.whl` and `dist/codeplain-<version>.tar.gz`.
|
|
89
87
|
3. (Optional) Smoke-test the wheel:
|
|
@@ -106,13 +104,11 @@ Releases are built and published with [uv](https://docs.astral.sh/uv/). The vers
|
|
|
106
104
|
### Examples and Sample Projects
|
|
107
105
|
|
|
108
106
|
- See the [examples](examples) folder for sample projects in Golang, Python, and React.
|
|
109
|
-
- For example application how to implement task manager in
|
|
110
|
-
- For example application how to implement SaaS connectors in
|
|
107
|
+
- For example application how to implement task manager in \*\*\*plain see [example-task-manager](https://github.com/Codeplain-ai/example-task-manager) repository.
|
|
108
|
+
- For example application how to implement SaaS connectors in \*\*\*plain see [example-saas-connectors](https://github.com/Codeplain-ai/example-saas-connectors) repository.
|
|
111
109
|
|
|
112
110
|
### Documentation
|
|
113
111
|
|
|
114
112
|
- For more details on the ***plain format, see the [***plain language specification](https://www.plainlang.org/docs/).
|
|
115
113
|
- For step-by-step instructions for creating your first ***plain project see the [Kickstart your ***plain project](docs/starting_a_plain_project_from_scratch.md).
|
|
116
114
|
- For complete CLI documentation and usage examples, see [plain2code CLI documentation](docs/plain2code_cli.md).
|
|
117
|
-
|
|
118
|
-
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.3.2"
|
|
@@ -15,7 +15,12 @@ def print_exit_summary(
|
|
|
15
15
|
"""Print render outcome after the TUI exits (terminal restored)."""
|
|
16
16
|
console.quiet = False
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
if run_state.render_succeeded:
|
|
19
|
+
msg = "\n[#79FC96]✓ rendering completed\n\n"
|
|
20
|
+
elif run_state.render_cancelled:
|
|
21
|
+
msg = "\n[#FFFFFF]— rendering canceled\n\n"
|
|
22
|
+
else:
|
|
23
|
+
msg = "\n[#FF6B6B]✗ rendering failed\n\n"
|
|
19
24
|
msg += f" [#8E8F91]render id:\t\t\t[#FFFFFF]{run_state.render_id}\n"
|
|
20
25
|
msg += f" [#8E8F91]input file:\t\t\t[#FFFFFF]{spec_filename}\n"
|
|
21
26
|
msg += f" [#8E8F91]generated code folder:\t[#FFFFFF]{run_state.render_generated_code_path or '-'}\n\n"
|
|
@@ -108,7 +108,7 @@ class CodeplainAPI:
|
|
|
108
108
|
if error_code == "InternalServerError":
|
|
109
109
|
raise plain2code_exceptions.InternalServerError(
|
|
110
110
|
"Internal server error.\n\n"
|
|
111
|
-
|
|
111
|
+
"Please report the error to support@codeplain.ai with the attached .log file."
|
|
112
112
|
)
|
|
113
113
|
exception_class = ERROR_CODE_EXCEPTIONS[error_code]
|
|
114
114
|
raise exception_class(message)
|
{codeplain-0.3.1 → codeplain-0.3.2}/examples/example_hello_world_python/hello_world_python.plain
RENAMED
|
@@ -13,7 +13,7 @@ import:
|
|
|
13
13
|
- Display "hello, world"
|
|
14
14
|
|
|
15
15
|
***acceptance tests***
|
|
16
|
-
|
|
17
|
-
- :App: should exit with status code 0 indicating successful execution.
|
|
18
16
|
|
|
19
|
-
- :App: should
|
|
17
|
+
- :App: should exit with status code 0 indicating successful execution [adsa](asdsa).
|
|
18
|
+
|
|
19
|
+
- :App: should complete execution in under 1 second.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
hello
|
|
@@ -54,15 +54,6 @@ def is_system_folder_path(file_path: str) -> bool:
|
|
|
54
54
|
return bool(parts) and parts[0] in SYSTEM_FOLDERS
|
|
55
55
|
|
|
56
56
|
|
|
57
|
-
def get_file_type(file_name):
|
|
58
|
-
|
|
59
|
-
# Extract the file extension
|
|
60
|
-
ext = Path(file_name).suffix.lower() # Convert to lowercase to handle case-insensitive matching
|
|
61
|
-
|
|
62
|
-
# Use the dictionary to get the file type, defaulting to 'unknown' if the extension is not found
|
|
63
|
-
return FILE_EXTENSION_MAPPING.get(ext, "unknown")
|
|
64
|
-
|
|
65
|
-
|
|
66
57
|
def list_all_text_files(directory):
|
|
67
58
|
all_files = []
|
|
68
59
|
for root, dirs, files in os.walk(directory, topdown=True):
|
|
@@ -99,64 +90,29 @@ def list_folders_in_directory(directory):
|
|
|
99
90
|
return folders
|
|
100
91
|
|
|
101
92
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
delete_files_and_subfolders(folder_name)
|
|
107
|
-
_make_writable(folder_name)
|
|
108
|
-
os.rmdir(folder_name)
|
|
93
|
+
def _on_rm_error(func, path, _exc_info):
|
|
94
|
+
"""On Windows, clear read-only flag and retry the removal."""
|
|
95
|
+
os.chmod(path, stat.S_IWRITE)
|
|
96
|
+
func(path)
|
|
109
97
|
|
|
110
98
|
|
|
111
|
-
def
|
|
112
|
-
"""
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
if is_windows:
|
|
116
|
-
try:
|
|
117
|
-
mode = os.stat(path).st_mode
|
|
118
|
-
os.chmod(path, mode | stat.S_IWRITE)
|
|
119
|
-
except OSError:
|
|
120
|
-
pass
|
|
99
|
+
def delete_folder(folder_name):
|
|
100
|
+
"""Delete a folder and all its subfolders and files."""
|
|
101
|
+
if os.path.exists(folder_name):
|
|
102
|
+
shutil.rmtree(folder_name, onerror=_on_rm_error)
|
|
121
103
|
|
|
122
104
|
|
|
123
105
|
def delete_files_and_subfolders(directory):
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
total_files_deleted += 1
|
|
135
|
-
|
|
136
|
-
# Delete directories
|
|
137
|
-
for dir_ in dirs:
|
|
138
|
-
dir_path = os.path.join(root, dir_)
|
|
139
|
-
_make_writable(dir_path)
|
|
140
|
-
os.rmdir(dir_path)
|
|
141
|
-
total_folders_deleted += 1
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
def copy_file(source_path, destination_path):
|
|
145
|
-
# Ensure the destination directory exists
|
|
146
|
-
os.makedirs(os.path.dirname(destination_path), exist_ok=True)
|
|
147
|
-
|
|
148
|
-
# Open the source file in read-binary ('rb') mode
|
|
149
|
-
with open(source_path, "rb") as source_file:
|
|
150
|
-
# Open the destination file in write-binary ('wb') mode
|
|
151
|
-
with open(destination_path, "wb") as destination_file:
|
|
152
|
-
# Copy the content from source to destination
|
|
153
|
-
while True:
|
|
154
|
-
# Read a chunk of the source file
|
|
155
|
-
chunk = source_file.read(4096) # Reading in chunks of 4KB
|
|
156
|
-
if not chunk:
|
|
157
|
-
break # End of file reached
|
|
158
|
-
# Write the chunk to the destination file
|
|
159
|
-
destination_file.write(chunk)
|
|
106
|
+
"""Delete all contents of a directory but keep the directory itself."""
|
|
107
|
+
for entry in os.scandir(directory):
|
|
108
|
+
if entry.is_dir(follow_symlinks=False):
|
|
109
|
+
shutil.rmtree(entry.path, onerror=_on_rm_error)
|
|
110
|
+
else:
|
|
111
|
+
try:
|
|
112
|
+
os.remove(entry.path)
|
|
113
|
+
except PermissionError:
|
|
114
|
+
os.chmod(entry.path, stat.S_IWRITE)
|
|
115
|
+
os.remove(entry.path)
|
|
160
116
|
|
|
161
117
|
|
|
162
118
|
def add_current_path_if_no_path(filename):
|
|
@@ -25,6 +25,7 @@ from plain2code_console import console
|
|
|
25
25
|
from plain2code_events import RenderFailed
|
|
26
26
|
from plain2code_exceptions import (
|
|
27
27
|
ConflictingRequirements,
|
|
28
|
+
GitNotInstalledError,
|
|
28
29
|
InvalidAPIKey,
|
|
29
30
|
InvalidFridArgument,
|
|
30
31
|
MissingAPIKey,
|
|
@@ -181,6 +182,7 @@ def render(args, run_state: RunState, event_bus: EventBus, default_log_level: st
|
|
|
181
182
|
render_choices,
|
|
182
183
|
system_config.client_version,
|
|
183
184
|
run_state.render_id,
|
|
185
|
+
on_cancel=run_state.set_render_cancelled,
|
|
184
186
|
css_path="styles.css",
|
|
185
187
|
)
|
|
186
188
|
render_choice = app.run()
|
|
@@ -189,6 +191,7 @@ def render(args, run_state: RunState, event_bus: EventBus, default_log_level: st
|
|
|
189
191
|
and render_choice.render_range is None
|
|
190
192
|
and render_choice.choice_type == "quit"
|
|
191
193
|
):
|
|
194
|
+
run_state.set_render_cancelled()
|
|
192
195
|
sys.exit(0)
|
|
193
196
|
elif ask_user and args.headless:
|
|
194
197
|
# ignore the default choice if it requires user input due to headless mode
|
|
@@ -217,7 +220,7 @@ def render(args, run_state: RunState, event_bus: EventBus, default_log_level: st
|
|
|
217
220
|
try:
|
|
218
221
|
module_renderer.render_module()
|
|
219
222
|
except RenderCancelledError:
|
|
220
|
-
|
|
223
|
+
run_state.set_render_cancelled() # TUI already closed, nothing to report
|
|
221
224
|
except Exception as e:
|
|
222
225
|
run_state.set_render_succeeded(False)
|
|
223
226
|
render_error.append(e)
|
|
@@ -228,8 +231,7 @@ def render(args, run_state: RunState, event_bus: EventBus, default_log_level: st
|
|
|
228
231
|
try:
|
|
229
232
|
module_renderer.render_module()
|
|
230
233
|
except RenderCancelledError:
|
|
231
|
-
run_state.
|
|
232
|
-
pass
|
|
234
|
+
run_state.set_render_cancelled()
|
|
233
235
|
return
|
|
234
236
|
else:
|
|
235
237
|
render_thread = threading.Thread(target=run_render, daemon=True)
|
|
@@ -242,6 +244,7 @@ def render(args, run_state: RunState, event_bus: EventBus, default_log_level: st
|
|
|
242
244
|
prepare_environment_script=args.prepare_environment_script,
|
|
243
245
|
state_machine_version=system_config.client_version,
|
|
244
246
|
enter_pause_event=enter_pause_event,
|
|
247
|
+
on_cancel=run_state.set_render_cancelled,
|
|
245
248
|
default_log_level=default_log_level,
|
|
246
249
|
css_path="styles.css",
|
|
247
250
|
)
|
|
@@ -354,6 +357,7 @@ def main(): # noqa: C901
|
|
|
354
357
|
NetworkConnectionError,
|
|
355
358
|
ModuleDoesNotExistError,
|
|
356
359
|
UnsupportedResourceType,
|
|
360
|
+
GitNotInstalledError,
|
|
357
361
|
),
|
|
358
362
|
):
|
|
359
363
|
exc_info = sys.exc_info()
|
|
@@ -11,6 +11,7 @@ class RunState:
|
|
|
11
11
|
def __init__(self, spec_filename: str, replay_with: Optional[str] = None):
|
|
12
12
|
self.replay: bool = replay_with is not None
|
|
13
13
|
self.render_succeeded: bool = False
|
|
14
|
+
self.render_cancelled: bool = False
|
|
14
15
|
self.render_generated_code_path: Optional[str] = None
|
|
15
16
|
self.rendered_functionalities: int = 0
|
|
16
17
|
if replay_with:
|
|
@@ -20,7 +21,6 @@ class RunState:
|
|
|
20
21
|
self.spec_filename: str = spec_filename
|
|
21
22
|
self.call_count: int = 0
|
|
22
23
|
self.unittest_batch_id: int = 0
|
|
23
|
-
self.frid_render_anaysis: dict[str, str] = {}
|
|
24
24
|
self.render_time_accumulated: int = 0
|
|
25
25
|
self.last_render_start_timestamp: float = time.monotonic()
|
|
26
26
|
|
|
@@ -30,12 +30,12 @@ class RunState:
|
|
|
30
30
|
def increment_unittest_batch_id(self):
|
|
31
31
|
self.unittest_batch_id += 1
|
|
32
32
|
|
|
33
|
-
def add_rendering_analysis_for_frid(self, frid, rendering_analysis) -> None:
|
|
34
|
-
self.frid_render_anaysis[frid] = rendering_analysis
|
|
35
|
-
|
|
36
33
|
def set_render_succeeded(self, succeeded: bool):
|
|
37
34
|
self.render_succeeded = succeeded
|
|
38
35
|
|
|
36
|
+
def set_render_cancelled(self):
|
|
37
|
+
self.render_cancelled = True
|
|
38
|
+
|
|
39
39
|
def set_render_generated_code_path(self, generated_code_path: str):
|
|
40
40
|
self.render_generated_code_path = generated_code_path
|
|
41
41
|
|
|
@@ -55,6 +55,3 @@ class RunState:
|
|
|
55
55
|
"replay": self.replay,
|
|
56
56
|
"spec_filename": self.spec_filename,
|
|
57
57
|
}
|
|
58
|
-
|
|
59
|
-
def get_render_func_id(self, frid: str) -> str:
|
|
60
|
-
return f"{self.render_id}-{frid}"
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
def format_duration_hms(total_seconds: int) -> str:
|
|
2
|
+
"""Format a duration in seconds as hours, minutes, and seconds (e.g. ``1h 2m 3.45s``, ``45.67s``)."""
|
|
3
|
+
if total_seconds < 0:
|
|
4
|
+
total_seconds = 0
|
|
5
|
+
h = int(total_seconds // 3600)
|
|
6
|
+
m = int((total_seconds % 3600) // 60)
|
|
7
|
+
s = total_seconds % 60
|
|
8
|
+
if h:
|
|
9
|
+
return f"{h}h {m}m {s}s"
|
|
10
|
+
if m:
|
|
11
|
+
return f"{m}m {s}s"
|
|
12
|
+
text = f"{s}".rstrip("0").rstrip(".")
|
|
13
|
+
return f"{text}s" if text else "0s"
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
AMBIGUITY_CAUSES = {
|
|
17
|
+
"reference_resource_ambiguity": "Ambiguity is in the reference resources",
|
|
18
|
+
"definition_ambiguity": "Ambiguity is in the definitions",
|
|
19
|
+
"non_functional_requirement_ambiguity": "Ambiguity is in the implementation reqs",
|
|
20
|
+
"functional_requirement_ambiguity": "Ambiguity is in the functionality",
|
|
21
|
+
"other": "Ambiguity in the other parts of the specification",
|
|
22
|
+
}
|
|
@@ -91,6 +91,12 @@ def check_section_for_linked_resources(section):
|
|
|
91
91
|
f"Plain syntax error: Only relative links are allowed (text: {link.node.children[0].content}, target: {link.node.target})."
|
|
92
92
|
)
|
|
93
93
|
|
|
94
|
+
if not os.path.exists(link.node.target):
|
|
95
|
+
raise PlainSyntaxError(f"Plain syntax error: Link {link.node.target} does not exist.")
|
|
96
|
+
|
|
97
|
+
if not os.path.isfile(link.node.target):
|
|
98
|
+
raise PlainSyntaxError(f"Plain syntax error: Link {link.node.target} must be a file.")
|
|
99
|
+
|
|
94
100
|
if len(link.node.children) != 1:
|
|
95
101
|
raise PlainSyntaxError(f"Plain syntax error: Link must have text specified (link: {link.node.target}).")
|
|
96
102
|
|
|
@@ -5,13 +5,17 @@ import os
|
|
|
5
5
|
import shutil
|
|
6
6
|
from functools import cached_property
|
|
7
7
|
|
|
8
|
-
from
|
|
8
|
+
from plain2code_exceptions import GitNotInstalledError, MissingPreviousFunctionalitiesError, ModuleDoesNotExistError
|
|
9
|
+
|
|
10
|
+
try:
|
|
11
|
+
from git.exc import NoSuchPathError
|
|
12
|
+
except ImportError:
|
|
13
|
+
raise GitNotInstalledError("git is not installed. Please install git and try again.")
|
|
9
14
|
|
|
10
15
|
import git_utils
|
|
11
16
|
import plain_file
|
|
12
17
|
import plain_spec
|
|
13
18
|
from plain2code_console import console
|
|
14
|
-
from plain2code_exceptions import MissingPreviousFunctionalitiesError, ModuleDoesNotExistError
|
|
15
19
|
from render_machine.implementation_code_helpers import ImplementationCodeHelpers
|
|
16
20
|
|
|
17
21
|
CODEPLAIN_MEMORY_SUBFOLDER = ".memory"
|
|
@@ -7,7 +7,7 @@ name = "codeplain"
|
|
|
7
7
|
dynamic = ["version"]
|
|
8
8
|
description = "Transform plain language specifications into working code"
|
|
9
9
|
readme = "README.md"
|
|
10
|
-
requires-python = "
|
|
10
|
+
requires-python = ">=3.11"
|
|
11
11
|
classifiers = [
|
|
12
12
|
"Environment :: Console",
|
|
13
13
|
"Intended Audience :: Developers",
|
|
@@ -40,7 +40,7 @@ class RunConformanceTests(BaseAction):
|
|
|
40
40
|
+ f"in module {render_context.conformance_tests_running_context.current_testing_module_name}"
|
|
41
41
|
+ ")."
|
|
42
42
|
)
|
|
43
|
-
exit_code, conformance_tests_issue,
|
|
43
|
+
exit_code, conformance_tests_issue, conformance_tests_temp_log_file_path = render_utils.execute_script(
|
|
44
44
|
conformance_tests_script,
|
|
45
45
|
[render_context.build_folder, conformance_tests_folder_name],
|
|
46
46
|
"Conformance Tests",
|
|
@@ -49,7 +49,9 @@ class RunConformanceTests(BaseAction):
|
|
|
49
49
|
timeout=render_context.test_script_timeout,
|
|
50
50
|
stop_event=render_context.stop_event,
|
|
51
51
|
)
|
|
52
|
-
render_context.script_execution_history.latest_conformance_test_output_path =
|
|
52
|
+
render_context.script_execution_history.latest_conformance_test_output_path = (
|
|
53
|
+
conformance_tests_temp_log_file_path
|
|
54
|
+
)
|
|
53
55
|
render_context.script_execution_history.should_update_script_outputs = True
|
|
54
56
|
|
|
55
57
|
render_context.memory_manager.create_conformance_tests_memory(
|
|
@@ -21,7 +21,7 @@ class RunUnitTests(BaseAction):
|
|
|
21
21
|
console.info(
|
|
22
22
|
f"Running unit tests script {unittests_script}. (attempt: {render_context.unit_tests_running_context.fix_attempts + 1})"
|
|
23
23
|
)
|
|
24
|
-
exit_code, unittests_issue,
|
|
24
|
+
exit_code, unittests_issue, unittests_temp_log_file_path = render_utils.execute_script(
|
|
25
25
|
unittests_script,
|
|
26
26
|
[render_context.build_folder],
|
|
27
27
|
"Unit Tests",
|
|
@@ -29,7 +29,7 @@ class RunUnitTests(BaseAction):
|
|
|
29
29
|
stop_event=render_context.stop_event,
|
|
30
30
|
)
|
|
31
31
|
|
|
32
|
-
render_context.script_execution_history.latest_unit_test_output_path =
|
|
32
|
+
render_context.script_execution_history.latest_unit_test_output_path = unittests_temp_log_file_path
|
|
33
33
|
render_context.script_execution_history.should_update_script_outputs = True
|
|
34
34
|
if exit_code == 0:
|
|
35
35
|
return self.SUCCESSFUL_OUTCOME, None
|
|
@@ -179,7 +179,11 @@ class RenderContext:
|
|
|
179
179
|
)
|
|
180
180
|
|
|
181
181
|
def has_next_frid(self) -> bool:
|
|
182
|
-
|
|
182
|
+
next_frid = plain_spec.get_next_frid(self.plain_source_tree, self.frid_context.frid)
|
|
183
|
+
if self.render_range is None or len(self.render_range) == 0:
|
|
184
|
+
return next_frid is not None
|
|
185
|
+
|
|
186
|
+
return next_frid is not None and int(next_frid) <= int(self.render_range[-1])
|
|
183
187
|
|
|
184
188
|
def finish_implementing_frid(self):
|
|
185
189
|
self.functional_requirements_render_attempts_failed_unit_during_conformance_tests = 0
|
|
@@ -248,7 +252,8 @@ class RenderContext:
|
|
|
248
252
|
conformance_tests_running_context = self.conformance_tests_running_context
|
|
249
253
|
if conformance_tests_running_context.current_testing_module_name == self.module_name:
|
|
250
254
|
conformance_tests_running_context.current_testing_frid = plain_spec.get_next_frid(
|
|
251
|
-
self.plain_source_tree,
|
|
255
|
+
self.plain_source_tree,
|
|
256
|
+
self.conformance_tests_running_context.current_testing_frid,
|
|
252
257
|
)
|
|
253
258
|
else:
|
|
254
259
|
all_frids = list(
|