codeplain 0.3.8__tar.gz → 0.3.9__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.8 → codeplain-0.3.9}/.github/workflows/publish-install-script.yml +17 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/.github/workflows/publish-to-pypi.yml +34 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/CLAUDE.md +6 -2
- {codeplain-0.3.8 → codeplain-0.3.9}/PKG-INFO +1 -1
- {codeplain-0.3.8 → codeplain-0.3.9}/docs/plain2code_cli.md +22 -20
- {codeplain-0.3.8 → codeplain-0.3.9}/docs/starting_a_plain_project_from_scratch.md +8 -2
- {codeplain-0.3.8 → codeplain-0.3.9}/examples/example_hello_world_golang/run.sh +2 -2
- {codeplain-0.3.8 → codeplain-0.3.9}/examples/example_hello_world_python/run.sh +2 -2
- {codeplain-0.3.8 → codeplain-0.3.9}/examples/example_hello_world_react/run.sh +1 -1
- {codeplain-0.3.8 → codeplain-0.3.9}/git_utils.py +0 -10
- {codeplain-0.3.8 → codeplain-0.3.9}/memory_management.py +2 -3
- codeplain-0.3.9/metadata_utils.py +46 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/module_renderer.py +3 -6
- {codeplain-0.3.8 → codeplain-0.3.9}/plain2code.py +6 -1
- {codeplain-0.3.8 → codeplain-0.3.9}/plain2code_arguments.py +6 -15
- {codeplain-0.3.8 → codeplain-0.3.9}/plain2code_cli.md +17 -19
- {codeplain-0.3.8 → codeplain-0.3.9}/plain2code_telemetry.py +17 -11
- {codeplain-0.3.8 → codeplain-0.3.9}/plain_modules.py +73 -41
- {codeplain-0.3.8 → codeplain-0.3.9}/render_machine/actions/prepare_repositories.py +3 -10
- {codeplain-0.3.8 → codeplain-0.3.9}/render_machine/conformance_tests.py +8 -6
- {codeplain-0.3.8 → codeplain-0.3.9}/render_machine/render_context.py +1 -3
- {codeplain-0.3.8 → codeplain-0.3.9}/render_machine/render_utils.py +1 -2
- {codeplain-0.3.8 → codeplain-0.3.9}/system_config.py +45 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/e2e/test_hello_world_python.py +1 -1
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/e2e/test_hello_world_python_windows.py +1 -1
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/test_arg_provenance.py +3 -3
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/test_folder_path_resolution.py +12 -13
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/test_plain2code.py +1 -2
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/test_plain_modules.py +200 -15
- codeplain-0.3.9/tests/test_prepare_repositories_layout.py +119 -0
- codeplain-0.3.9/tests/test_system_config.py +58 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/test_telemetry.py +31 -10
- {codeplain-0.3.8 → codeplain-0.3.9}/.claude/settings.json +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/.flake8 +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/.github/dependabot.yml +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/.github/workflows/e2e.yml +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/.github/workflows/lint-and-test.yml +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/.github/workflows/nofity-slack-on-main-merge.yml +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/.gitignore +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/.vscode/launch.json +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/.vscode/settings.json +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/LICENSE +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/README.md +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/change_detection.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/cli_output/__init__.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/cli_output/dry_run.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/cli_output/render_summary.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/cli_output/status.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/codeplain_REST_api.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/concept_utils.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/config/__init__.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/config/system_config.yaml +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/diff_utils.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/docs/generate_cli.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/event_bus.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/examples/example_hello_world_golang/config.yaml +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/examples/example_hello_world_golang/harness_tests/hello_world_test.go +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/examples/example_hello_world_golang/hello_world_golang.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/examples/example_hello_world_python/config.yaml +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/examples/example_hello_world_python/harness_tests/hello_world_display/test_hello_world.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/examples/example_hello_world_python/hello_world_python.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/examples/example_hello_world_react/config.yaml +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/examples/example_hello_world_react/harness_tests/hello_world_display/cypress/e2e/hello_world.cy.ts +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/examples/example_hello_world_react/harness_tests/hello_world_display/cypress/support/e2e.ts +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/examples/example_hello_world_react/harness_tests/hello_world_display/cypress.config.ts +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/examples/example_hello_world_react/harness_tests/hello_world_display/package.json +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/examples/example_hello_world_react/harness_tests/hello_world_display/tsconfig.json +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/examples/example_hello_world_react/hello_world_react.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/examples/run.sh +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/file_utils.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/install/bash/examples.sh +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/install/bash/install.sh +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/install/bash/walkthrough.sh +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/install/powershell/examples.ps1 +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/install/powershell/install.ps1 +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/install/powershell/walkthrough.ps1 +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/partial_rendering.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/path_resolution.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/plain2code_console.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/plain2code_events.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/plain2code_exceptions.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/plain2code_logger.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/plain2code_nodes.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/plain2code_read_config.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/plain2code_state.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/plain2code_utils.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/plain_file.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/plain_spec.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/pyproject.toml +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/pytest.ini +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/render_machine/__init__.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/render_machine/actions/analyze_specification_ambiguity.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/render_machine/actions/base_action.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/render_machine/actions/commit_conformance_tests_changes.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/render_machine/actions/commit_implementation_code_changes.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/render_machine/actions/create_dist.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/render_machine/actions/exit_with_error.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/render_machine/actions/finish_functional_requirement.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/render_machine/actions/fix_conformance_test.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/render_machine/actions/fix_unit_tests.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/render_machine/actions/prepare_testing_environment.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/render_machine/actions/refactor_code.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/render_machine/actions/render_conformance_tests.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/render_machine/actions/render_functional_requirement.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/render_machine/actions/run_conformance_tests.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/render_machine/actions/run_unit_tests.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/render_machine/actions/summarize_conformance_tests.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/render_machine/code_renderer.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/render_machine/implementation_code_helpers.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/render_machine/render_types.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/render_machine/state_machine_config.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/render_machine/states.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/render_machine/triggers.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/requirements.txt +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/resources/codeplain_overview.png +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/resources/plain_example.png +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/standard_template_library/golang-console-app-template.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/standard_template_library/python-console-app-template.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/standard_template_library/typescript-react-app-boilerplate.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/standard_template_library/typescript-react-app-template.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/test_scripts/run_conformance_tests_cypress.ps1 +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/test_scripts/run_conformance_tests_cypress.sh +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/test_scripts/run_conformance_tests_golang.ps1 +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/test_scripts/run_conformance_tests_golang.sh +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/test_scripts/run_conformance_tests_python.ps1 +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/test_scripts/run_conformance_tests_python.sh +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/test_scripts/run_unittests_flutter.ps1 +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/test_scripts/run_unittests_flutter.sh +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/test_scripts/run_unittests_golang.ps1 +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/test_scripts/run_unittests_golang.sh +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/test_scripts/run_unittests_python.ps1 +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/test_scripts/run_unittests_python.sh +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/test_scripts/run_unittests_react.ps1 +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/test_scripts/run_unittests_react.sh +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/__init__.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/conftest.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/data/acceptance_tests_warning/main_requiring_acceptance_tests.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/data/acceptance_tests_warning/required_with_acceptance_tests.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/data/imports/circular_imports_1.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/data/imports/circular_imports_2.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/data/imports/circular_imports_main.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/data/imports/diamond_import_1.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/data/imports/diamond_import_2.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/data/imports/diamond_import_common.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/data/imports/diamond_imports_main.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/data/imports/import_with_functionalities.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/data/imports/imports_module_with_functionalities.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/data/imports/non_existent_import.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/data/partial_rendering/pr_code_var.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/data/partial_rendering/pr_implement.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/data/partial_rendering/pr_leaf.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/data/partial_rendering/pr_middle.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/data/partial_rendering/pr_root.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/data/partial_rendering/pr_solo.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/data/plainfile/add_new_task_modal_specification.yaml +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/data/plainfile/duplicate_specification_heading.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/data/plainfile/empty_functional_specs_section.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/data/plainfile/invalid_specification_order.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/data/plainfile/missing_non_functional_requirements.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/data/plainfile/no_functional_specs_section.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/data/plainfile/plain_source_with_absolute_link.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/data/plainfile/plain_source_with_url_link.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/data/plainfile/task_list_ui_specification.yaml +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/data/plainfile/task_manager_with_reference_links.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/data/plainfile/without_non_functional_requirement.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/data/plainfileparser/concept_validation_acceptance_tests.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/data/plainfileparser/concept_validation_acceptance_tests_nondefined.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/data/plainfileparser/concept_validation_defined_nondefined.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/data/plainfileparser/concept_validation_defined_nondefined_2.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/data/plainfileparser/concept_validation_definition.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/data/plainfileparser/concept_validation_noconcepts.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/data/plainfileparser/concept_validation_nonconcept.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/data/plainfileparser/concept_validation_nondefined.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/data/plainfileparser/concept_validation_redefinition.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/data/plainfileparser/concept_validation_several_concepts.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/data/plainfileparser/concept_validation_valid.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/data/plainfileparser/exported_concepts.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/data/plainfileparser/exported_concepts_base.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/data/plainfileparser/exported_concepts_example.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/data/plainfileparser/exported_concepts_missing.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/data/plainfileparser/exported_concepts_missing_example.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/data/plainfileparser/exported_concepts_nested.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/data/plainfileparser/exported_concepts_nested_example.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/data/plainfileparser/exported_concepts_transitive_example.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/data/plainfileparser/exported_concepts_transitive_l1.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/data/plainfileparser/exported_concepts_transitive_l2.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/data/plainfileparser/plain_file_parser_with_comments.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/data/plainfileparser/plain_file_with_comments_indented.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/data/plainfileparser/regular_plain_source.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/data/plainfileparser/required_concepts.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/data/plainfileparser/required_concepts_defs.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/data/plainfileparser/required_concepts_example.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/data/plainfileparser/required_concepts_l1.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/data/plainfileparser/required_concepts_l2.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/data/plainfileparser/required_concepts_missing.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/data/plainfileparser/required_concepts_module.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/data/plainfileparser/required_concepts_partial.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/data/plainfileparser/required_concepts_partial_duplicate.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/data/plainfileparser/topological_sort.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/data/plainfileparser/topological_sort_not_referenced.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/data/requires/circular_requires_main.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/data/requires/circular_requires_sub.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/data/requires/diamond_requires_1.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/data/requires/diamond_requires_2.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/data/requires/diamond_requires_common.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/data/requires/diamond_requires_main.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/data/requires/independent_requires_1.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/data/requires/independent_requires_2.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/data/requires/independent_requires_main.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/data/requires/non_existent_require.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/data/requires/normal_requires_1.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/data/requires/normal_requires_2.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/data/requires/normal_requires_common.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/data/requires/normal_requires_main.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/data/sample_base64_image.txt +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/data/simple.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/data/templates/block_level_include.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/data/templates/code_variables.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/data/templates/header.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/data/templates/implement.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/data/templates/implement_2.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/data/templates/template_include.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/data/templates/test_hardest_problem.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/e2e/Dockerfile +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/e2e/conftest.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/test_change_detection.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/test_cli_output.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/test_console_log_styles.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/test_file_utils.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/test_git_utils.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/test_imports.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/test_log_file_name_resolution.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/test_logging_config_path_resolution.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/test_partial_rendering.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/test_path_resolution.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/test_plain2code_state.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/test_plain2code_utils.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/test_plainfile.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/test_plainfileparser.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/test_plainspec.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/test_requires.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/test_resolve_config_file.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/test_script_path_resolution.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/test_tui_usage.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tests/test_usage_summary.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tui/__init__.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tui/components.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tui/models.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tui/plain2code_tui.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tui/plain_module_render_choice_tui.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tui/spinner.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tui/state_handlers.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tui/styles.css +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/tui/widget_helpers.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.9}/usage_summary.py +0 -0
|
@@ -14,6 +14,9 @@ jobs:
|
|
|
14
14
|
name: Upload to Cloudflare R2
|
|
15
15
|
runs-on: ubuntu-latest
|
|
16
16
|
|
|
17
|
+
env:
|
|
18
|
+
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
|
|
19
|
+
|
|
17
20
|
steps:
|
|
18
21
|
- uses: actions/checkout@v4
|
|
19
22
|
|
|
@@ -54,3 +57,17 @@ jobs:
|
|
|
54
57
|
--content-type "text/plain"
|
|
55
58
|
echo "✓ examples.ps1 uploaded to R2"
|
|
56
59
|
|
|
60
|
+
- name: Notify Slack (success)
|
|
61
|
+
if: ${{ success() && env.SLACK_WEBHOOK_URL != '' }}
|
|
62
|
+
run: |
|
|
63
|
+
curl -s -X POST "$SLACK_WEBHOOK_URL" \
|
|
64
|
+
-H 'Content-type: application/json' \
|
|
65
|
+
--data "{\"text\":\"*Codeplain Client*: Install scripts deployed to R2 :white_check_mark: (\`${GITHUB_SHA:0:7}\`, by *${{ github.actor }}*).\"}"
|
|
66
|
+
|
|
67
|
+
- name: Notify Slack (failure)
|
|
68
|
+
if: ${{ failure() && env.SLACK_WEBHOOK_URL != '' }}
|
|
69
|
+
run: |
|
|
70
|
+
curl -s -X POST "$SLACK_WEBHOOK_URL" \
|
|
71
|
+
-H 'Content-type: application/json' \
|
|
72
|
+
--data "{\"text\":\"*Codeplain Client*: Install script deploy to R2 FAILED :x: (\`${GITHUB_SHA:0:7}\`). Users may be getting a stale installer. See <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|the run log>.\"}"
|
|
73
|
+
|
|
@@ -15,12 +15,22 @@ jobs:
|
|
|
15
15
|
permissions:
|
|
16
16
|
contents: write
|
|
17
17
|
|
|
18
|
+
env:
|
|
19
|
+
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
|
|
20
|
+
|
|
18
21
|
steps:
|
|
19
22
|
- uses: actions/checkout@v4
|
|
20
23
|
with:
|
|
21
24
|
# hatch-vcs derives the version from git tags, so we need full history.
|
|
22
25
|
fetch-depth: 0
|
|
23
26
|
|
|
27
|
+
- name: Notify Slack (start)
|
|
28
|
+
if: ${{ env.SLACK_WEBHOOK_URL != '' }}
|
|
29
|
+
run: |
|
|
30
|
+
curl -s -X POST "$SLACK_WEBHOOK_URL" \
|
|
31
|
+
-H 'Content-type: application/json' \
|
|
32
|
+
--data "{\"text\":\"*Codeplain Client*: Release \`${{ github.ref_name }}\` published by *${{ github.actor }}* — building and publishing to PyPI...\"}"
|
|
33
|
+
|
|
24
34
|
- name: Install uv
|
|
25
35
|
# uv provisions its own Python (honoring requires-python), so no
|
|
26
36
|
# separate actions/setup-python step is needed.
|
|
@@ -47,6 +57,13 @@ jobs:
|
|
|
47
57
|
run: |
|
|
48
58
|
gh release upload ${{ github.ref_name }} dist/* --clobber
|
|
49
59
|
|
|
60
|
+
- name: Notify Slack (build failure)
|
|
61
|
+
if: ${{ failure() && env.SLACK_WEBHOOK_URL != '' }}
|
|
62
|
+
run: |
|
|
63
|
+
curl -s -X POST "$SLACK_WEBHOOK_URL" \
|
|
64
|
+
-H 'Content-type: application/json' \
|
|
65
|
+
--data "{\"text\":\"*Codeplain Client*: Build of \`${{ github.ref_name }}\` FAILED :x:. Nothing was published to PyPI. See <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|the run log>.\"}"
|
|
66
|
+
|
|
50
67
|
publish-to-pypi:
|
|
51
68
|
name: Publish to PyPI
|
|
52
69
|
needs: build
|
|
@@ -59,6 +76,9 @@ jobs:
|
|
|
59
76
|
# authenticate this run — no long-lived API token needed.
|
|
60
77
|
id-token: write
|
|
61
78
|
|
|
79
|
+
env:
|
|
80
|
+
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
|
|
81
|
+
|
|
62
82
|
steps:
|
|
63
83
|
- name: Download distribution packages
|
|
64
84
|
uses: actions/download-artifact@v4
|
|
@@ -68,3 +88,17 @@ jobs:
|
|
|
68
88
|
|
|
69
89
|
- name: Publish to PyPI
|
|
70
90
|
uses: pypa/gh-action-pypi-publish@release/v1
|
|
91
|
+
|
|
92
|
+
- name: Notify Slack (success)
|
|
93
|
+
if: ${{ success() && env.SLACK_WEBHOOK_URL != '' }}
|
|
94
|
+
run: |
|
|
95
|
+
curl -s -X POST "$SLACK_WEBHOOK_URL" \
|
|
96
|
+
-H 'Content-type: application/json' \
|
|
97
|
+
--data "{\"text\":\"*Codeplain Client*: \`${{ github.ref_name }}\` published to PyPI :white_check_mark:. Install with \`pip install --upgrade codeplain\`.\"}"
|
|
98
|
+
|
|
99
|
+
- name: Notify Slack (failure)
|
|
100
|
+
if: ${{ failure() && env.SLACK_WEBHOOK_URL != '' }}
|
|
101
|
+
run: |
|
|
102
|
+
curl -s -X POST "$SLACK_WEBHOOK_URL" \
|
|
103
|
+
-H 'Content-type: application/json' \
|
|
104
|
+
--data "{\"text\":\"*Codeplain Client*: Publishing \`${{ github.ref_name }}\` to PyPI FAILED :x:. See <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|the run log>.\"}"
|
|
@@ -212,8 +212,12 @@ Two logging modes:
|
|
|
212
212
|
### Code Generation Process
|
|
213
213
|
- Templates in `standard_template_library/` use Liquid2 syntax
|
|
214
214
|
- Template search order: (1) `.plain` file dir, (2) `--template-dir`, (3) built-in standard lib
|
|
215
|
-
-
|
|
216
|
-
-
|
|
215
|
+
- Each module renders into its own tree under the build folder (configurable via `--build-folder`, default `plain_modules/`):
|
|
216
|
+
- `<build-folder>/<module>/code/` — implementation code (its own git repo)
|
|
217
|
+
- `<build-folder>/<module>/tests/` — conformance tests (its own git repo; only created when a conformance tests script is configured)
|
|
218
|
+
- `<build-folder>/<module>/.codeplain/` — module metadata (`module_metadata.json`), not tracked in git
|
|
219
|
+
- `<build-folder>/<module>/.memory/` — conformance test memory, not tracked in git
|
|
220
|
+
- Each FRID render produces a git commit in the `code/` and `tests/` repos for rollback capability
|
|
217
221
|
|
|
218
222
|
### Configuration
|
|
219
223
|
- `config.yaml` can be placed in `.plain` file dir or CWD
|
|
@@ -9,7 +9,6 @@ usage: generate_cli.py [-h] [--verbose] [--base-folder BASE_FOLDER]
|
|
|
9
9
|
[--render-range RENDER_RANGE |
|
|
10
10
|
--render-from RENDER_FROM] [--force-render]
|
|
11
11
|
[--unittests-script UNITTESTS_SCRIPT]
|
|
12
|
-
[--conformance-tests-folder CONFORMANCE_TESTS_FOLDER]
|
|
13
12
|
[--conformance-tests-script CONFORMANCE_TESTS_SCRIPT]
|
|
14
13
|
[--prepare-environment-script PREPARE_ENVIRONMENT_SCRIPT]
|
|
15
14
|
[--test-script-timeout TEST_SCRIPT_TIMEOUT]
|
|
@@ -20,8 +19,8 @@ usage: generate_cli.py [-h] [--verbose] [--base-folder BASE_FOLDER]
|
|
|
20
19
|
[--conformance-tests-dest CONFORMANCE_TESTS_DEST]
|
|
21
20
|
[--render-machine-graph]
|
|
22
21
|
[--logging-config-path LOGGING_CONFIG_PATH]
|
|
23
|
-
[--headless]
|
|
24
|
-
filename
|
|
22
|
+
[--headless] [--status] [--version]
|
|
23
|
+
[filename]
|
|
25
24
|
|
|
26
25
|
Render plain code to target code. Path arguments resolve based on where they
|
|
27
26
|
were written: values given on the command line are resolved against the
|
|
@@ -39,7 +38,7 @@ positional arguments:
|
|
|
39
38
|
|
|
40
39
|
options:
|
|
41
40
|
-h, --help show this help message and exit
|
|
42
|
-
--verbose, -v
|
|
41
|
+
--verbose, -v Set default log level to DEBUG for TUI and file logs
|
|
43
42
|
--base-folder BASE_FOLDER
|
|
44
43
|
Base folder for the build files
|
|
45
44
|
--build-folder BUILD_FOLDER
|
|
@@ -66,18 +65,17 @@ options:
|
|
|
66
65
|
--force-render Force re-render of all the required modules.
|
|
67
66
|
--unittests-script UNITTESTS_SCRIPT
|
|
68
67
|
Shell script to run unit tests on generated code.
|
|
69
|
-
Receives the
|
|
70
|
-
(
|
|
71
|
-
--conformance-tests-folder CONFORMANCE_TESTS_FOLDER
|
|
72
|
-
Folder for conformance test files
|
|
68
|
+
Receives the module's code folder path as its first
|
|
69
|
+
argument (e.g. `plain_modules/module_name/code`).
|
|
73
70
|
--conformance-tests-script CONFORMANCE_TESTS_SCRIPT
|
|
74
71
|
Path to conformance tests shell script. Every
|
|
75
72
|
conformance test script should accept two arguments:
|
|
76
|
-
1) Path to a folder (e.g.
|
|
77
|
-
|
|
78
|
-
subfolder of the
|
|
79
|
-
|
|
80
|
-
|
|
73
|
+
1) Path to a folder (e.g.
|
|
74
|
+
`plain_modules/module_name/code`) containing generated
|
|
75
|
+
source code, 2) Path to a subfolder of the module's
|
|
76
|
+
tests folder (e.g.
|
|
77
|
+
`plain_modules/module_name/tests/subfoldername`)
|
|
78
|
+
containing test files.
|
|
81
79
|
--prepare-environment-script PREPARE_ENVIRONMENT_SCRIPT
|
|
82
80
|
Path to a shell script that prepares the testing
|
|
83
81
|
environment. The script should accept the source code
|
|
@@ -90,9 +88,9 @@ options:
|
|
|
90
88
|
--api-key API_KEY API key used to access the API. If not provided, the
|
|
91
89
|
`CODEPLAIN_API_KEY` environment variable is used.
|
|
92
90
|
--full-plain Full preview ***plain specification before code
|
|
93
|
-
generation.Use when you want to preview context of
|
|
94
|
-
***plain primitives that are going to be included
|
|
95
|
-
order to render the given module.
|
|
91
|
+
generation. Use when you want to preview context of
|
|
92
|
+
all ***plain primitives that are going to be included
|
|
93
|
+
in order to render the given module.
|
|
96
94
|
--dry-run Dry run preview of the code generation (without
|
|
97
95
|
actually making any changes).
|
|
98
96
|
--replay-with REPLAY_WITH
|
|
@@ -109,10 +107,10 @@ options:
|
|
|
109
107
|
Target folder to copy rendered contents of code to
|
|
110
108
|
(used only if --copy-build is set).
|
|
111
109
|
--copy-conformance-tests
|
|
112
|
-
If set, copy the conformance tests
|
|
113
|
-
|
|
114
|
-
tests-dest` folder successful rendering.
|
|
115
|
-
--conformance-tests-script.
|
|
110
|
+
If set, copy the module's conformance tests (from
|
|
111
|
+
`<build-folder>/<module>/tests`) to `--conformance-
|
|
112
|
+
tests-dest` folder after successful rendering.
|
|
113
|
+
Requires --conformance-tests-script.
|
|
116
114
|
--conformance-tests-dest CONFORMANCE_TESTS_DEST
|
|
117
115
|
Target folder to copy conformance tests of code to
|
|
118
116
|
(used only if --copy-conformance-tests is set).
|
|
@@ -123,6 +121,10 @@ options:
|
|
|
123
121
|
--headless Run in headless mode: no TUI, no terminal output
|
|
124
122
|
except a single render-started message. All logs are
|
|
125
123
|
written to the log file.
|
|
124
|
+
--status Display account status including user information, API
|
|
125
|
+
key label, and rendering credits. Does not render any
|
|
126
|
+
code.
|
|
127
|
+
--version Display the client version and exit.
|
|
126
128
|
|
|
127
129
|
configuration:
|
|
128
130
|
--config-name CONFIG_NAME
|
|
@@ -22,10 +22,16 @@ my-new-project/
|
|
|
22
22
|
├── run_unittests_[language].sh # Unit test script
|
|
23
23
|
├── run_conformance_tests_[language].sh # Conformance test script
|
|
24
24
|
├── build/ # Generated final code
|
|
25
|
-
|
|
26
|
-
└──
|
|
25
|
+
└── plain_modules/ # Generated modules
|
|
26
|
+
└── my_app/ # One folder per module
|
|
27
|
+
├── .codeplain/ # Module metadata
|
|
28
|
+
├── .memory/ # Conformance test memory
|
|
29
|
+
├── code/ # Generated code
|
|
30
|
+
└── tests/ # Generated conformance tests
|
|
27
31
|
```
|
|
28
32
|
|
|
33
|
+
The `tests/` folder is only created when a conformance test script is configured.
|
|
34
|
+
|
|
29
35
|
In this guide we will cover how to create each of these step by step.
|
|
30
36
|
|
|
31
37
|
## 1. Define Your .plain File
|
|
@@ -20,11 +20,11 @@ if [ $? -ne 0 ]; then
|
|
|
20
20
|
exit 1
|
|
21
21
|
fi
|
|
22
22
|
|
|
23
|
-
cd plain_modules/hello_world_golang
|
|
23
|
+
cd plain_modules/hello_world_golang/code
|
|
24
24
|
|
|
25
25
|
# We need to compile the tests so that we can execute them in the current folder
|
|
26
26
|
# (https://stackoverflow.com/questions/23847003/golang-tests-and-working-directory/29541248#29541248)
|
|
27
|
-
go test -c
|
|
27
|
+
go test -c ../../../harness_tests/hello_world_test.go
|
|
28
28
|
|
|
29
29
|
# Check if test compilation has failed for the hello world example
|
|
30
30
|
if [ $? -ne 0 ]; then
|
|
@@ -7,9 +7,9 @@ if [ $? -ne 0 ]; then
|
|
|
7
7
|
exit 1
|
|
8
8
|
fi
|
|
9
9
|
|
|
10
|
-
cd plain_modules/hello_world_python
|
|
10
|
+
cd plain_modules/hello_world_python/code
|
|
11
11
|
|
|
12
|
-
python
|
|
12
|
+
python ../../../harness_tests/hello_world_display/test_hello_world.py
|
|
13
13
|
|
|
14
14
|
# Check if the test harness has failed for the hello world example
|
|
15
15
|
if [ $? -ne 0 ]; then
|
|
@@ -20,7 +20,7 @@ if [ $? -ne 0 ]; then
|
|
|
20
20
|
exit 1
|
|
21
21
|
fi
|
|
22
22
|
|
|
23
|
-
../../test_scripts/run_conformance_tests_cypress.sh plain_modules/hello_world_react harness_tests/hello_world_display ${VERBOSE:+-v}
|
|
23
|
+
../../test_scripts/run_conformance_tests_cypress.sh plain_modules/hello_world_react/code harness_tests/hello_world_display ${VERBOSE:+-v}
|
|
24
24
|
|
|
25
25
|
# Check if the test harness has failed for the hello world example
|
|
26
26
|
if [ $? -ne 0 ]; then
|
|
@@ -64,7 +64,6 @@ def init_git_repo(
|
|
|
64
64
|
path_to_repo: Union[str, os.PathLike],
|
|
65
65
|
module_name: Optional[str] = None,
|
|
66
66
|
render_id: Optional[str] = None,
|
|
67
|
-
initial_files: Optional[dict[str, str]] = None,
|
|
68
67
|
) -> Repo:
|
|
69
68
|
"""
|
|
70
69
|
Initializes a new git repository in the given path.
|
|
@@ -79,10 +78,6 @@ def init_git_repo(
|
|
|
79
78
|
repo = Repo.init(path_to_repo)
|
|
80
79
|
_ensure_git_config(repo)
|
|
81
80
|
|
|
82
|
-
if initial_files:
|
|
83
|
-
file_utils.store_response_files(path_to_repo, initial_files, [])
|
|
84
|
-
repo.git.add(".")
|
|
85
|
-
|
|
86
81
|
repo.git.commit(
|
|
87
82
|
"--allow-empty", "-m", _get_full_commit_message(INITIAL_COMMIT_MESSAGE, module_name, None, render_id)
|
|
88
83
|
)
|
|
@@ -95,14 +90,9 @@ def clone_repo(
|
|
|
95
90
|
new_repo_path: str,
|
|
96
91
|
module_name: Optional[str] = None,
|
|
97
92
|
render_id: Optional[str] = None,
|
|
98
|
-
initial_files: Optional[dict[str, str]] = None,
|
|
99
93
|
) -> Repo:
|
|
100
94
|
repo = Repo.clone_from(source_repo_path, new_repo_path)
|
|
101
95
|
|
|
102
|
-
if initial_files:
|
|
103
|
-
file_utils.store_response_files(new_repo_path, initial_files, [])
|
|
104
|
-
repo.git.add(".")
|
|
105
|
-
|
|
106
96
|
repo.git.commit(
|
|
107
97
|
"--allow-empty", "-m", _get_full_commit_message(INITIAL_COMMIT_MESSAGE, module_name, None, render_id)
|
|
108
98
|
)
|
|
@@ -3,7 +3,6 @@ import os
|
|
|
3
3
|
|
|
4
4
|
import file_utils
|
|
5
5
|
from plain2code_console import console
|
|
6
|
-
from plain_modules import CODEPLAIN_MEMORY_SUBFOLDER
|
|
7
6
|
from render_machine.implementation_code_helpers import ImplementationCodeHelpers
|
|
8
7
|
from render_machine.render_context import RenderContext
|
|
9
8
|
|
|
@@ -24,9 +23,9 @@ class MemoryManager:
|
|
|
24
23
|
console.debug(f"Loaded {len(memory_files_content)} memory files.")
|
|
25
24
|
return memory_files, memory_files_content
|
|
26
25
|
|
|
27
|
-
def __init__(self, codeplain_api,
|
|
26
|
+
def __init__(self, codeplain_api, memory_folder: str):
|
|
28
27
|
self.codeplain_api = codeplain_api
|
|
29
|
-
self.memory_folder =
|
|
28
|
+
self.memory_folder = memory_folder
|
|
30
29
|
|
|
31
30
|
def create_conformance_tests_memory(
|
|
32
31
|
self, render_context: RenderContext, exit_code: int, conformance_tests_issue: str
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"""Read/write helpers for the per-module metadata file (``module_metadata.json``).
|
|
2
|
+
|
|
3
|
+
These helpers operate purely on a metadata path or a plain dict. Module-specific
|
|
4
|
+
logic — computing the hashes, assembling the payload from the spec and required
|
|
5
|
+
modules — stays on :class:`plain_modules.PlainModule`.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import json
|
|
11
|
+
import os
|
|
12
|
+
|
|
13
|
+
MODULE_METADATA_FILENAME = "module_metadata.json"
|
|
14
|
+
MODULE_FUNCTIONALITIES = "functionalities"
|
|
15
|
+
REQUIRED_MODULES_FUNCTIONALITIES = "required_modules_functionalities"
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def load_metadata(metadata_path: str) -> dict | None:
|
|
19
|
+
"""Return the parsed metadata dict, or None if the file does not exist."""
|
|
20
|
+
if not os.path.exists(metadata_path):
|
|
21
|
+
return None
|
|
22
|
+
|
|
23
|
+
with open(metadata_path, "r", encoding="utf-8") as f:
|
|
24
|
+
return json.load(f)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def write_metadata(metadata_path: str, metadata: dict) -> None:
|
|
28
|
+
"""Write metadata as indented JSON, creating the parent folder if needed."""
|
|
29
|
+
os.makedirs(os.path.dirname(metadata_path), exist_ok=True)
|
|
30
|
+
|
|
31
|
+
with open(metadata_path, "w", encoding="utf-8") as f:
|
|
32
|
+
json.dump(metadata, f, indent=4)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def truncate_functionalities(metadata: dict, keep_count: int) -> bool:
|
|
36
|
+
"""Trim the functionalities list in ``metadata`` in place to ``keep_count`` entries.
|
|
37
|
+
|
|
38
|
+
Returns True if the list was shortened, False if it was already short enough
|
|
39
|
+
(in which case ``metadata`` is left untouched).
|
|
40
|
+
"""
|
|
41
|
+
functionalities = metadata.get(MODULE_FUNCTIONALITIES, [])
|
|
42
|
+
if len(functionalities) <= keep_count:
|
|
43
|
+
return False
|
|
44
|
+
|
|
45
|
+
metadata[MODULE_FUNCTIONALITIES] = functionalities[:keep_count]
|
|
46
|
+
return True
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import argparse
|
|
2
|
-
import os
|
|
3
2
|
import threading
|
|
4
3
|
|
|
5
4
|
from event_bus import EventBus
|
|
@@ -48,9 +47,8 @@ class ModuleRenderer:
|
|
|
48
47
|
self.codeplainAPI,
|
|
49
48
|
memory_manager,
|
|
50
49
|
plain_module,
|
|
51
|
-
build_folder=
|
|
50
|
+
build_folder=plain_module.module_build_folder,
|
|
52
51
|
build_dest=self.args.build_dest,
|
|
53
|
-
conformance_tests_folder=self.args.conformance_tests_folder,
|
|
54
52
|
conformance_tests_dest=self.args.conformance_tests_dest,
|
|
55
53
|
unittests_script=self.args.unittests_script,
|
|
56
54
|
conformance_tests_script=self.args.conformance_tests_script,
|
|
@@ -115,8 +113,7 @@ class ModuleRenderer:
|
|
|
115
113
|
|
|
116
114
|
memory_manager = MemoryManager(
|
|
117
115
|
self.codeplainAPI,
|
|
118
|
-
plain_module.
|
|
119
|
-
self.args.conformance_tests_folder,
|
|
116
|
+
plain_module.module_memory_folder,
|
|
120
117
|
)
|
|
121
118
|
render_context = self._build_render_context_for_module(
|
|
122
119
|
plain_module,
|
|
@@ -165,7 +162,7 @@ class ModuleRenderer:
|
|
|
165
162
|
if self.args.copy_build:
|
|
166
163
|
rendered_code_path = f"{self.args.build_dest}/"
|
|
167
164
|
else:
|
|
168
|
-
rendered_code_path = self.
|
|
165
|
+
rendered_code_path = self.plain_module.module_build_folder
|
|
169
166
|
|
|
170
167
|
self.run_state.set_render_generated_code_path(rendered_code_path)
|
|
171
168
|
self.event_bus.publish(RenderCompleted(rendered_code_path=rendered_code_path))
|
|
@@ -212,6 +212,12 @@ def render( # noqa: C901
|
|
|
212
212
|
|
|
213
213
|
warn_if_acceptance_tests_without_conformance_script(plain_module, args)
|
|
214
214
|
|
|
215
|
+
# The module_metadata file lives outside the code git repo. That means that a crash mid-render can leave it
|
|
216
|
+
# claiming a functionality was implemented even thought it wasn't yet committed (because of the crash).
|
|
217
|
+
# Out of precaution, this reconciles every module_metadata against the code repo.
|
|
218
|
+
for module in plain_module.all_required_modules + [plain_module]:
|
|
219
|
+
module.reconcile_metadata_with_git()
|
|
220
|
+
|
|
215
221
|
render_choice = None
|
|
216
222
|
if render_range is None:
|
|
217
223
|
plain_module_render_state = get_plain_module_render_state(plain_module)
|
|
@@ -356,7 +362,6 @@ def main(): # noqa: C901
|
|
|
356
362
|
plain_module = plain_modules.PlainModule(
|
|
357
363
|
os.path.basename(args.filename),
|
|
358
364
|
args.build_folder,
|
|
359
|
-
args.conformance_tests_folder,
|
|
360
365
|
template_dirs,
|
|
361
366
|
)
|
|
362
367
|
except Exception as e:
|
|
@@ -16,7 +16,6 @@ CODEPLAIN_API_KEY = os.getenv("CODEPLAIN_API_KEY")
|
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
DEFAULT_BUILD_FOLDER = "plain_modules"
|
|
19
|
-
DEFAULT_CONFORMANCE_TESTS_FOLDER = "conformance_tests"
|
|
20
19
|
DEFAULT_BUILD_DEST = "dist"
|
|
21
20
|
DEFAULT_CONFORMANCE_TESTS_DEST = "dist_conformance_tests"
|
|
22
21
|
|
|
@@ -299,23 +298,15 @@ def create_parser():
|
|
|
299
298
|
parser,
|
|
300
299
|
"--unittests-script",
|
|
301
300
|
type=str,
|
|
302
|
-
help="Shell script to run unit tests on generated code. Receives the
|
|
303
|
-
)
|
|
304
|
-
_add_arg(
|
|
305
|
-
parser,
|
|
306
|
-
"--conformance-tests-folder",
|
|
307
|
-
type=non_empty_string,
|
|
308
|
-
default=DEFAULT_CONFORMANCE_TESTS_FOLDER,
|
|
309
|
-
help="Folder for conformance test files",
|
|
310
|
-
path=True,
|
|
301
|
+
help="Shell script to run unit tests on generated code. Receives the module's code folder path as its first argument (e.g. `plain_modules/module_name/code`).",
|
|
311
302
|
)
|
|
312
303
|
_add_arg(
|
|
313
304
|
parser,
|
|
314
305
|
"--conformance-tests-script",
|
|
315
306
|
type=str,
|
|
316
307
|
help="Path to conformance tests shell script. Every conformance test script should accept two arguments: "
|
|
317
|
-
"1) Path to a folder (e.g. `plain_modules/module_name`) containing generated source code, "
|
|
318
|
-
"2) Path to a subfolder of the
|
|
308
|
+
"1) Path to a folder (e.g. `plain_modules/module_name/code`) containing generated source code, "
|
|
309
|
+
"2) Path to a subfolder of the module's tests folder (e.g. `plain_modules/module_name/tests/subfoldername`) containing test files.",
|
|
319
310
|
)
|
|
320
311
|
|
|
321
312
|
_add_arg(
|
|
@@ -400,7 +391,7 @@ def create_parser():
|
|
|
400
391
|
"--copy-conformance-tests",
|
|
401
392
|
action="store_true",
|
|
402
393
|
default=False,
|
|
403
|
-
help="If set, copy the conformance tests
|
|
394
|
+
help="If set, copy the module's conformance tests (from `<build-folder>/<module>/tests`) to `--conformance-tests-dest` folder after successful rendering. Requires --conformance-tests-script.",
|
|
404
395
|
)
|
|
405
396
|
_add_arg(
|
|
406
397
|
parser,
|
|
@@ -490,8 +481,8 @@ def parse_arguments(command_line: Optional[Sequence[str]] = None):
|
|
|
490
481
|
|
|
491
482
|
if args.build_folder == args.build_dest:
|
|
492
483
|
parser.error("--build-folder and --build-dest cannot be the same")
|
|
493
|
-
if args.
|
|
494
|
-
parser.error("--conformance-tests-
|
|
484
|
+
if args.conformance_tests_dest == args.build_folder:
|
|
485
|
+
parser.error("--conformance-tests-dest and --build-folder cannot be the same")
|
|
495
486
|
|
|
496
487
|
args.render_conformance_tests = args.conformance_tests_script is not None
|
|
497
488
|
|
|
@@ -3,19 +3,19 @@
|
|
|
3
3
|
```text
|
|
4
4
|
[1;34musage: [0m[1;35mgenerate_cli.py[0m [[32m-h[0m] [[36m--verbose[0m] [[36m--base-folder [33mBASE_FOLDER[0m] [[36m--build-folder [33mBUILD_FOLDER[0m] [[36m--log-to-file | --no-log-to-file[0m] [[36m--log-file-name [33mLOG_FILE_NAME[0m]
|
|
5
5
|
[[36m--config-name [33mCONFIG_NAME[0m] [[36m--render-range [33mRENDER_RANGE[0m | [36m--render-from [33mRENDER_FROM[0m] [[36m--force-render[0m] [[36m--unittests-script [33mUNITTESTS_SCRIPT[0m]
|
|
6
|
-
[[36m--conformance-tests-
|
|
7
|
-
[[36m--
|
|
8
|
-
[[36m--
|
|
9
|
-
[[36m--
|
|
6
|
+
[[36m--conformance-tests-script [33mCONFORMANCE_TESTS_SCRIPT[0m] [[36m--prepare-environment-script [33mPREPARE_ENVIRONMENT_SCRIPT[0m] [[36m--test-script-timeout [33mTEST_SCRIPT_TIMEOUT[0m]
|
|
7
|
+
[[36m--api [33m[API][0m] [[36m--api-key [33mAPI_KEY[0m] [[36m--full-plain[0m] [[36m--dry-run[0m] [[36m--replay-with [33mREPLAY_WITH[0m] [[36m--template-dir [33mTEMPLATE_DIR[0m] [[36m--copy-build[0m] [[36m--build-dest [33mBUILD_DEST[0m]
|
|
8
|
+
[[36m--copy-conformance-tests[0m] [[36m--conformance-tests-dest [33mCONFORMANCE_TESTS_DEST[0m] [[36m--render-machine-graph[0m] [[36m--logging-config-path [33mLOGGING_CONFIG_PATH[0m] [[36m--headless[0m]
|
|
9
|
+
[[36m--status[0m] [[36m--version[0m]
|
|
10
10
|
[32m[filename][0m
|
|
11
11
|
|
|
12
|
-
Render plain code to target code. Path arguments resolve based on where they were written: values given on the command line are resolved against the current working directory, values
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
Render plain code to target code. Path arguments resolve based on where they were written: values given on the command line are resolved against the current working directory, values read
|
|
13
|
+
from config.yaml are resolved against the config file's directory, and defaults are resolved against the directory containing the plain file. Absolute paths (and paths starting with '~')
|
|
14
|
+
are used as-is.
|
|
15
15
|
|
|
16
16
|
[1;34mpositional arguments:[0m
|
|
17
|
-
[1;32mfilename[0m Path to the plain file to render. The directory containing this file has highest precedence for template loading, so you can place custom templates here to
|
|
18
|
-
|
|
17
|
+
[1;32mfilename[0m Path to the plain file to render. The directory containing this file has highest precedence for template loading, so you can place custom templates here to override
|
|
18
|
+
the defaults. See --template-dir for more details about template loading.
|
|
19
19
|
|
|
20
20
|
[1;34moptions:[0m
|
|
21
21
|
[1;32m-h[0m, [1;36m--help[0m show this help message and exit
|
|
@@ -32,24 +32,22 @@ with '~') are used as-is.
|
|
|
32
32
|
Specify a range of functionalities to render (e.g. `1` , `2`, `3`). Use comma to separate start and end IDs. If only one functionality ID is provided, only that
|
|
33
33
|
functionality is rendered. Range is inclusive of both start and end IDs.
|
|
34
34
|
[1;36m--render-from[0m [1;33mRENDER_FROM[0m
|
|
35
|
-
Continue generation starting from this specific functionality (e.g. `2`). The functionality with this ID will be included in the output. The functionality ID
|
|
36
|
-
|
|
35
|
+
Continue generation starting from this specific functionality (e.g. `2`). The functionality with this ID will be included in the output. The functionality ID must
|
|
36
|
+
match one of the functionalities in your plain file.
|
|
37
37
|
[1;36m--force-render[0m Force re-render of all the required modules.
|
|
38
38
|
[1;36m--unittests-script[0m [1;33mUNITTESTS_SCRIPT[0m
|
|
39
|
-
Shell script to run unit tests on generated code. Receives the
|
|
40
|
-
[1;36m--conformance-tests-folder[0m [1;33mCONFORMANCE_TESTS_FOLDER[0m
|
|
41
|
-
Folder for conformance test files
|
|
39
|
+
Shell script to run unit tests on generated code. Receives the module's code folder path as its first argument (e.g. `plain_modules/module_name/code`).
|
|
42
40
|
[1;36m--conformance-tests-script[0m [1;33mCONFORMANCE_TESTS_SCRIPT[0m
|
|
43
|
-
Path to conformance tests shell script. Every conformance test script should accept two arguments: 1) Path to a folder (e.g. `plain_modules/module_name`)
|
|
44
|
-
containing generated source code, 2) Path to a subfolder of the
|
|
41
|
+
Path to conformance tests shell script. Every conformance test script should accept two arguments: 1) Path to a folder (e.g. `plain_modules/module_name/code`)
|
|
42
|
+
containing generated source code, 2) Path to a subfolder of the module's tests folder (e.g. `plain_modules/module_name/tests/subfoldername`) containing test files.
|
|
45
43
|
[1;36m--prepare-environment-script[0m [1;33mPREPARE_ENVIRONMENT_SCRIPT[0m
|
|
46
44
|
Path to a shell script that prepares the testing environment. The script should accept the source code folder path as its first argument.
|
|
47
45
|
[1;36m--test-script-timeout[0m [1;33mTEST_SCRIPT_TIMEOUT[0m
|
|
48
46
|
Timeout for test scripts in seconds. If not provided, the default timeout of 120 seconds is used.
|
|
49
47
|
[1;36m--api[0m [1;33m[API][0m Alternative base URL for the API. Default: `https://api.codeplain.ai`
|
|
50
48
|
[1;36m--api-key[0m [1;33mAPI_KEY[0m API key used to access the API. If not provided, the `CODEPLAIN_API_KEY` environment variable is used.
|
|
51
|
-
[1;36m--full-plain[0m Full preview ***plain specification before code generation. Use when you want to preview context of all ***plain primitives that are going to be included in
|
|
52
|
-
|
|
49
|
+
[1;36m--full-plain[0m Full preview ***plain specification before code generation. Use when you want to preview context of all ***plain primitives that are going to be included in order
|
|
50
|
+
to render the given module.
|
|
53
51
|
[1;36m--dry-run[0m Dry run preview of the code generation (without actually making any changes).
|
|
54
52
|
[1;36m--replay-with[0m [1;33mREPLAY_WITH[0m
|
|
55
53
|
[1;36m--template-dir[0m [1;33mTEMPLATE_DIR[0m
|
|
@@ -59,7 +57,7 @@ with '~') are used as-is.
|
|
|
59
57
|
[1;36m--build-dest[0m [1;33mBUILD_DEST[0m
|
|
60
58
|
Target folder to copy rendered contents of code to (used only if --copy-build is set).
|
|
61
59
|
[1;36m--copy-conformance-tests[0m
|
|
62
|
-
If set, copy the conformance tests
|
|
60
|
+
If set, copy the module's conformance tests (from `<build-folder>/<module>/tests`) to `--conformance-tests-dest` folder after successful rendering. Requires
|
|
63
61
|
--conformance-tests-script.
|
|
64
62
|
[1;36m--conformance-tests-dest[0m [1;33mCONFORMANCE_TESTS_DEST[0m
|
|
65
63
|
Target folder to copy conformance tests of code to (used only if --copy-conformance-tests is set).
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
"""Crash reporting via Sentry.
|
|
2
2
|
|
|
3
3
|
Only unexpected exceptions are reported (the caller decides which exceptions are
|
|
4
|
-
expected; see EXPECTED_EXCEPTIONS in plain2code.py).
|
|
5
|
-
and can be disabled by setting
|
|
6
|
-
|
|
4
|
+
expected; see EXPECTED_EXCEPTIONS in plain2code.py). In production, reporting is
|
|
5
|
+
on by default and can be disabled by setting CODEPLAIN_TELEMETRY to 0, false or
|
|
6
|
+
off. In any other environment it is off unless CODEPLAIN_TELEMETRY is explicitly
|
|
7
|
+
set to 1, true or on.
|
|
7
8
|
"""
|
|
8
9
|
|
|
9
10
|
import os
|
|
@@ -20,9 +21,7 @@ from system_config import system_config
|
|
|
20
21
|
|
|
21
22
|
SENTRY_DSN = "https://64d0d86b50b34e2dede3e4eaf5142282@o4510793955934208.ingest.us.sentry.io/4511540621213696"
|
|
22
23
|
|
|
23
|
-
|
|
24
|
-
ENVIRONMENT_ENV_VAR = "CODEPLAIN_ENV"
|
|
25
|
-
DEFAULT_ENVIRONMENT = "production"
|
|
24
|
+
TELEMETRY_ENV_VAR = "CODEPLAIN_TELEMETRY"
|
|
26
25
|
|
|
27
26
|
FLUSH_TIMEOUT_SECONDS = 2
|
|
28
27
|
|
|
@@ -50,10 +49,17 @@ SCRUB_DENYLIST = DEFAULT_DENYLIST + [
|
|
|
50
49
|
|
|
51
50
|
|
|
52
51
|
def telemetry_enabled() -> bool:
|
|
53
|
-
"""Return True if crash reporting should be active.
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
52
|
+
"""Return True if crash reporting should be active.
|
|
53
|
+
|
|
54
|
+
In production it is on unless CODEPLAIN_TELEMETRY disables it.
|
|
55
|
+
Anywhere else it is off unless CODEPLAIN_TELEMETRY enables it.
|
|
56
|
+
"""
|
|
57
|
+
setting = os.environ.get(TELEMETRY_ENV_VAR, "").strip().lower()
|
|
58
|
+
|
|
59
|
+
if system_config.environment == "production":
|
|
60
|
+
return setting not in {"0", "false", "off"}
|
|
61
|
+
|
|
62
|
+
return setting in {"1", "true", "on"}
|
|
57
63
|
|
|
58
64
|
|
|
59
65
|
def initialize_telemetry(**init_overrides: Any) -> bool:
|
|
@@ -65,7 +71,7 @@ def initialize_telemetry(**init_overrides: Any) -> bool:
|
|
|
65
71
|
init_kwargs: dict[str, Any] = dict(
|
|
66
72
|
dsn=SENTRY_DSN,
|
|
67
73
|
release=system_config.client_version,
|
|
68
|
-
environment=
|
|
74
|
+
environment=system_config.environment,
|
|
69
75
|
send_default_pii=False,
|
|
70
76
|
server_name="", # hostname is identifying; don't send it
|
|
71
77
|
default_integrations=False,
|