codeplain 0.3.2__tar.gz → 0.3.3__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.2 → codeplain-0.3.3}/PKG-INFO +8 -2
- {codeplain-0.3.2 → codeplain-0.3.3}/README.md +5 -0
- codeplain-0.3.3/_version.py +1 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/cli_output/status.py +14 -9
- {codeplain-0.3.2 → codeplain-0.3.3}/examples/example_hello_world_python/hello_world_python.plain +3 -3
- {codeplain-0.3.2 → codeplain-0.3.3}/plain2code.py +28 -23
- {codeplain-0.3.2 → codeplain-0.3.3}/plain2code_state.py +4 -0
- codeplain-0.3.3/plain2code_telemetry.py +114 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/pyproject.toml +2 -1
- {codeplain-0.3.2 → codeplain-0.3.3}/render_machine/code_renderer.py +2 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/render_machine/render_context.py +23 -44
- {codeplain-0.3.2 → codeplain-0.3.3}/render_machine/state_machine_config.py +22 -63
- {codeplain-0.3.2 → codeplain-0.3.3}/render_machine/triggers.py +1 -1
- {codeplain-0.3.2 → codeplain-0.3.3}/requirements.txt +1 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tests/test_cli_output.py +119 -13
- codeplain-0.3.3/tests/test_telemetry.py +204 -0
- codeplain-0.3.2/.claude/settings.local.json +0 -66
- codeplain-0.3.2/.zed/settings.json +0 -46
- codeplain-0.3.2/_version.py +0 -1
- codeplain-0.3.2/examples/example_hello_world_python/text.txt +0 -1
- {codeplain-0.3.2 → codeplain-0.3.3}/.claude/settings.json +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/.flake8 +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/.github/dependabot.yml +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/.github/workflows/e2e.yml +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/.github/workflows/lint-and-test.yml +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/.github/workflows/nofity-slack-on-main-merge.yml +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/.github/workflows/publish-install-script.yml +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/.github/workflows/publish-to-pypi.yml +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/.gitignore +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/.vscode/launch.json +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/.vscode/settings.json +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/CLAUDE.md +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/LICENSE +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/cli_output/__init__.py +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/cli_output/dry_run.py +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/cli_output/render_summary.py +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/codeplain_REST_api.py +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/concept_utils.py +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/config/__init__.py +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/config/system_config.yaml +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/diff_utils.py +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/docs/generate_cli.py +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/docs/plain2code_cli.md +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/docs/starting_a_plain_project_from_scratch.md +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/event_bus.py +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/examples/example_hello_world_golang/config.yaml +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/examples/example_hello_world_golang/harness_tests/hello_world_test.go +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/examples/example_hello_world_golang/hello_world_golang.plain +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/examples/example_hello_world_golang/run.sh +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/examples/example_hello_world_python/config.yaml +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/examples/example_hello_world_python/harness_tests/hello_world_display/test_hello_world.py +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/examples/example_hello_world_python/run.sh +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/examples/example_hello_world_react/config.yaml +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/examples/example_hello_world_react/harness_tests/hello_world_display/cypress/e2e/hello_world.cy.ts +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/examples/example_hello_world_react/harness_tests/hello_world_display/cypress/support/e2e.ts +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/examples/example_hello_world_react/harness_tests/hello_world_display/cypress.config.ts +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/examples/example_hello_world_react/harness_tests/hello_world_display/package.json +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/examples/example_hello_world_react/harness_tests/hello_world_display/tsconfig.json +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/examples/example_hello_world_react/hello_world_react.plain +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/examples/example_hello_world_react/run.sh +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/examples/run.sh +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/file_utils.py +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/git_utils.py +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/install/bash/examples.sh +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/install/bash/install.sh +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/install/bash/walkthrough.sh +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/install/powershell/examples.ps1 +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/install/powershell/install.ps1 +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/install/powershell/walkthrough.ps1 +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/memory_management.py +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/module_renderer.py +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/partial_rendering.py +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/plain2code_arguments.py +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/plain2code_console.py +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/plain2code_events.py +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/plain2code_exceptions.py +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/plain2code_logger.py +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/plain2code_nodes.py +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/plain2code_read_config.py +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/plain2code_utils.py +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/plain_file.py +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/plain_modules.py +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/plain_spec.py +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/pytest.ini +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/render_machine/__init__.py +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/render_machine/actions/analyze_specification_ambiguity.py +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/render_machine/actions/base_action.py +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/render_machine/actions/commit_conformance_tests_changes.py +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/render_machine/actions/commit_implementation_code_changes.py +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/render_machine/actions/create_dist.py +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/render_machine/actions/exit_with_error.py +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/render_machine/actions/finish_functional_requirement.py +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/render_machine/actions/fix_conformance_test.py +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/render_machine/actions/fix_unit_tests.py +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/render_machine/actions/prepare_repositories.py +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/render_machine/actions/prepare_testing_environment.py +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/render_machine/actions/refactor_code.py +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/render_machine/actions/render_conformance_tests.py +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/render_machine/actions/render_functional_requirement.py +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/render_machine/actions/run_conformance_tests.py +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/render_machine/actions/run_unit_tests.py +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/render_machine/actions/summarize_conformance_tests.py +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/render_machine/conformance_tests.py +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/render_machine/implementation_code_helpers.py +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/render_machine/render_types.py +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/render_machine/render_utils.py +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/render_machine/states.py +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/resources/codeplain_overview.png +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/resources/plain_example.png +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/standard_template_library/__init__.py +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/standard_template_library/golang-console-app-template.plain +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/standard_template_library/python-console-app-template.plain +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/standard_template_library/typescript-react-app-boilerplate.plain +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/standard_template_library/typescript-react-app-template.plain +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/system_config.py +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/test_scripts/run_conformance_tests_cypress.ps1 +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/test_scripts/run_conformance_tests_cypress.sh +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/test_scripts/run_conformance_tests_golang.ps1 +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/test_scripts/run_conformance_tests_golang.sh +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/test_scripts/run_conformance_tests_python.ps1 +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/test_scripts/run_conformance_tests_python.sh +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/test_scripts/run_unittests_flutter.ps1 +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/test_scripts/run_unittests_golang.ps1 +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/test_scripts/run_unittests_golang.sh +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/test_scripts/run_unittests_python.ps1 +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/test_scripts/run_unittests_python.sh +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/test_scripts/run_unittests_react.ps1 +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/test_scripts/run_unittests_react.sh +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tests/__init__.py +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tests/conftest.py +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tests/data/imports/circular_imports_1.plain +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tests/data/imports/circular_imports_2.plain +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tests/data/imports/circular_imports_main.plain +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tests/data/imports/diamond_import_1.plain +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tests/data/imports/diamond_import_2.plain +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tests/data/imports/diamond_import_common.plain +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tests/data/imports/diamond_imports_main.plain +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tests/data/imports/non_existent_import.plain +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tests/data/partial_rendering/pr_leaf.plain +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tests/data/partial_rendering/pr_middle.plain +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tests/data/partial_rendering/pr_root.plain +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tests/data/partial_rendering/pr_solo.plain +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tests/data/plainfile/add_new_task_modal_specification.yaml +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tests/data/plainfile/duplicate_specification_heading.plain +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tests/data/plainfile/invalid_specification_order.plain +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tests/data/plainfile/missing_non_functional_requirements.plain +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tests/data/plainfile/plain_source_with_absolute_link.plain +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tests/data/plainfile/plain_source_with_url_link.plain +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tests/data/plainfile/task_list_ui_specification.yaml +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tests/data/plainfile/task_manager_with_reference_links.plain +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tests/data/plainfile/without_non_functional_requirement.plain +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tests/data/plainfileparser/concept_validation_acceptance_tests.plain +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tests/data/plainfileparser/concept_validation_acceptance_tests_nondefined.plain +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tests/data/plainfileparser/concept_validation_defined_nondefined.plain +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tests/data/plainfileparser/concept_validation_defined_nondefined_2.plain +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tests/data/plainfileparser/concept_validation_definition.plain +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tests/data/plainfileparser/concept_validation_noconcepts.plain +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tests/data/plainfileparser/concept_validation_nonconcept.plain +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tests/data/plainfileparser/concept_validation_nondefined.plain +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tests/data/plainfileparser/concept_validation_redefinition.plain +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tests/data/plainfileparser/concept_validation_several_concepts.plain +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tests/data/plainfileparser/concept_validation_valid.plain +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tests/data/plainfileparser/exported_concepts.plain +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tests/data/plainfileparser/exported_concepts_base.plain +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tests/data/plainfileparser/exported_concepts_example.plain +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tests/data/plainfileparser/exported_concepts_missing.plain +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tests/data/plainfileparser/exported_concepts_missing_example.plain +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tests/data/plainfileparser/exported_concepts_nested.plain +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tests/data/plainfileparser/exported_concepts_nested_example.plain +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tests/data/plainfileparser/exported_concepts_transitive_example.plain +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tests/data/plainfileparser/exported_concepts_transitive_l1.plain +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tests/data/plainfileparser/exported_concepts_transitive_l2.plain +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tests/data/plainfileparser/plain_file_parser_with_comments.plain +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tests/data/plainfileparser/plain_file_with_comments_indented.plain +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tests/data/plainfileparser/regular_plain_source.plain +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tests/data/plainfileparser/required_concepts.plain +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tests/data/plainfileparser/required_concepts_defs.plain +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tests/data/plainfileparser/required_concepts_example.plain +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tests/data/plainfileparser/required_concepts_l1.plain +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tests/data/plainfileparser/required_concepts_l2.plain +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tests/data/plainfileparser/required_concepts_missing.plain +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tests/data/plainfileparser/required_concepts_module.plain +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tests/data/plainfileparser/required_concepts_partial.plain +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tests/data/plainfileparser/required_concepts_partial_duplicate.plain +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tests/data/plainfileparser/topological_sort.plain +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tests/data/plainfileparser/topological_sort_not_referenced.plain +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tests/data/requires/circular_requires_main.plain +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tests/data/requires/circular_requires_sub.plain +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tests/data/requires/diamond_requires_1.plain +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tests/data/requires/diamond_requires_2.plain +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tests/data/requires/diamond_requires_common.plain +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tests/data/requires/diamond_requires_main.plain +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tests/data/requires/independent_requires_1.plain +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tests/data/requires/independent_requires_2.plain +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tests/data/requires/independent_requires_main.plain +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tests/data/requires/non_existent_require.plain +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tests/data/requires/normal_requires_1.plain +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tests/data/requires/normal_requires_2.plain +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tests/data/requires/normal_requires_common.plain +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tests/data/requires/normal_requires_main.plain +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tests/data/simple.plain +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tests/data/templates/block_level_include.plain +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tests/data/templates/code_variables.plain +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tests/data/templates/header.plain +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tests/data/templates/implement.plain +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tests/data/templates/implement_2.plain +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tests/data/templates/template_include.plain +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tests/data/templates/test_hardest_problem.plain +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tests/e2e/Dockerfile +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tests/e2e/conftest.py +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tests/e2e/test_hello_world_python.py +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tests/e2e/test_hello_world_python_windows.py +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tests/test_file_utils.py +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tests/test_git_utils.py +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tests/test_imports.py +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tests/test_partial_rendering.py +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tests/test_plain_modules.py +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tests/test_plainfile.py +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tests/test_plainfileparser.py +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tests/test_plainspec.py +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tests/test_requires.py +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tests/test_resolve_config_file.py +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tui/__init__.py +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tui/components.py +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tui/models.py +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tui/plain2code_tui.py +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tui/plain_module_render_choice_tui.py +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tui/spinner.py +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tui/state_handlers.py +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tui/styles.css +0 -0
- {codeplain-0.3.2 → codeplain-0.3.3}/tui/widget_helpers.py +0 -0
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: codeplain
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.3
|
|
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
|
|
@@ -16,6 +16,7 @@ Requires-Dist: python-liquid2==0.3.0
|
|
|
16
16
|
Requires-Dist: pyyaml==6.0.3
|
|
17
17
|
Requires-Dist: requests==2.34.0
|
|
18
18
|
Requires-Dist: rich==15.0.0
|
|
19
|
+
Requires-Dist: sentry-sdk==2.62.0
|
|
19
20
|
Requires-Dist: textual>=7.5.0
|
|
20
21
|
Requires-Dist: tiktoken==0.12.0
|
|
21
22
|
Requires-Dist: transitions==0.9.3
|
|
@@ -103,6 +104,11 @@ After completing the installation steps above, you can immediately test the syst
|
|
|
103
104
|
python hello_world.py
|
|
104
105
|
```
|
|
105
106
|
|
|
107
|
+
### Crash reporting
|
|
108
|
+
|
|
109
|
+
If the plain2code client crashes unexpectedly, it sends an anonymous crash report to Codeplain to help improve the tool. To disable crash reporting, set the `CODEPLAIN_NO_TELEMETRY=1` flag.
|
|
110
|
+
|
|
111
|
+
|
|
106
112
|
## Releasing
|
|
107
113
|
|
|
108
114
|
Releases are built and published with [uv](https://docs.astral.sh/uv/). The version is read from `_version.py`.
|
|
@@ -74,6 +74,11 @@ After completing the installation steps above, you can immediately test the syst
|
|
|
74
74
|
python hello_world.py
|
|
75
75
|
```
|
|
76
76
|
|
|
77
|
+
### Crash reporting
|
|
78
|
+
|
|
79
|
+
If the plain2code client crashes unexpectedly, it sends an anonymous crash report to Codeplain to help improve the tool. To disable crash reporting, set the `CODEPLAIN_NO_TELEMETRY=1` flag.
|
|
80
|
+
|
|
81
|
+
|
|
77
82
|
## Releasing
|
|
78
83
|
|
|
79
84
|
Releases are built and published with [uv](https://docs.astral.sh/uv/). The version is read from `_version.py`.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.3.3"
|
|
@@ -50,8 +50,8 @@ def _display_credit_line(plan_credits: dict) -> None:
|
|
|
50
50
|
console.print(f" {plan_label:10} {bar} {remaining:2} of {total} remaining expires {formatted_date}")
|
|
51
51
|
|
|
52
52
|
|
|
53
|
-
def
|
|
54
|
-
"""Display a
|
|
53
|
+
def _display_bucket_credit_line(bucket: dict, label: str) -> None:
|
|
54
|
+
"""Display a credit bucket line (purchased or promo) with progress bar."""
|
|
55
55
|
remaining = bucket["remaining"]
|
|
56
56
|
total = bucket["total"]
|
|
57
57
|
expiry_date = bucket["expiry_date"]
|
|
@@ -71,12 +71,12 @@ def _display_purchased_credit_line(bucket: dict) -> None:
|
|
|
71
71
|
bar = _create_progress_bar(remaining, total, width=30)
|
|
72
72
|
|
|
73
73
|
if is_expired:
|
|
74
|
-
console.print(f"
|
|
74
|
+
console.print(f" {label:10} {bar} expired {formatted_date}")
|
|
75
75
|
else:
|
|
76
|
-
console.print(f"
|
|
76
|
+
console.print(f" {label:10} {bar} {remaining:2} of {total} remaining expires {formatted_date}")
|
|
77
77
|
|
|
78
78
|
|
|
79
|
-
def _display_status_message(plan_credits: Optional[dict], purchased_credits: list) -> None:
|
|
79
|
+
def _display_status_message(plan_credits: Optional[dict], purchased_credits: list, promo_credits: list) -> None:
|
|
80
80
|
"""Display appropriate status message based on credit state."""
|
|
81
81
|
has_remaining = False
|
|
82
82
|
|
|
@@ -93,8 +93,8 @@ def _display_status_message(plan_credits: Optional[dict], purchased_credits: lis
|
|
|
93
93
|
if remaining > 0 and period_end > now:
|
|
94
94
|
has_remaining = True
|
|
95
95
|
|
|
96
|
-
# Check if any purchased credits have remaining balance and not expired
|
|
97
|
-
for bucket in purchased_credits:
|
|
96
|
+
# Check if any purchased or promo credits have remaining balance and not expired
|
|
97
|
+
for bucket in [*purchased_credits, *promo_credits]:
|
|
98
98
|
dt_str = bucket["expiry_date"].replace("Z", "+00:00")
|
|
99
99
|
expiry_date = datetime.fromisoformat(dt_str)
|
|
100
100
|
# If naive datetime, assume UTC
|
|
@@ -127,6 +127,7 @@ def print_status(api_key: str, api_url: str, client_version: str) -> None:
|
|
|
127
127
|
org_owner = response.get("organization_owner_email")
|
|
128
128
|
plan_credits = response.get("plan_credits")
|
|
129
129
|
purchased_credits = response.get("purchased_credits", [])
|
|
130
|
+
promo_credits = response.get("promo_credits", [])
|
|
130
131
|
|
|
131
132
|
# Display header information
|
|
132
133
|
if client_version_valid:
|
|
@@ -153,8 +154,12 @@ def print_status(api_key: str, api_url: str, client_version: str) -> None:
|
|
|
153
154
|
|
|
154
155
|
# Display purchased credits
|
|
155
156
|
for bucket in purchased_credits:
|
|
156
|
-
|
|
157
|
+
_display_bucket_credit_line(bucket, "Purchased")
|
|
158
|
+
|
|
159
|
+
# Display promo credits
|
|
160
|
+
for bucket in promo_credits:
|
|
161
|
+
_display_bucket_credit_line(bucket, "Promo")
|
|
157
162
|
|
|
158
163
|
# Display status messages and management link
|
|
159
|
-
_display_status_message(plan_credits, purchased_credits)
|
|
164
|
+
_display_status_message(plan_credits, purchased_credits, promo_credits)
|
|
160
165
|
console.print("\nTo manage your plan navigate to https://platform.codeplain.ai/plans")
|
{codeplain-0.3.2 → codeplain-0.3.3}/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.
|
|
16
18
|
|
|
17
|
-
- :App: should
|
|
18
|
-
|
|
19
|
-
- :App: should complete execution in under 1 second.
|
|
19
|
+
- :App: should complete execution in under 1 second.
|
|
@@ -49,6 +49,7 @@ from plain2code_logger import (
|
|
|
49
49
|
get_log_file_path,
|
|
50
50
|
)
|
|
51
51
|
from plain2code_state import RunState
|
|
52
|
+
from plain2code_telemetry import capture_crash, initialize_telemetry
|
|
52
53
|
from system_config import system_config
|
|
53
54
|
from tui.plain2code_tui import Plain2CodeTUI
|
|
54
55
|
from tui.plain_module_render_choice_tui import PlainModuleRenderChoiceTUI
|
|
@@ -56,6 +57,27 @@ from tui.plain_module_render_choice_tui import PlainModuleRenderChoiceTUI
|
|
|
56
57
|
DEFAULT_TEMPLATE_DIRS = importlib.resources.files("standard_template_library")
|
|
57
58
|
RENDER_THREAD_SHUTDOWN_TIMEOUT = 0.7
|
|
58
59
|
|
|
60
|
+
# Exceptions that represent expected, user-facing error conditions. They are
|
|
61
|
+
# reported to the user directly and must never be sent to Sentry as crashes.
|
|
62
|
+
EXPECTED_EXCEPTIONS = (
|
|
63
|
+
InvalidFridArgument,
|
|
64
|
+
FileNotFoundError,
|
|
65
|
+
MissingResource,
|
|
66
|
+
TemplateNotFoundError,
|
|
67
|
+
PlainSyntaxError,
|
|
68
|
+
MissingPreviousFunctionalitiesError,
|
|
69
|
+
MissingAPIKey,
|
|
70
|
+
InvalidAPIKey,
|
|
71
|
+
OutdatedClientVersion,
|
|
72
|
+
ConflictingRequirements,
|
|
73
|
+
RenderingCreditBalanceTooLow,
|
|
74
|
+
NetworkConnectionError,
|
|
75
|
+
ModuleDoesNotExistError,
|
|
76
|
+
UnsupportedResourceType,
|
|
77
|
+
GitNotInstalledError,
|
|
78
|
+
SystemExit,
|
|
79
|
+
)
|
|
80
|
+
|
|
59
81
|
|
|
60
82
|
def setup_logging(
|
|
61
83
|
args,
|
|
@@ -324,6 +346,8 @@ def main(): # noqa: C901
|
|
|
324
346
|
args, event_bus, run_state, args.log_to_file, args.log_file_name, args.filename, args.headless
|
|
325
347
|
)
|
|
326
348
|
|
|
349
|
+
initialize_telemetry()
|
|
350
|
+
|
|
327
351
|
exc_info = None
|
|
328
352
|
error_message = None
|
|
329
353
|
|
|
@@ -340,36 +364,17 @@ def main(): # noqa: C901
|
|
|
340
364
|
else:
|
|
341
365
|
error_message = str(e) if str(e) else repr(e)
|
|
342
366
|
|
|
343
|
-
if not isinstance(
|
|
344
|
-
e,
|
|
345
|
-
(
|
|
346
|
-
InvalidFridArgument,
|
|
347
|
-
FileNotFoundError,
|
|
348
|
-
MissingResource,
|
|
349
|
-
TemplateNotFoundError,
|
|
350
|
-
PlainSyntaxError,
|
|
351
|
-
MissingPreviousFunctionalitiesError,
|
|
352
|
-
MissingAPIKey,
|
|
353
|
-
InvalidAPIKey,
|
|
354
|
-
OutdatedClientVersion,
|
|
355
|
-
ConflictingRequirements,
|
|
356
|
-
RenderingCreditBalanceTooLow,
|
|
357
|
-
NetworkConnectionError,
|
|
358
|
-
ModuleDoesNotExistError,
|
|
359
|
-
UnsupportedResourceType,
|
|
360
|
-
GitNotInstalledError,
|
|
361
|
-
),
|
|
362
|
-
):
|
|
367
|
+
if not isinstance(e, EXPECTED_EXCEPTIONS):
|
|
363
368
|
exc_info = sys.exc_info()
|
|
364
369
|
finally:
|
|
370
|
+
if exc_info:
|
|
371
|
+
dump_crash_logs(args, run_state)
|
|
372
|
+
capture_crash(exc_info, run_state, args)
|
|
365
373
|
print_exit_summary(
|
|
366
374
|
run_state,
|
|
367
375
|
args.filename,
|
|
368
376
|
error_message=error_message,
|
|
369
377
|
)
|
|
370
|
-
if exc_info:
|
|
371
|
-
# Log traceback
|
|
372
|
-
dump_crash_logs(args, run_state)
|
|
373
378
|
|
|
374
379
|
if args.headless and (exc_info is not None or not run_state.render_succeeded):
|
|
375
380
|
sys.exit(1)
|
|
@@ -23,6 +23,10 @@ class RunState:
|
|
|
23
23
|
self.unittest_batch_id: int = 0
|
|
24
24
|
self.render_time_accumulated: int = 0
|
|
25
25
|
self.last_render_start_timestamp: float = time.monotonic()
|
|
26
|
+
# Mirrored from the render state machine for crash reporting; not authoritative.
|
|
27
|
+
self.current_module: Optional[str] = None
|
|
28
|
+
self.current_frid: Optional[str] = None
|
|
29
|
+
self.current_render_state: Optional[str] = None
|
|
26
30
|
|
|
27
31
|
def increment_call_count(self):
|
|
28
32
|
self.call_count += 1
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
"""Crash reporting via Sentry.
|
|
2
|
+
|
|
3
|
+
Only unexpected exceptions are reported (the caller decides which exceptions are
|
|
4
|
+
expected; see EXPECTED_EXCEPTIONS in plain2code.py). Reporting is on by default
|
|
5
|
+
and can be disabled by setting the CODEPLAIN_NO_TELEMETRY environment variable
|
|
6
|
+
to any non-empty value.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import os
|
|
10
|
+
from typing import Any, Optional
|
|
11
|
+
|
|
12
|
+
import sentry_sdk
|
|
13
|
+
from sentry_sdk.integrations.atexit import AtexitIntegration
|
|
14
|
+
from sentry_sdk.integrations.dedupe import DedupeIntegration
|
|
15
|
+
from sentry_sdk.integrations.modules import ModulesIntegration
|
|
16
|
+
from sentry_sdk.scrubber import DEFAULT_DENYLIST, EventScrubber
|
|
17
|
+
|
|
18
|
+
from plain2code_state import RunState
|
|
19
|
+
from system_config import system_config
|
|
20
|
+
|
|
21
|
+
SENTRY_DSN = "https://64d0d86b50b34e2dede3e4eaf5142282@o4510793955934208.ingest.us.sentry.io/4511540621213696"
|
|
22
|
+
|
|
23
|
+
NO_TELEMETRY_ENV_VAR = "CODEPLAIN_NO_TELEMETRY"
|
|
24
|
+
ENVIRONMENT_ENV_VAR = "CODEPLAIN_ENV"
|
|
25
|
+
DEFAULT_ENVIRONMENT = "production"
|
|
26
|
+
|
|
27
|
+
FLUSH_TIMEOUT_SECONDS = 2
|
|
28
|
+
|
|
29
|
+
# Local variable names whose values may contain proprietary spec or generated
|
|
30
|
+
# code content and must be scrubbed from stack traces (extends Sentry's
|
|
31
|
+
# default denylist, which already covers api_key, auth, secrets etc.).
|
|
32
|
+
# "headers" and "x-api-key" cover the request headers local in
|
|
33
|
+
# codeplain_REST_api.post_request; the default denylist only has the
|
|
34
|
+
# underscore form "x_api_key".
|
|
35
|
+
SCRUB_DENYLIST = DEFAULT_DENYLIST + [
|
|
36
|
+
"authorization",
|
|
37
|
+
"headers",
|
|
38
|
+
"x-api-key",
|
|
39
|
+
"plain_source",
|
|
40
|
+
"plain_source_tree",
|
|
41
|
+
"full_plain_source",
|
|
42
|
+
"existing_files_content",
|
|
43
|
+
"file_content",
|
|
44
|
+
"files_content",
|
|
45
|
+
"content",
|
|
46
|
+
"source",
|
|
47
|
+
"response_json",
|
|
48
|
+
"payload",
|
|
49
|
+
]
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def telemetry_enabled() -> bool:
|
|
53
|
+
"""Return True if crash reporting should be active."""
|
|
54
|
+
if os.environ.get(NO_TELEMETRY_ENV_VAR):
|
|
55
|
+
return False
|
|
56
|
+
return True
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def initialize_telemetry(**init_overrides: Any) -> bool:
|
|
60
|
+
"""Initialize Sentry crash reporting. Returns True if initialized."""
|
|
61
|
+
if not telemetry_enabled():
|
|
62
|
+
return False
|
|
63
|
+
|
|
64
|
+
try:
|
|
65
|
+
init_kwargs: dict[str, Any] = dict(
|
|
66
|
+
dsn=SENTRY_DSN,
|
|
67
|
+
release=system_config.client_version,
|
|
68
|
+
environment=os.environ.get(ENVIRONMENT_ENV_VAR, DEFAULT_ENVIRONMENT),
|
|
69
|
+
send_default_pii=False,
|
|
70
|
+
server_name="", # hostname is identifying; don't send it
|
|
71
|
+
default_integrations=False,
|
|
72
|
+
auto_enabling_integrations=False,
|
|
73
|
+
integrations=[
|
|
74
|
+
AtexitIntegration(callback=lambda pending, timeout: None),
|
|
75
|
+
DedupeIntegration(),
|
|
76
|
+
ModulesIntegration(),
|
|
77
|
+
],
|
|
78
|
+
include_local_variables=True,
|
|
79
|
+
event_scrubber=EventScrubber(denylist=SCRUB_DENYLIST, recursive=True),
|
|
80
|
+
shutdown_timeout=FLUSH_TIMEOUT_SECONDS,
|
|
81
|
+
)
|
|
82
|
+
init_kwargs.update(init_overrides)
|
|
83
|
+
sentry_sdk.init(**init_kwargs)
|
|
84
|
+
return True
|
|
85
|
+
except Exception:
|
|
86
|
+
return False
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def capture_crash(exc_info, run_state: Optional[RunState], args) -> bool:
|
|
90
|
+
"""Report an unexpected crash to Sentry. Returns True if an event was sent."""
|
|
91
|
+
if not telemetry_enabled():
|
|
92
|
+
return False
|
|
93
|
+
|
|
94
|
+
try:
|
|
95
|
+
with sentry_sdk.new_scope() as scope:
|
|
96
|
+
if run_state is not None:
|
|
97
|
+
scope.set_tag("render_id", run_state.render_id)
|
|
98
|
+
scope.set_tag("render_state", run_state.current_render_state)
|
|
99
|
+
scope.set_tag("current_module", run_state.current_module)
|
|
100
|
+
scope.set_tag("current_frid", run_state.current_frid)
|
|
101
|
+
scope.set_tag("headless", bool(getattr(args, "headless", False)))
|
|
102
|
+
scope.set_tag("unittests_script_provided", bool(getattr(args, "unittests_script", None)))
|
|
103
|
+
scope.set_tag("conformance_tests_script_provided", bool(getattr(args, "conformance_tests_script", None)))
|
|
104
|
+
scope.set_tag(
|
|
105
|
+
"prepare_environment_script_provided", bool(getattr(args, "prepare_environment_script", None))
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
event_id = sentry_sdk.capture_exception(exc_info[1])
|
|
109
|
+
|
|
110
|
+
sentry_sdk.flush(timeout=FLUSH_TIMEOUT_SECONDS)
|
|
111
|
+
return event_id is not None
|
|
112
|
+
except Exception:
|
|
113
|
+
# Telemetry must never break the CLI or mask the original crash.
|
|
114
|
+
return False
|
|
@@ -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",
|
|
@@ -26,6 +26,7 @@ dependencies = [
|
|
|
26
26
|
"rich==15.0.0",
|
|
27
27
|
"python-frontmatter==1.3.0",
|
|
28
28
|
"networkx==3.6.1",
|
|
29
|
+
"sentry-sdk==2.62.0",
|
|
29
30
|
]
|
|
30
31
|
|
|
31
32
|
[project.optional-dependencies]
|
|
@@ -42,6 +42,7 @@ class CodeRenderer:
|
|
|
42
42
|
def run(self):
|
|
43
43
|
"""Execute the main rendering workflow."""
|
|
44
44
|
self.render_context.event_bus.publish(RenderModuleStarted(module_name=self.render_context.module_name))
|
|
45
|
+
self.render_context.run_state.current_module = self.render_context.module_name
|
|
45
46
|
previous_action_payload = None
|
|
46
47
|
previous_state = None
|
|
47
48
|
|
|
@@ -63,6 +64,7 @@ class CodeRenderer:
|
|
|
63
64
|
)
|
|
64
65
|
)
|
|
65
66
|
previous_state = deepcopy(self.render_context.state)
|
|
67
|
+
self.render_context.run_state.current_render_state = self.render_context.state
|
|
66
68
|
self.render_context.script_execution_history.should_update_script_outputs = False
|
|
67
69
|
|
|
68
70
|
self.render_context.previous_action_payload = previous_action_payload
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import threading
|
|
2
2
|
from copy import deepcopy
|
|
3
|
-
from typing import Optional
|
|
3
|
+
from typing import Callable, Optional
|
|
4
4
|
|
|
5
5
|
import file_utils
|
|
6
6
|
import git_utils
|
|
@@ -162,6 +162,7 @@ class RenderContext:
|
|
|
162
162
|
linked_resources=linked_resources,
|
|
163
163
|
functional_requirement_render_attempts=0,
|
|
164
164
|
)
|
|
165
|
+
self.run_state.current_frid = frid
|
|
165
166
|
return
|
|
166
167
|
|
|
167
168
|
def check_frid_iteration_limit(self):
|
|
@@ -195,19 +196,10 @@ class RenderContext:
|
|
|
195
196
|
def should_run_conformance_tests(self) -> bool:
|
|
196
197
|
return self.conformance_tests_script is not None
|
|
197
198
|
|
|
198
|
-
def finish_frid_implementation_step(self):
|
|
199
|
-
pass
|
|
200
|
-
|
|
201
199
|
def start_unittests_processing(self):
|
|
202
200
|
self.unit_tests_running_context = UnitTestsRunningContext(fix_attempts=0)
|
|
203
201
|
self.run_state.increment_unittest_batch_id()
|
|
204
202
|
|
|
205
|
-
def start_unittests_processing_in_implementation(self):
|
|
206
|
-
self.start_unittests_processing()
|
|
207
|
-
|
|
208
|
-
def start_unittests_processing_in_refactoring(self):
|
|
209
|
-
self.start_unittests_processing()
|
|
210
|
-
|
|
211
203
|
def _get_first_frid_conformance_test_running_context(self, module: PlainModule | None):
|
|
212
204
|
conformance_tests_running_context = self.conformance_tests_running_context
|
|
213
205
|
|
|
@@ -280,9 +272,6 @@ class RenderContext:
|
|
|
280
272
|
|
|
281
273
|
return conformance_tests_running_context
|
|
282
274
|
|
|
283
|
-
def start_unittests_processing_in_conformance_tests(self):
|
|
284
|
-
self.start_unittests_processing()
|
|
285
|
-
|
|
286
275
|
def finish_unittests_processing(self):
|
|
287
276
|
existing_files = file_utils.list_all_text_files(self.build_folder)
|
|
288
277
|
|
|
@@ -294,39 +283,32 @@ class RenderContext:
|
|
|
294
283
|
self.frid_context.changed_files.add(file_name)
|
|
295
284
|
self.unit_tests_running_context.fix_attempts = 1
|
|
296
285
|
|
|
297
|
-
def
|
|
298
|
-
self.finish_unittests_processing()
|
|
299
|
-
|
|
300
|
-
def start_fixing_unit_tests(self):
|
|
286
|
+
def start_fixing_unit_tests(self, on_limit_exceeded: Callable):
|
|
301
287
|
self.unit_tests_running_context.fix_attempts += 1
|
|
302
|
-
|
|
303
288
|
if self.unit_tests_running_context.fix_attempts > MAX_UNITTEST_FIX_ATTEMPTS:
|
|
304
|
-
|
|
289
|
+
on_limit_exceeded()
|
|
305
290
|
|
|
306
|
-
def
|
|
307
|
-
self.
|
|
291
|
+
def _on_unit_test_limit_exceeded_in_implementation(self):
|
|
292
|
+
self.machine.dispatch(triggers.RESTART_FRID_PROCESSING)
|
|
308
293
|
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
def start_fixing_unit_tests_in_refactoring(self):
|
|
325
|
-
self.unit_tests_running_context.fix_attempts += 1
|
|
294
|
+
def _on_unit_test_limit_exceeded_in_conformance_tests(self):
|
|
295
|
+
self.functional_requirements_render_attempts_failed_unit_during_conformance_tests += 1
|
|
296
|
+
if (
|
|
297
|
+
self.functional_requirements_render_attempts_failed_unit_during_conformance_tests
|
|
298
|
+
>= MAX_FUNCTIONAL_REQUIREMENT_RENDER_ATTEMPTS_FAILED_UNIT_DURING_CONFORMANCE_TESTS
|
|
299
|
+
):
|
|
300
|
+
error_msg = f"Failed to adjust the unit tests after implementation code was update while fixing the conformance tests for functionality {self.frid_context.frid} for the {MAX_FUNCTIONAL_REQUIREMENT_RENDER_ATTEMPTS_FAILED_UNIT_DURING_CONFORMANCE_TESTS} times."
|
|
301
|
+
self.dispatch_error(error_msg)
|
|
302
|
+
else:
|
|
303
|
+
console.info(
|
|
304
|
+
f"Failed to adjust the unit tests after implementation code was updated while fixing the conformance tests for functionality {self.frid_context.frid}."
|
|
305
|
+
)
|
|
306
|
+
console.info(f"Restarting rendering the functionality {self.frid_context.frid} from scratch.")
|
|
307
|
+
self.machine.dispatch(triggers.RESTART_FRID_PROCESSING)
|
|
326
308
|
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
309
|
+
def _on_unit_test_limit_exceeded_in_refactoring(self):
|
|
310
|
+
git_utils.revert_changes(self.build_folder)
|
|
311
|
+
self.machine.dispatch(triggers.START_NEW_REFACTORING_ITERATION)
|
|
330
312
|
|
|
331
313
|
def start_refactoring_code(self):
|
|
332
314
|
|
|
@@ -341,9 +323,6 @@ class RenderContext:
|
|
|
341
323
|
)
|
|
342
324
|
self.machine.dispatch(triggers.PROCEED_FRID_PROCESSING)
|
|
343
325
|
|
|
344
|
-
def finish_refactoring_code(self):
|
|
345
|
-
pass
|
|
346
|
-
|
|
347
326
|
def start_testing_environment_preparation(self):
|
|
348
327
|
if (
|
|
349
328
|
self.prepare_environment_script is None
|
|
@@ -5,7 +5,6 @@ This module defines the hierarchical state machine structure, transitions, and a
|
|
|
5
5
|
used by the CodeRenderer to orchestrate the code generation workflow.
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
|
-
from dataclasses import dataclass
|
|
9
8
|
from typing import Any, Callable, Dict, List
|
|
10
9
|
|
|
11
10
|
import git_utils
|
|
@@ -30,46 +29,6 @@ from render_machine.render_context import RenderContext
|
|
|
30
29
|
from render_machine.states import States
|
|
31
30
|
|
|
32
31
|
|
|
33
|
-
@dataclass
|
|
34
|
-
class UnitTestsStateConfig:
|
|
35
|
-
"""Dataclass for unit test state configuration."""
|
|
36
|
-
|
|
37
|
-
unit_tests_failed_on_enter_function: Callable
|
|
38
|
-
on_enter_action: Callable
|
|
39
|
-
on_exit_action: Callable
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
class UnitTestsConfig:
|
|
43
|
-
"""Provides configurations for different unit test scenarios."""
|
|
44
|
-
|
|
45
|
-
@staticmethod
|
|
46
|
-
def for_refactoring(render_context: RenderContext) -> UnitTestsStateConfig:
|
|
47
|
-
"""Configuration for unit tests during refactoring."""
|
|
48
|
-
return UnitTestsStateConfig(
|
|
49
|
-
unit_tests_failed_on_enter_function=render_context.start_fixing_unit_tests_in_refactoring,
|
|
50
|
-
on_enter_action=render_context.start_unittests_processing_in_refactoring,
|
|
51
|
-
on_exit_action=render_context.finish_unittests_processing,
|
|
52
|
-
)
|
|
53
|
-
|
|
54
|
-
@staticmethod
|
|
55
|
-
def for_conformance_tests(render_context: RenderContext) -> UnitTestsStateConfig:
|
|
56
|
-
"""Configuration for unit tests during conformance tests."""
|
|
57
|
-
return UnitTestsStateConfig(
|
|
58
|
-
unit_tests_failed_on_enter_function=render_context.start_fixing_unit_tests_in_conformance_tests,
|
|
59
|
-
on_enter_action=render_context.start_unittests_processing_in_conformance_tests,
|
|
60
|
-
on_exit_action=render_context.finish_unittests_processing,
|
|
61
|
-
)
|
|
62
|
-
|
|
63
|
-
@staticmethod
|
|
64
|
-
def for_implementation(render_context: RenderContext) -> UnitTestsStateConfig:
|
|
65
|
-
"""Configuration for unit tests during initial implementation."""
|
|
66
|
-
return UnitTestsStateConfig(
|
|
67
|
-
unit_tests_failed_on_enter_function=render_context.start_fixing_unit_tests,
|
|
68
|
-
on_enter_action=render_context.start_unittests_processing_in_implementation,
|
|
69
|
-
on_exit_action=render_context.finish_unittests_processing_during_implementation,
|
|
70
|
-
)
|
|
71
|
-
|
|
72
|
-
|
|
73
32
|
class StateMachineConfig:
|
|
74
33
|
"""Configuration class for the render state machine."""
|
|
75
34
|
|
|
@@ -137,26 +96,21 @@ class StateMachineConfig:
|
|
|
137
96
|
AnalyzeSpecificationAmbiguity.SUCCESSFUL_OUTCOME: triggers.PROCEED_FRID_PROCESSING,
|
|
138
97
|
}
|
|
139
98
|
|
|
140
|
-
def get_processing_unit_tests_states(
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
Args:
|
|
144
|
-
config: A dataclass containing the configuration for the unit test state.
|
|
145
|
-
|
|
146
|
-
Returns:
|
|
147
|
-
Dictionary defining the processing unit tests hierarchical state.
|
|
148
|
-
"""
|
|
149
|
-
children = [
|
|
150
|
-
States.UNIT_TESTS_READY.value,
|
|
151
|
-
{"name": States.UNIT_TESTS_FAILED.value, "on_enter": config.unit_tests_failed_on_enter_function},
|
|
152
|
-
]
|
|
153
|
-
|
|
99
|
+
def get_processing_unit_tests_states(
|
|
100
|
+
self, render_context: RenderContext, on_limit_exceeded: Callable
|
|
101
|
+
) -> Dict[str, Any]:
|
|
154
102
|
return {
|
|
155
103
|
"name": States.PROCESSING_UNIT_TESTS.value,
|
|
156
104
|
"initial": States.UNIT_TESTS_READY.value,
|
|
157
|
-
"on_enter":
|
|
158
|
-
"on_exit":
|
|
159
|
-
"children":
|
|
105
|
+
"on_enter": render_context.start_unittests_processing,
|
|
106
|
+
"on_exit": render_context.finish_unittests_processing,
|
|
107
|
+
"children": [
|
|
108
|
+
States.UNIT_TESTS_READY.value,
|
|
109
|
+
{
|
|
110
|
+
"name": States.UNIT_TESTS_FAILED.value,
|
|
111
|
+
"on_enter": lambda: render_context.start_fixing_unit_tests(on_limit_exceeded),
|
|
112
|
+
},
|
|
113
|
+
],
|
|
160
114
|
}
|
|
161
115
|
|
|
162
116
|
def get_postprocessing_conformance_tests_states(self) -> Dict[str, Any]:
|
|
@@ -191,7 +145,9 @@ class StateMachineConfig:
|
|
|
191
145
|
"on_enter": render_context.start_fixing_conformance_tests,
|
|
192
146
|
"on_exit": render_context.finish_fixing_conformance_tests,
|
|
193
147
|
},
|
|
194
|
-
self.get_processing_unit_tests_states(
|
|
148
|
+
self.get_processing_unit_tests_states(
|
|
149
|
+
render_context, render_context._on_unit_test_limit_exceeded_in_conformance_tests
|
|
150
|
+
),
|
|
195
151
|
self.get_postprocessing_conformance_tests_states(),
|
|
196
152
|
],
|
|
197
153
|
}
|
|
@@ -209,10 +165,11 @@ class StateMachineConfig:
|
|
|
209
165
|
"name": States.REFACTORING_CODE.value,
|
|
210
166
|
"initial": States.READY_FOR_REFACTORING.value,
|
|
211
167
|
"on_enter": render_context.start_refactoring_code,
|
|
212
|
-
"on_exit": render_context.finish_refactoring_code,
|
|
213
168
|
"children": [
|
|
214
169
|
States.READY_FOR_REFACTORING.value,
|
|
215
|
-
self.get_processing_unit_tests_states(
|
|
170
|
+
self.get_processing_unit_tests_states(
|
|
171
|
+
render_context, render_context._on_unit_test_limit_exceeded_in_refactoring
|
|
172
|
+
),
|
|
216
173
|
States.STEP_COMPLETED.value,
|
|
217
174
|
],
|
|
218
175
|
}
|
|
@@ -225,12 +182,14 @@ class StateMachineConfig:
|
|
|
225
182
|
"on_enter": render_context.start_implementing_frid,
|
|
226
183
|
"on_exit": render_context.finish_implementing_frid,
|
|
227
184
|
"children": [
|
|
228
|
-
{"name": States.STEP_COMPLETED.value
|
|
185
|
+
{"name": States.STEP_COMPLETED.value},
|
|
229
186
|
{
|
|
230
187
|
"name": States.READY_FOR_FRID_IMPLEMENTATION.value,
|
|
231
188
|
"on_enter": render_context.check_frid_iteration_limit,
|
|
232
189
|
},
|
|
233
|
-
self.get_processing_unit_tests_states(
|
|
190
|
+
self.get_processing_unit_tests_states(
|
|
191
|
+
render_context, render_context._on_unit_test_limit_exceeded_in_implementation
|
|
192
|
+
),
|
|
234
193
|
refactoring_code_states,
|
|
235
194
|
self.get_processing_conformance_tests_states(render_context),
|
|
236
195
|
States.FRID_FULLY_IMPLEMENTED.value,
|
|
@@ -7,7 +7,7 @@ that controls the code rendering process.
|
|
|
7
7
|
|
|
8
8
|
# Trigger constants for state machine transitions
|
|
9
9
|
START_RENDER = "start_render"
|
|
10
|
-
RENDER_FUNCTIONAL_REQUIREMENT = "render_functional_requirement"
|
|
10
|
+
RENDER_FUNCTIONAL_REQUIREMENT = "render_functional_requirement"
|
|
11
11
|
PROCEED_FRID_PROCESSING = "proceed_frid_processing"
|
|
12
12
|
MARK_UNIT_TESTS_FAILED = "mark_unit_tests_failed"
|
|
13
13
|
MARK_UNIT_TESTS_PASSED = "mark_unit_tests_passed"
|