codeplain 0.3.6__tar.gz → 0.3.8__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/.github/workflows/publish-to-pypi.yml +70 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/PKG-INFO +7 -7
- {codeplain-0.3.6 → codeplain-0.3.8}/cli_output/render_summary.py +2 -2
- {codeplain-0.3.6 → codeplain-0.3.8}/cli_output/status.py +2 -2
- {codeplain-0.3.6 → codeplain-0.3.8}/codeplain_REST_api.py +6 -2
- codeplain-0.3.8/docs/plain2code_cli.md +133 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/file_utils.py +1 -1
- {codeplain-0.3.6 → codeplain-0.3.8}/install/bash/examples.sh +5 -11
- {codeplain-0.3.6 → codeplain-0.3.8}/install/bash/install.sh +3 -1
- {codeplain-0.3.6 → codeplain-0.3.8}/install/powershell/examples.ps1 +5 -11
- {codeplain-0.3.6 → codeplain-0.3.8}/install/powershell/install.ps1 +5 -1
- {codeplain-0.3.6 → codeplain-0.3.8}/module_renderer.py +3 -2
- codeplain-0.3.8/path_resolution.py +64 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/plain2code.py +6 -10
- {codeplain-0.3.6 → codeplain-0.3.8}/plain2code_arguments.py +200 -99
- codeplain-0.3.8/plain2code_cli.md +78 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/plain2code_console.py +34 -22
- {codeplain-0.3.6 → codeplain-0.3.8}/plain2code_events.py +1 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/plain2code_logger.py +13 -22
- {codeplain-0.3.6 → codeplain-0.3.8}/plain2code_state.py +17 -1
- {codeplain-0.3.6 → codeplain-0.3.8}/plain2code_utils.py +17 -13
- {codeplain-0.3.6 → codeplain-0.3.8}/plain_file.py +39 -28
- {codeplain-0.3.6 → codeplain-0.3.8}/pyproject.toml +11 -8
- {codeplain-0.3.6 → codeplain-0.3.8}/render_machine/actions/create_dist.py +2 -2
- {codeplain-0.3.6 → codeplain-0.3.8}/render_machine/actions/exit_with_error.py +2 -1
- {codeplain-0.3.6 → codeplain-0.3.8}/render_machine/actions/fix_conformance_test.py +4 -2
- {codeplain-0.3.6 → codeplain-0.3.8}/render_machine/actions/render_functional_requirement.py +4 -3
- {codeplain-0.3.6 → codeplain-0.3.8}/render_machine/render_context.py +5 -3
- {codeplain-0.3.6 → codeplain-0.3.8}/render_machine/render_utils.py +14 -8
- {codeplain-0.3.6 → codeplain-0.3.8}/requirements.txt +6 -6
- codeplain-0.3.8/system_config.py +68 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/test_scripts/run_conformance_tests_cypress.ps1 +30 -19
- {codeplain-0.3.6 → codeplain-0.3.8}/test_scripts/run_conformance_tests_cypress.sh +6 -2
- {codeplain-0.3.6 → codeplain-0.3.8}/test_scripts/run_conformance_tests_golang.ps1 +14 -5
- {codeplain-0.3.6 → codeplain-0.3.8}/test_scripts/run_conformance_tests_golang.sh +6 -6
- {codeplain-0.3.6 → codeplain-0.3.8}/test_scripts/run_conformance_tests_python.ps1 +11 -2
- {codeplain-0.3.6 → codeplain-0.3.8}/test_scripts/run_conformance_tests_python.sh +3 -3
- {codeplain-0.3.6 → codeplain-0.3.8}/test_scripts/run_unittests_flutter.ps1 +4 -1
- codeplain-0.3.8/test_scripts/run_unittests_flutter.sh +55 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/test_scripts/run_unittests_golang.ps1 +4 -1
- {codeplain-0.3.6 → codeplain-0.3.8}/test_scripts/run_unittests_golang.sh +3 -1
- {codeplain-0.3.6 → codeplain-0.3.8}/test_scripts/run_unittests_python.ps1 +4 -1
- {codeplain-0.3.6 → codeplain-0.3.8}/test_scripts/run_unittests_python.sh +3 -1
- {codeplain-0.3.6 → codeplain-0.3.8}/test_scripts/run_unittests_react.ps1 +4 -1
- {codeplain-0.3.6 → codeplain-0.3.8}/test_scripts/run_unittests_react.sh +3 -1
- codeplain-0.3.8/tests/test_arg_provenance.py +89 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/test_cli_output.py +2 -2
- codeplain-0.3.8/tests/test_console_log_styles.py +112 -0
- codeplain-0.3.8/tests/test_folder_path_resolution.py +165 -0
- codeplain-0.3.8/tests/test_log_file_name_resolution.py +89 -0
- codeplain-0.3.8/tests/test_logging_config_path_resolution.py +67 -0
- codeplain-0.3.8/tests/test_path_resolution.py +65 -0
- codeplain-0.3.8/tests/test_plain2code_state.py +36 -0
- codeplain-0.3.8/tests/test_plain2code_utils.py +36 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/test_plainfileparser.py +2 -2
- codeplain-0.3.8/tests/test_script_path_resolution.py +107 -0
- codeplain-0.3.8/tests/test_tui_usage.py +209 -0
- codeplain-0.3.8/tests/test_usage_summary.py +28 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tui/components.py +29 -20
- {codeplain-0.3.6 → codeplain-0.3.8}/tui/plain2code_tui.py +71 -2
- {codeplain-0.3.6 → codeplain-0.3.8}/tui/styles.css +4 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tui/widget_helpers.py +20 -1
- codeplain-0.3.8/usage_summary.py +30 -0
- codeplain-0.3.6/.github/workflows/publish-to-pypi.yml +0 -109
- codeplain-0.3.6/_version.py +0 -1
- codeplain-0.3.6/docs/plain2code_cli.md +0 -85
- codeplain-0.3.6/system_config.py +0 -34
- {codeplain-0.3.6 → codeplain-0.3.8}/.claude/settings.json +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/.flake8 +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/.github/dependabot.yml +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/.github/workflows/e2e.yml +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/.github/workflows/lint-and-test.yml +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/.github/workflows/nofity-slack-on-main-merge.yml +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/.github/workflows/publish-install-script.yml +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/.gitignore +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/.vscode/launch.json +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/.vscode/settings.json +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/CLAUDE.md +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/LICENSE +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/README.md +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/change_detection.py +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/cli_output/__init__.py +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/cli_output/dry_run.py +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/concept_utils.py +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/config/__init__.py +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/config/system_config.yaml +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/diff_utils.py +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/docs/generate_cli.py +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/docs/starting_a_plain_project_from_scratch.md +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/event_bus.py +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/examples/example_hello_world_golang/config.yaml +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/examples/example_hello_world_golang/harness_tests/hello_world_test.go +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/examples/example_hello_world_golang/hello_world_golang.plain +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/examples/example_hello_world_golang/run.sh +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/examples/example_hello_world_python/config.yaml +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/examples/example_hello_world_python/harness_tests/hello_world_display/test_hello_world.py +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/examples/example_hello_world_python/hello_world_python.plain +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/examples/example_hello_world_python/run.sh +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/examples/example_hello_world_react/config.yaml +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/examples/example_hello_world_react/harness_tests/hello_world_display/cypress/e2e/hello_world.cy.ts +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/examples/example_hello_world_react/harness_tests/hello_world_display/cypress/support/e2e.ts +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/examples/example_hello_world_react/harness_tests/hello_world_display/cypress.config.ts +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/examples/example_hello_world_react/harness_tests/hello_world_display/package.json +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/examples/example_hello_world_react/harness_tests/hello_world_display/tsconfig.json +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/examples/example_hello_world_react/hello_world_react.plain +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/examples/example_hello_world_react/run.sh +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/examples/run.sh +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/git_utils.py +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/install/bash/walkthrough.sh +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/install/powershell/walkthrough.ps1 +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/memory_management.py +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/partial_rendering.py +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/plain2code_exceptions.py +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/plain2code_nodes.py +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/plain2code_read_config.py +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/plain2code_telemetry.py +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/plain_modules.py +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/plain_spec.py +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/pytest.ini +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/render_machine/__init__.py +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/render_machine/actions/analyze_specification_ambiguity.py +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/render_machine/actions/base_action.py +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/render_machine/actions/commit_conformance_tests_changes.py +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/render_machine/actions/commit_implementation_code_changes.py +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/render_machine/actions/finish_functional_requirement.py +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/render_machine/actions/fix_unit_tests.py +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/render_machine/actions/prepare_repositories.py +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/render_machine/actions/prepare_testing_environment.py +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/render_machine/actions/refactor_code.py +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/render_machine/actions/render_conformance_tests.py +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/render_machine/actions/run_conformance_tests.py +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/render_machine/actions/run_unit_tests.py +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/render_machine/actions/summarize_conformance_tests.py +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/render_machine/code_renderer.py +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/render_machine/conformance_tests.py +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/render_machine/implementation_code_helpers.py +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/render_machine/render_types.py +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/render_machine/state_machine_config.py +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/render_machine/states.py +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/render_machine/triggers.py +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/resources/codeplain_overview.png +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/resources/plain_example.png +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/standard_template_library/golang-console-app-template.plain +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/standard_template_library/python-console-app-template.plain +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/standard_template_library/typescript-react-app-boilerplate.plain +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/standard_template_library/typescript-react-app-template.plain +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/__init__.py +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/conftest.py +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/data/acceptance_tests_warning/main_requiring_acceptance_tests.plain +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/data/acceptance_tests_warning/required_with_acceptance_tests.plain +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/data/imports/circular_imports_1.plain +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/data/imports/circular_imports_2.plain +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/data/imports/circular_imports_main.plain +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/data/imports/diamond_import_1.plain +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/data/imports/diamond_import_2.plain +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/data/imports/diamond_import_common.plain +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/data/imports/diamond_imports_main.plain +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/data/imports/import_with_functionalities.plain +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/data/imports/imports_module_with_functionalities.plain +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/data/imports/non_existent_import.plain +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/data/partial_rendering/pr_code_var.plain +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/data/partial_rendering/pr_implement.plain +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/data/partial_rendering/pr_leaf.plain +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/data/partial_rendering/pr_middle.plain +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/data/partial_rendering/pr_root.plain +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/data/partial_rendering/pr_solo.plain +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/data/plainfile/add_new_task_modal_specification.yaml +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/data/plainfile/duplicate_specification_heading.plain +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/data/plainfile/empty_functional_specs_section.plain +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/data/plainfile/invalid_specification_order.plain +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/data/plainfile/missing_non_functional_requirements.plain +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/data/plainfile/no_functional_specs_section.plain +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/data/plainfile/plain_source_with_absolute_link.plain +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/data/plainfile/plain_source_with_url_link.plain +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/data/plainfile/task_list_ui_specification.yaml +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/data/plainfile/task_manager_with_reference_links.plain +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/data/plainfile/without_non_functional_requirement.plain +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/data/plainfileparser/concept_validation_acceptance_tests.plain +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/data/plainfileparser/concept_validation_acceptance_tests_nondefined.plain +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/data/plainfileparser/concept_validation_defined_nondefined.plain +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/data/plainfileparser/concept_validation_defined_nondefined_2.plain +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/data/plainfileparser/concept_validation_definition.plain +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/data/plainfileparser/concept_validation_noconcepts.plain +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/data/plainfileparser/concept_validation_nonconcept.plain +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/data/plainfileparser/concept_validation_nondefined.plain +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/data/plainfileparser/concept_validation_redefinition.plain +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/data/plainfileparser/concept_validation_several_concepts.plain +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/data/plainfileparser/concept_validation_valid.plain +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/data/plainfileparser/exported_concepts.plain +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/data/plainfileparser/exported_concepts_base.plain +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/data/plainfileparser/exported_concepts_example.plain +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/data/plainfileparser/exported_concepts_missing.plain +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/data/plainfileparser/exported_concepts_missing_example.plain +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/data/plainfileparser/exported_concepts_nested.plain +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/data/plainfileparser/exported_concepts_nested_example.plain +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/data/plainfileparser/exported_concepts_transitive_example.plain +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/data/plainfileparser/exported_concepts_transitive_l1.plain +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/data/plainfileparser/exported_concepts_transitive_l2.plain +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/data/plainfileparser/plain_file_parser_with_comments.plain +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/data/plainfileparser/plain_file_with_comments_indented.plain +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/data/plainfileparser/regular_plain_source.plain +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/data/plainfileparser/required_concepts.plain +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/data/plainfileparser/required_concepts_defs.plain +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/data/plainfileparser/required_concepts_example.plain +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/data/plainfileparser/required_concepts_l1.plain +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/data/plainfileparser/required_concepts_l2.plain +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/data/plainfileparser/required_concepts_missing.plain +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/data/plainfileparser/required_concepts_module.plain +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/data/plainfileparser/required_concepts_partial.plain +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/data/plainfileparser/required_concepts_partial_duplicate.plain +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/data/plainfileparser/topological_sort.plain +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/data/plainfileparser/topological_sort_not_referenced.plain +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/data/requires/circular_requires_main.plain +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/data/requires/circular_requires_sub.plain +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/data/requires/diamond_requires_1.plain +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/data/requires/diamond_requires_2.plain +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/data/requires/diamond_requires_common.plain +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/data/requires/diamond_requires_main.plain +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/data/requires/independent_requires_1.plain +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/data/requires/independent_requires_2.plain +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/data/requires/independent_requires_main.plain +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/data/requires/non_existent_require.plain +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/data/requires/normal_requires_1.plain +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/data/requires/normal_requires_2.plain +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/data/requires/normal_requires_common.plain +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/data/requires/normal_requires_main.plain +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/data/sample_base64_image.txt +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/data/simple.plain +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/data/templates/block_level_include.plain +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/data/templates/code_variables.plain +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/data/templates/header.plain +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/data/templates/implement.plain +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/data/templates/implement_2.plain +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/data/templates/template_include.plain +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/data/templates/test_hardest_problem.plain +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/e2e/Dockerfile +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/e2e/conftest.py +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/e2e/test_hello_world_python.py +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/e2e/test_hello_world_python_windows.py +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/test_change_detection.py +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/test_file_utils.py +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/test_git_utils.py +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/test_imports.py +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/test_partial_rendering.py +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/test_plain2code.py +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/test_plain_modules.py +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/test_plainfile.py +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/test_plainspec.py +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/test_requires.py +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/test_resolve_config_file.py +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tests/test_telemetry.py +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tui/__init__.py +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tui/models.py +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tui/plain_module_render_choice_tui.py +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tui/spinner.py +0 -0
- {codeplain-0.3.6 → codeplain-0.3.8}/tui/state_handlers.py +0 -0
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
|
|
7
|
+
# Least privilege by default: jobs get no GITHUB_TOKEN scopes unless they
|
|
8
|
+
# opt in below.
|
|
9
|
+
permissions: {}
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
build:
|
|
13
|
+
name: Build distribution
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
permissions:
|
|
16
|
+
contents: write
|
|
17
|
+
|
|
18
|
+
steps:
|
|
19
|
+
- uses: actions/checkout@v4
|
|
20
|
+
with:
|
|
21
|
+
# hatch-vcs derives the version from git tags, so we need full history.
|
|
22
|
+
fetch-depth: 0
|
|
23
|
+
|
|
24
|
+
- name: Install uv
|
|
25
|
+
# uv provisions its own Python (honoring requires-python), so no
|
|
26
|
+
# separate actions/setup-python step is needed.
|
|
27
|
+
run: |
|
|
28
|
+
curl -LsSf https://astral.sh/uv/install.sh | sh
|
|
29
|
+
echo "$HOME/.local/bin" >> $GITHUB_PATH
|
|
30
|
+
|
|
31
|
+
- name: Build package
|
|
32
|
+
# hatch-vcs reads the version straight from the release tag.
|
|
33
|
+
run: |
|
|
34
|
+
uv build
|
|
35
|
+
echo "Built distributions:"
|
|
36
|
+
ls -l dist/
|
|
37
|
+
|
|
38
|
+
- name: Store the distribution packages
|
|
39
|
+
uses: actions/upload-artifact@v4
|
|
40
|
+
with:
|
|
41
|
+
name: python-package-distributions
|
|
42
|
+
path: dist/
|
|
43
|
+
|
|
44
|
+
- name: Upload assets to GitHub Release
|
|
45
|
+
env:
|
|
46
|
+
GH_TOKEN: ${{ github.token }}
|
|
47
|
+
run: |
|
|
48
|
+
gh release upload ${{ github.ref_name }} dist/* --clobber
|
|
49
|
+
|
|
50
|
+
publish-to-pypi:
|
|
51
|
+
name: Publish to PyPI
|
|
52
|
+
needs: build
|
|
53
|
+
runs-on: ubuntu-latest
|
|
54
|
+
environment:
|
|
55
|
+
name: pypi
|
|
56
|
+
url: https://pypi.org/p/codeplain
|
|
57
|
+
permissions:
|
|
58
|
+
# Mint a short-lived OIDC token so PyPI Trusted Publishing can
|
|
59
|
+
# authenticate this run — no long-lived API token needed.
|
|
60
|
+
id-token: write
|
|
61
|
+
|
|
62
|
+
steps:
|
|
63
|
+
- name: Download distribution packages
|
|
64
|
+
uses: actions/download-artifact@v4
|
|
65
|
+
with:
|
|
66
|
+
name: python-package-distributions
|
|
67
|
+
path: dist/
|
|
68
|
+
|
|
69
|
+
- name: Publish to PyPI
|
|
70
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: codeplain
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.8
|
|
4
4
|
Summary: Transform plain language specifications into working code
|
|
5
5
|
License-File: LICENSE
|
|
6
6
|
Classifier: Environment :: Console
|
|
@@ -8,23 +8,23 @@ Classifier: Intended Audience :: Developers
|
|
|
8
8
|
Classifier: Operating System :: OS Independent
|
|
9
9
|
Classifier: Topic :: Software Development :: Code Generators
|
|
10
10
|
Requires-Python: ==3.11.*
|
|
11
|
-
Requires-Dist: gitpython==3.1.
|
|
12
|
-
Requires-Dist: mistletoe==1.
|
|
11
|
+
Requires-Dist: gitpython==3.1.52
|
|
12
|
+
Requires-Dist: mistletoe==1.5.1
|
|
13
13
|
Requires-Dist: networkx==3.6.1
|
|
14
14
|
Requires-Dist: python-frontmatter==1.3.0
|
|
15
15
|
Requires-Dist: python-liquid2==0.4.0
|
|
16
16
|
Requires-Dist: pyyaml==6.0.3
|
|
17
17
|
Requires-Dist: requests==2.34.2
|
|
18
18
|
Requires-Dist: rich==15.0.0
|
|
19
|
-
Requires-Dist: sentry-sdk==2.
|
|
19
|
+
Requires-Dist: sentry-sdk==2.66.0
|
|
20
20
|
Requires-Dist: textual>=7.5.0
|
|
21
21
|
Requires-Dist: tiktoken==0.13.0
|
|
22
22
|
Requires-Dist: transitions==0.9.3
|
|
23
23
|
Provides-Extra: dev
|
|
24
|
-
Requires-Dist: black==26.
|
|
24
|
+
Requires-Dist: black==26.5.1; extra == 'dev'
|
|
25
25
|
Requires-Dist: flake8==7.3.0; extra == 'dev'
|
|
26
|
-
Requires-Dist: isort==
|
|
27
|
-
Requires-Dist: mypy==2.
|
|
26
|
+
Requires-Dist: isort==8.0.1; extra == 'dev'
|
|
27
|
+
Requires-Dist: mypy==2.3.0; extra == 'dev'
|
|
28
28
|
Requires-Dist: pytest==9.1.1; extra == 'dev'
|
|
29
29
|
Description-Content-Type: text/markdown
|
|
30
30
|
|
|
@@ -4,7 +4,7 @@ from typing import Optional
|
|
|
4
4
|
|
|
5
5
|
from plain2code_console import console
|
|
6
6
|
from plain2code_state import RunState
|
|
7
|
-
from
|
|
7
|
+
from usage_summary import format_usage_summary
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
def print_exit_summary(
|
|
@@ -24,7 +24,7 @@ def print_exit_summary(
|
|
|
24
24
|
msg += f" [#8E8F91]render id:\t\t\t[#FFFFFF]{run_state.render_id}\n"
|
|
25
25
|
msg += f" [#8E8F91]input file:\t\t\t[#FFFFFF]{spec_filename}\n"
|
|
26
26
|
msg += f" [#8E8F91]generated code folder:\t[#FFFFFF]{run_state.render_generated_code_path or '-'}\n\n"
|
|
27
|
-
msg +=
|
|
27
|
+
msg += format_usage_summary(run_state.rendered_functionalities, run_state.render_time_accumulated) + "\n"
|
|
28
28
|
console.print(msg)
|
|
29
29
|
|
|
30
30
|
if not run_state.render_succeeded and error_message:
|
|
@@ -32,7 +32,7 @@ def _display_credit_line(plan_credits: dict) -> None:
|
|
|
32
32
|
# If naive datetime, assume UTC
|
|
33
33
|
if dt.tzinfo is None:
|
|
34
34
|
dt = dt.replace(tzinfo=timezone.utc)
|
|
35
|
-
formatted_date = dt.strftime(
|
|
35
|
+
formatted_date = f"{dt.strftime('%b')} {dt.day}, {dt.year}"
|
|
36
36
|
|
|
37
37
|
# Check if expired
|
|
38
38
|
now = datetime.now(timezone.utc)
|
|
@@ -62,7 +62,7 @@ def _display_bucket_credit_line(bucket: dict, label: str) -> None:
|
|
|
62
62
|
# If naive datetime, assume UTC
|
|
63
63
|
if dt.tzinfo is None:
|
|
64
64
|
dt = dt.replace(tzinfo=timezone.utc)
|
|
65
|
-
formatted_date = dt.strftime(
|
|
65
|
+
formatted_date = f"{dt.strftime('%b')} {dt.day}, {dt.year}"
|
|
66
66
|
|
|
67
67
|
# Check if expired
|
|
68
68
|
now = datetime.now(timezone.utc)
|
|
@@ -5,6 +5,7 @@ import requests
|
|
|
5
5
|
from requests.exceptions import ConnectionError, RequestException, Timeout
|
|
6
6
|
|
|
7
7
|
import plain2code_exceptions
|
|
8
|
+
from plain2code_console import RETRY_COLOR
|
|
8
9
|
from plain2code_state import RunState
|
|
9
10
|
|
|
10
11
|
MAX_RETRIES = 4
|
|
@@ -67,8 +68,11 @@ class CodeplainAPI:
|
|
|
67
68
|
connection_error_type = "Network error" if is_connection_error else "Error"
|
|
68
69
|
if attempt < num_retries:
|
|
69
70
|
if not silent:
|
|
70
|
-
self.console.debug(
|
|
71
|
-
|
|
71
|
+
self.console.debug(
|
|
72
|
+
f"↻ {connection_error_type} on attempt {attempt + 1}/{num_retries + 1}: {error}. "
|
|
73
|
+
f"Retrying in {retry_delay} seconds...",
|
|
74
|
+
color=RETRY_COLOR,
|
|
75
|
+
)
|
|
72
76
|
time.sleep(retry_delay)
|
|
73
77
|
# Exponential backoff
|
|
74
78
|
return retry_delay * 2
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
# Plain2Code CLI Reference
|
|
2
|
+
|
|
3
|
+
```text
|
|
4
|
+
usage: generate_cli.py [-h] [--verbose] [--base-folder BASE_FOLDER]
|
|
5
|
+
[--build-folder BUILD_FOLDER]
|
|
6
|
+
[--log-to-file | --no-log-to-file]
|
|
7
|
+
[--log-file-name LOG_FILE_NAME]
|
|
8
|
+
[--config-name CONFIG_NAME]
|
|
9
|
+
[--render-range RENDER_RANGE |
|
|
10
|
+
--render-from RENDER_FROM] [--force-render]
|
|
11
|
+
[--unittests-script UNITTESTS_SCRIPT]
|
|
12
|
+
[--conformance-tests-folder CONFORMANCE_TESTS_FOLDER]
|
|
13
|
+
[--conformance-tests-script CONFORMANCE_TESTS_SCRIPT]
|
|
14
|
+
[--prepare-environment-script PREPARE_ENVIRONMENT_SCRIPT]
|
|
15
|
+
[--test-script-timeout TEST_SCRIPT_TIMEOUT]
|
|
16
|
+
[--api [API]] [--api-key API_KEY] [--full-plain]
|
|
17
|
+
[--dry-run] [--replay-with REPLAY_WITH]
|
|
18
|
+
[--template-dir TEMPLATE_DIR] [--copy-build]
|
|
19
|
+
[--build-dest BUILD_DEST] [--copy-conformance-tests]
|
|
20
|
+
[--conformance-tests-dest CONFORMANCE_TESTS_DEST]
|
|
21
|
+
[--render-machine-graph]
|
|
22
|
+
[--logging-config-path LOGGING_CONFIG_PATH]
|
|
23
|
+
[--headless]
|
|
24
|
+
filename
|
|
25
|
+
|
|
26
|
+
Render plain code to target code. Path arguments resolve based on where they
|
|
27
|
+
were written: values given on the command line are resolved against the
|
|
28
|
+
current working directory, values read from config.yaml are resolved against
|
|
29
|
+
the config file's directory, and defaults are resolved against the directory
|
|
30
|
+
containing the plain file. Absolute paths (and paths starting with '~') are
|
|
31
|
+
used as-is.
|
|
32
|
+
|
|
33
|
+
positional arguments:
|
|
34
|
+
filename Path to the plain file to render. The directory
|
|
35
|
+
containing this file has highest precedence for
|
|
36
|
+
template loading, so you can place custom templates
|
|
37
|
+
here to override the defaults. See --template-dir for
|
|
38
|
+
more details about template loading.
|
|
39
|
+
|
|
40
|
+
options:
|
|
41
|
+
-h, --help show this help message and exit
|
|
42
|
+
--verbose, -v Enable verbose output
|
|
43
|
+
--base-folder BASE_FOLDER
|
|
44
|
+
Base folder for the build files
|
|
45
|
+
--build-folder BUILD_FOLDER
|
|
46
|
+
Folder for build files
|
|
47
|
+
--log-to-file, --no-log-to-file
|
|
48
|
+
Enable logging to a file. Defaults to True. Set to
|
|
49
|
+
False to disable.
|
|
50
|
+
--log-file-name LOG_FILE_NAME
|
|
51
|
+
Name of the log file. Defaults to 'codeplain.log'. If
|
|
52
|
+
a file already exists at the resolved path, it will be
|
|
53
|
+
overwritten by the current logs.
|
|
54
|
+
--render-range RENDER_RANGE
|
|
55
|
+
Specify a range of functionalities to render (e.g. `1`
|
|
56
|
+
, `2`, `3`). Use comma to separate start and end IDs.
|
|
57
|
+
If only one functionality ID is provided, only that
|
|
58
|
+
functionality is rendered. Range is inclusive of both
|
|
59
|
+
start and end IDs.
|
|
60
|
+
--render-from RENDER_FROM
|
|
61
|
+
Continue generation starting from this specific
|
|
62
|
+
functionality (e.g. `2`). The functionality with this
|
|
63
|
+
ID will be included in the output. The functionality
|
|
64
|
+
ID must match one of the functionalities in your plain
|
|
65
|
+
file.
|
|
66
|
+
--force-render Force re-render of all the required modules.
|
|
67
|
+
--unittests-script UNITTESTS_SCRIPT
|
|
68
|
+
Shell script to run unit tests on generated code.
|
|
69
|
+
Receives the build folder path as its first argument
|
|
70
|
+
(default: 'plain_modules').
|
|
71
|
+
--conformance-tests-folder CONFORMANCE_TESTS_FOLDER
|
|
72
|
+
Folder for conformance test files
|
|
73
|
+
--conformance-tests-script CONFORMANCE_TESTS_SCRIPT
|
|
74
|
+
Path to conformance tests shell script. Every
|
|
75
|
+
conformance test script should accept two arguments:
|
|
76
|
+
1) Path to a folder (e.g. `plain_modules/module_name`)
|
|
77
|
+
containing generated source code, 2) Path to a
|
|
78
|
+
subfolder of the conformance tests folder (e.g.
|
|
79
|
+
`conformance_tests/subfoldername`) containing test
|
|
80
|
+
files.
|
|
81
|
+
--prepare-environment-script PREPARE_ENVIRONMENT_SCRIPT
|
|
82
|
+
Path to a shell script that prepares the testing
|
|
83
|
+
environment. The script should accept the source code
|
|
84
|
+
folder path as its first argument.
|
|
85
|
+
--test-script-timeout TEST_SCRIPT_TIMEOUT
|
|
86
|
+
Timeout for test scripts in seconds. If not provided,
|
|
87
|
+
the default timeout of 120 seconds is used.
|
|
88
|
+
--api [API] Alternative base URL for the API. Default:
|
|
89
|
+
`https://api.codeplain.ai`
|
|
90
|
+
--api-key API_KEY API key used to access the API. If not provided, the
|
|
91
|
+
`CODEPLAIN_API_KEY` environment variable is used.
|
|
92
|
+
--full-plain Full preview ***plain specification before code
|
|
93
|
+
generation.Use when you want to preview context of all
|
|
94
|
+
***plain primitives that are going to be included in
|
|
95
|
+
order to render the given module.
|
|
96
|
+
--dry-run Dry run preview of the code generation (without
|
|
97
|
+
actually making any changes).
|
|
98
|
+
--replay-with REPLAY_WITH
|
|
99
|
+
--template-dir TEMPLATE_DIR
|
|
100
|
+
Path to a custom template directory. Templates are
|
|
101
|
+
searched in the following order: 1) Directory
|
|
102
|
+
containing the plain file, 2) Custom template
|
|
103
|
+
directory (if provided through this argument), 3)
|
|
104
|
+
Built-in standard_template_library directory
|
|
105
|
+
--copy-build If set, copy the rendered contents of code in `--base-
|
|
106
|
+
folder` folder to `--build-dest` folder after
|
|
107
|
+
successful rendering.
|
|
108
|
+
--build-dest BUILD_DEST
|
|
109
|
+
Target folder to copy rendered contents of code to
|
|
110
|
+
(used only if --copy-build is set).
|
|
111
|
+
--copy-conformance-tests
|
|
112
|
+
If set, copy the conformance tests of code in
|
|
113
|
+
`--conformance-tests-folder` folder to `--conformance-
|
|
114
|
+
tests-dest` folder successful rendering. Requires
|
|
115
|
+
--conformance-tests-script.
|
|
116
|
+
--conformance-tests-dest CONFORMANCE_TESTS_DEST
|
|
117
|
+
Target folder to copy conformance tests of code to
|
|
118
|
+
(used only if --copy-conformance-tests is set).
|
|
119
|
+
--render-machine-graph
|
|
120
|
+
If set, render the state machine graph.
|
|
121
|
+
--logging-config-path LOGGING_CONFIG_PATH
|
|
122
|
+
Path to the logging configuration file.
|
|
123
|
+
--headless Run in headless mode: no TUI, no terminal output
|
|
124
|
+
except a single render-started message. All logs are
|
|
125
|
+
written to the log file.
|
|
126
|
+
|
|
127
|
+
configuration:
|
|
128
|
+
--config-name CONFIG_NAME
|
|
129
|
+
Name of the config file to look for. Looked up in the
|
|
130
|
+
plain file directory and the current working
|
|
131
|
+
directory. Defaults to config.yaml.
|
|
132
|
+
|
|
133
|
+
```
|
|
@@ -293,7 +293,7 @@ def get_template_directories(plain_file_path, custom_template_dir=None, default_
|
|
|
293
293
|
3. Default template directory - for standard/fallback templates
|
|
294
294
|
"""
|
|
295
295
|
template_dirs = [
|
|
296
|
-
os.path.dirname(plain_file_path), # Highest precedence - directory containing plain file
|
|
296
|
+
os.path.dirname(os.path.abspath(plain_file_path)), # Highest precedence - directory containing plain file
|
|
297
297
|
]
|
|
298
298
|
|
|
299
299
|
if custom_template_dir:
|
|
@@ -13,7 +13,7 @@ NC="${NC:-\033[0m}"
|
|
|
13
13
|
|
|
14
14
|
# Examples configuration
|
|
15
15
|
EXAMPLES_FOLDER_NAME="plainlang-examples"
|
|
16
|
-
EXAMPLES_DOWNLOAD_URL="https://
|
|
16
|
+
EXAMPLES_DOWNLOAD_URL="https://codeplain.ai/examples/unix"
|
|
17
17
|
|
|
18
18
|
# Show current directory and ask for extraction path
|
|
19
19
|
CURRENT_DIR=$(pwd)
|
|
@@ -55,18 +55,12 @@ if [ "$SKIP_DOWNLOAD" = false ]; then
|
|
|
55
55
|
if [ $? -eq 0 ] && [ -s "$TEMP_ZIP" ]; then
|
|
56
56
|
echo -e " ${GRAY}Extracting to ${EXTRACT_PATH}...${NC}"
|
|
57
57
|
|
|
58
|
-
# Extract the zip file
|
|
59
|
-
|
|
58
|
+
# Extract the zip file (contents are at the zip root, so extract into the target folder)
|
|
59
|
+
EXTRACTED_DIR="${EXTRACT_PATH}/${EXAMPLES_FOLDER_NAME}"
|
|
60
|
+
rm -rf "$EXTRACTED_DIR" 2>/dev/null # Remove existing if present
|
|
61
|
+
unzip -q -o "$TEMP_ZIP" -d "$EXTRACTED_DIR" 2>/dev/null
|
|
60
62
|
|
|
61
63
|
if [ $? -eq 0 ]; then
|
|
62
|
-
# Find and rename extracted directory to remove version number
|
|
63
|
-
EXTRACTED_DIR="${EXTRACT_PATH}/${EXAMPLES_FOLDER_NAME}"
|
|
64
|
-
VERSIONED_DIR=$(find "$EXTRACT_PATH" -maxdepth 1 -type d -name "${EXAMPLES_FOLDER_NAME}-*" | head -1)
|
|
65
|
-
if [ -n "$VERSIONED_DIR" ]; then
|
|
66
|
-
rm -rf "$EXTRACTED_DIR" 2>/dev/null # Remove existing if present
|
|
67
|
-
mv "$VERSIONED_DIR" "$EXTRACTED_DIR"
|
|
68
|
-
fi
|
|
69
|
-
|
|
70
64
|
# Remove the .gitignore file from the root of the extracted directory
|
|
71
65
|
if [ -f "${EXTRACTED_DIR}/.gitignore" ]; then
|
|
72
66
|
rm -f "${EXTRACTED_DIR}/.gitignore"
|
|
@@ -396,10 +396,12 @@ if [ -n "${CODEPLAIN_API_KEY:-}" ]; then
|
|
|
396
396
|
# Ensure the freshly installed tool is findable in this session.
|
|
397
397
|
export PATH="$HOME/.local/bin:$PATH"
|
|
398
398
|
echo -e "${GRAY}Verifying your installation...${NC}"
|
|
399
|
-
if codeplain --status
|
|
399
|
+
if verify_output=$(codeplain --status 2>&1); then
|
|
400
400
|
echo -e "${GREEN}✓${NC} Installation verified."
|
|
401
401
|
else
|
|
402
402
|
echo -e "${RED}Something went wrong during installation.${NC}"
|
|
403
|
+
echo -e "${GRAY}Output of 'codeplain --status':${NC}"
|
|
404
|
+
echo "$verify_output"
|
|
403
405
|
echo -e "${GRAY}Please restart your terminal and try again, or reinstall with:${NC}"
|
|
404
406
|
echo -e " uv tool install --force codeplain"
|
|
405
407
|
exit 1
|
|
@@ -11,7 +11,7 @@ if (-not $env:NC) { $NC = "$([char]27)[0m" } else
|
|
|
11
11
|
|
|
12
12
|
# Examples configuration
|
|
13
13
|
$EXAMPLES_FOLDER_NAME = "plainlang-examples"
|
|
14
|
-
$EXAMPLES_DOWNLOAD_URL = "https://
|
|
14
|
+
$EXAMPLES_DOWNLOAD_URL = "https://codeplain.ai/examples/windows"
|
|
15
15
|
|
|
16
16
|
# Show current directory and ask for extraction path
|
|
17
17
|
$CURRENT_DIR = Get-Location
|
|
@@ -58,18 +58,12 @@ if (-not $SKIP_DOWNLOAD) {
|
|
|
58
58
|
Write-Host " ${GRAY}Extracting to ${EXTRACT_PATH}...${NC}"
|
|
59
59
|
|
|
60
60
|
try {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
# Find and rename extracted directory to remove version number
|
|
61
|
+
# Extract the zip file (contents are at the zip root, so extract into the target folder)
|
|
64
62
|
$EXTRACTED_DIR = Join-Path $EXTRACT_PATH $EXAMPLES_FOLDER_NAME
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
if ($VERSIONED_DIR) {
|
|
68
|
-
if (Test-Path $EXTRACTED_DIR) {
|
|
69
|
-
Remove-Item -Path $EXTRACTED_DIR -Recurse -Force -ErrorAction SilentlyContinue
|
|
70
|
-
}
|
|
71
|
-
Rename-Item -Path $VERSIONED_DIR.FullName -NewName $EXAMPLES_FOLDER_NAME
|
|
63
|
+
if (Test-Path $EXTRACTED_DIR) {
|
|
64
|
+
Remove-Item -Path $EXTRACTED_DIR -Recurse -Force -ErrorAction SilentlyContinue
|
|
72
65
|
}
|
|
66
|
+
Expand-Archive -Path $TEMP_ZIP -DestinationPath $EXTRACTED_DIR -Force
|
|
73
67
|
|
|
74
68
|
# Remove the .gitignore file from the root of the extracted directory
|
|
75
69
|
$GITIGNORE_PATH = Join-Path $EXTRACTED_DIR ".gitignore"
|
|
@@ -426,16 +426,20 @@ if ($downloadExamples -notmatch '^[Nn]$') {
|
|
|
426
426
|
if ($env:CODEPLAIN_API_KEY) {
|
|
427
427
|
Write-Host "${GRAY}Verifying your installation...${NC}"
|
|
428
428
|
$verifyOk = $false
|
|
429
|
+
$verifyOutput = ""
|
|
429
430
|
try {
|
|
430
|
-
& codeplain --status
|
|
431
|
+
$verifyOutput = & codeplain --status 2>&1 | Out-String
|
|
431
432
|
$verifyOk = ($LASTEXITCODE -eq 0)
|
|
432
433
|
} catch {
|
|
434
|
+
$verifyOutput = $_ | Out-String
|
|
433
435
|
$verifyOk = $false
|
|
434
436
|
}
|
|
435
437
|
if ($verifyOk) {
|
|
436
438
|
Write-Host "${GREEN}✓${NC} Installation verified."
|
|
437
439
|
} else {
|
|
438
440
|
Write-Host "${RED}Something went wrong during installation.${NC}"
|
|
441
|
+
Write-Host "${GRAY}Output of 'codeplain --status':${NC}"
|
|
442
|
+
Write-Host $verifyOutput
|
|
439
443
|
Write-Host "${GRAY}Please restart your terminal and try again, or reinstall with:${NC}"
|
|
440
444
|
Write-Host " uv tool install --force codeplain"
|
|
441
445
|
exit 1
|
|
@@ -158,13 +158,14 @@ class ModuleRenderer:
|
|
|
158
158
|
module.wipe_module()
|
|
159
159
|
|
|
160
160
|
self.loaded_modules = list[PlainModule]()
|
|
161
|
+
|
|
161
162
|
_, rendering_failed = self._render_module(self.plain_module, self.render_range, True)
|
|
163
|
+
|
|
162
164
|
if not rendering_failed:
|
|
163
|
-
# Get the last module that completed rendering
|
|
164
165
|
if self.args.copy_build:
|
|
165
166
|
rendered_code_path = f"{self.args.build_dest}/"
|
|
166
167
|
else:
|
|
167
|
-
rendered_code_path =
|
|
168
|
+
rendered_code_path = self.args.build_folder
|
|
168
169
|
|
|
169
170
|
self.run_state.set_render_generated_code_path(rendered_code_path)
|
|
170
171
|
self.event_bus.publish(RenderCompleted(rendered_code_path=rendered_code_path))
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"""Path resolution for CLI / config / default path arguments.
|
|
2
|
+
|
|
3
|
+
The rule, in one sentence: the resolution base for a relative path is determined
|
|
4
|
+
by *where the value was written*, not by which option key it sets.
|
|
5
|
+
|
|
6
|
+
- Values supplied on the command line resolve against the current working
|
|
7
|
+
directory (so they match what shell tab completion just produced).
|
|
8
|
+
- Values read from ``config.yaml`` resolve against the directory containing
|
|
9
|
+
that config file.
|
|
10
|
+
- Values left at their default (not supplied anywhere) resolve against the
|
|
11
|
+
directory containing the spec file.
|
|
12
|
+
|
|
13
|
+
Paths are expanded for ``~`` and returned as absolute paths. Canonicalization
|
|
14
|
+
(symlink resolution) is left to the caller, to be done just before I/O that
|
|
15
|
+
needs it (writing output, executing scripts) so we don't accidentally
|
|
16
|
+
dereference links the user wanted preserved.
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
import os
|
|
20
|
+
from typing import Literal, Optional
|
|
21
|
+
|
|
22
|
+
PathSource = Literal["cli", "config", "default"]
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def resolve_path(
|
|
26
|
+
value: str,
|
|
27
|
+
source: PathSource,
|
|
28
|
+
*,
|
|
29
|
+
cwd: str,
|
|
30
|
+
config_dir: Optional[str] = None,
|
|
31
|
+
spec_dir: str,
|
|
32
|
+
) -> str:
|
|
33
|
+
"""Resolve *value* to an absolute path using the base anchor for *source*.
|
|
34
|
+
|
|
35
|
+
Args:
|
|
36
|
+
value: The path string as written by the user. May be absolute, relative,
|
|
37
|
+
or contain a leading ``~``.
|
|
38
|
+
source: Where the value came from -- ``"cli"``, ``"config"``, or
|
|
39
|
+
``"default"``.
|
|
40
|
+
cwd: Base directory for ``"cli"`` values.
|
|
41
|
+
config_dir: Base directory for ``"config"`` values. Must be provided
|
|
42
|
+
whenever ``source == "config"``.
|
|
43
|
+
spec_dir: Base directory for ``"default"`` values.
|
|
44
|
+
|
|
45
|
+
Returns:
|
|
46
|
+
Absolute path with ``~`` expanded. Symlinks are not resolved.
|
|
47
|
+
"""
|
|
48
|
+
expanded = os.path.expanduser(value)
|
|
49
|
+
|
|
50
|
+
if os.path.isabs(expanded):
|
|
51
|
+
return os.path.normpath(expanded)
|
|
52
|
+
|
|
53
|
+
if source == "cli":
|
|
54
|
+
base = cwd
|
|
55
|
+
elif source == "config":
|
|
56
|
+
if config_dir is None:
|
|
57
|
+
raise ValueError("config_dir must be provided when source == 'config'")
|
|
58
|
+
base = config_dir
|
|
59
|
+
elif source == "default":
|
|
60
|
+
base = spec_dir
|
|
61
|
+
else:
|
|
62
|
+
raise ValueError(f"Unknown path source: {source!r}")
|
|
63
|
+
|
|
64
|
+
return os.path.normpath(os.path.join(base, expanded))
|
|
@@ -48,7 +48,6 @@ from plain2code_logger import (
|
|
|
48
48
|
IndentedFormatter,
|
|
49
49
|
LoggingHandler,
|
|
50
50
|
dump_crash_logs,
|
|
51
|
-
get_log_file_path,
|
|
52
51
|
)
|
|
53
52
|
from plain2code_state import RunState
|
|
54
53
|
from plain2code_telemetry import capture_crash, initialize_telemetry
|
|
@@ -89,8 +88,7 @@ def setup_logging(
|
|
|
89
88
|
event_bus: EventBus,
|
|
90
89
|
run_state: RunState,
|
|
91
90
|
log_to_file: bool,
|
|
92
|
-
|
|
93
|
-
plain_file_path: Optional[str],
|
|
91
|
+
log_file_path: str,
|
|
94
92
|
headless: bool = False,
|
|
95
93
|
):
|
|
96
94
|
default_level = logging.DEBUG if args.verbose else logging.INFO
|
|
@@ -101,10 +99,9 @@ def setup_logging(
|
|
|
101
99
|
logging.getLogger("transitions").setLevel(logging.ERROR)
|
|
102
100
|
logging.getLogger("transitions.extensions.diagrams").setLevel(logging.ERROR)
|
|
103
101
|
|
|
104
|
-
log_file_path = get_log_file_path(plain_file_path, log_file_name)
|
|
105
|
-
|
|
106
102
|
# Try to load logging configuration from YAML file (takes precedence over --verbose)
|
|
107
103
|
config_loaded = False
|
|
104
|
+
|
|
108
105
|
if args.logging_config_path and os.path.exists(args.logging_config_path):
|
|
109
106
|
try:
|
|
110
107
|
with open(args.logging_config_path, "r") as f:
|
|
@@ -127,7 +124,7 @@ def setup_logging(
|
|
|
127
124
|
handler.setFormatter(formatter)
|
|
128
125
|
root_logger.addHandler(handler)
|
|
129
126
|
|
|
130
|
-
if log_to_file
|
|
127
|
+
if log_to_file:
|
|
131
128
|
try:
|
|
132
129
|
file_handler = logging.FileHandler(log_file_path, mode="w", encoding="utf-8")
|
|
133
130
|
file_handler.setFormatter(file_formatter)
|
|
@@ -289,6 +286,7 @@ def render( # noqa: C901
|
|
|
289
286
|
render_thread = threading.Thread(target=run_render, daemon=True)
|
|
290
287
|
app = Plain2CodeTUI(
|
|
291
288
|
event_bus=event_bus,
|
|
289
|
+
run_state=run_state,
|
|
292
290
|
on_ready=render_thread.start,
|
|
293
291
|
render_id=run_state.render_id,
|
|
294
292
|
unittests_script=args.unittests_script,
|
|
@@ -356,7 +354,7 @@ def main(): # noqa: C901
|
|
|
356
354
|
# Parse the plain file (and its required modules) once; reused by dry-run and rendering.
|
|
357
355
|
try:
|
|
358
356
|
plain_module = plain_modules.PlainModule(
|
|
359
|
-
args.filename,
|
|
357
|
+
os.path.basename(args.filename),
|
|
360
358
|
args.build_folder,
|
|
361
359
|
args.conformance_tests_folder,
|
|
362
360
|
template_dirs,
|
|
@@ -383,9 +381,7 @@ def main(): # noqa: C901
|
|
|
383
381
|
# Suppress Rich console output.
|
|
384
382
|
console.quiet = True
|
|
385
383
|
|
|
386
|
-
default_log_level = setup_logging(
|
|
387
|
-
args, event_bus, run_state, args.log_to_file, args.log_file_name, args.filename, args.headless
|
|
388
|
-
)
|
|
384
|
+
default_log_level = setup_logging(args, event_bus, run_state, args.log_to_file, args.log_file_name, args.headless)
|
|
389
385
|
|
|
390
386
|
initialize_telemetry()
|
|
391
387
|
|