codeplain 0.3.11.dev12__tar.gz → 0.3.11.dev14__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.11.dev12 → codeplain-0.3.11.dev14}/.flake8 +2 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/PKG-INFO +1 -1
- codeplain-0.3.11.dev14/git_preflight.py +41 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/plain_file.py +31 -9
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/plain_modules.py +6 -6
- codeplain-0.3.11.dev14/tests/data/plainfileparser/cyclic_definitions.plain +9 -0
- codeplain-0.3.11.dev14/tests/data/plainfileparser/exported_concepts_defaults_exported.plain +13 -0
- codeplain-0.3.11.dev14/tests/data/plainfileparser/exported_concepts_imported_exported.plain +12 -0
- codeplain-0.3.11.dev14/tests/data/plainfileparser/exported_concepts_inherited_reexported.plain +15 -0
- codeplain-0.3.11.dev14/tests/data/plainfileparser/exported_concepts_malformed.plain +13 -0
- codeplain-0.3.11.dev14/tests/data/plainfileparser/exported_concepts_missing_definition.plain +14 -0
- codeplain-0.3.11.dev14/tests/data/plainfileparser/exported_concepts_missing_definition_example.plain +13 -0
- codeplain-0.3.11.dev14/tests/data/plainfileparser/exported_concepts_multiple_per_bullet.plain +14 -0
- codeplain-0.3.11.dev14/tests/data/plainfileparser/exported_concepts_multiple_per_bullet_undefined.plain +13 -0
- codeplain-0.3.11.dev14/tests/data/plainfileparser/exported_concepts_no_definitions.plain +10 -0
- codeplain-0.3.11.dev12/tests/data/plainfileparser/exported_concepts_missing_example.plain → codeplain-0.3.11.dev14/tests/data/plainfileparser/exported_concepts_not_declared_example.plain +1 -1
- codeplain-0.3.11.dev14/tests/test_git_preflight.py +98 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/test_plainfileparser.py +33 -20
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/.claude/settings.json +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/.github/dependabot.yml +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/.github/workflows/e2e.yml +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/.github/workflows/lint-and-test.yml +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/.github/workflows/lint-powershell.yml +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/.github/workflows/nofity-slack-on-main-merge.yml +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/.github/workflows/publish-dev-to-pypi.yml +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/.github/workflows/publish-install-script.yml +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/.github/workflows/publish-to-pypi.yml +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/.gitignore +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/.vscode/launch.json +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/.vscode/settings.json +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/CLAUDE.md +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/CONTRIBUTING.md +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/LICENSE +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/README.md +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/change_detection.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/cli_output/__init__.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/cli_output/dry_run.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/cli_output/render_summary.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/cli_output/status.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/codeplain_REST_api.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/concept_utils.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/config/__init__.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/config/system_config.yaml +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/conformance_fix_journal.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/diff_utils.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/docs/generate_cli.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/docs/plain2code_cli.md +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/docs/starting_a_plain_project_from_scratch.md +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/event_bus.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/examples/example_hello_world_golang/config.yaml +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/examples/example_hello_world_golang/harness_tests/hello_world_test.go +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/examples/example_hello_world_golang/hello_world_golang.plain +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/examples/example_hello_world_golang/run.sh +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/examples/example_hello_world_python/config.yaml +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/examples/example_hello_world_python/harness_tests/hello_world_display/test_hello_world.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/examples/example_hello_world_python/hello_world_python.plain +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/examples/example_hello_world_python/run.sh +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/examples/example_hello_world_react/config.yaml +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/examples/example_hello_world_react/harness_tests/hello_world_display/cypress/e2e/hello_world.cy.ts +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/examples/example_hello_world_react/harness_tests/hello_world_display/cypress/support/e2e.ts +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/examples/example_hello_world_react/harness_tests/hello_world_display/cypress.config.ts +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/examples/example_hello_world_react/harness_tests/hello_world_display/package.json +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/examples/example_hello_world_react/harness_tests/hello_world_display/tsconfig.json +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/examples/example_hello_world_react/hello_world_react.plain +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/examples/example_hello_world_react/run.sh +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/examples/run.sh +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/file_utils.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/git_utils.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/install/bash/examples.sh +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/install/bash/install.sh +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/install/bash/walkthrough.sh +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/install/powershell/examples.ps1 +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/install/powershell/install.ps1 +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/install/powershell/walkthrough.ps1 +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/memory_management.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/metadata_utils.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/module_renderer.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/partial_rendering.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/path_resolution.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/plain2code.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/plain2code_arguments.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/plain2code_cli.md +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/plain2code_console.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/plain2code_events.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/plain2code_exceptions.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/plain2code_logger.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/plain2code_nodes.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/plain2code_read_config.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/plain2code_state.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/plain2code_telemetry.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/plain2code_utils.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/plain_spec.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/pyproject.toml +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/pytest.ini +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/render_machine/__init__.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/render_machine/actions/analyze_specification_ambiguity.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/render_machine/actions/base_action.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/render_machine/actions/commit_conformance_tests_changes.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/render_machine/actions/commit_implementation_code_changes.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/render_machine/actions/create_dist.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/render_machine/actions/distill_conformance_test_memory.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/render_machine/actions/exit_with_error.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/render_machine/actions/finish_functional_requirement.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/render_machine/actions/fix_conformance_test.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/render_machine/actions/fix_unit_tests.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/render_machine/actions/prepare_repositories.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/render_machine/actions/prepare_testing_environment.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/render_machine/actions/refactor_code.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/render_machine/actions/render_conformance_tests.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/render_machine/actions/render_functional_requirement.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/render_machine/actions/run_conformance_tests.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/render_machine/actions/run_unit_tests.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/render_machine/actions/summarize_conformance_tests.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/render_machine/code_renderer.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/render_machine/conformance_tests.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/render_machine/implementation_code_helpers.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/render_machine/render_context.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/render_machine/render_types.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/render_machine/render_utils.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/render_machine/state_machine_config.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/render_machine/states.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/render_machine/triggers.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/requirements.txt +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/resources/codeplain_overview.png +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/resources/plain_example.png +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/standard_template_library/golang-console-app-template.plain +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/standard_template_library/python-console-app-template.plain +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/standard_template_library/typescript-react-app-boilerplate.plain +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/standard_template_library/typescript-react-app-template.plain +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/system_config.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/test_scripts/run_conformance_tests_cypress.ps1 +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/test_scripts/run_conformance_tests_cypress.sh +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/test_scripts/run_conformance_tests_golang.ps1 +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/test_scripts/run_conformance_tests_golang.sh +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/test_scripts/run_conformance_tests_python.ps1 +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/test_scripts/run_conformance_tests_python.sh +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/test_scripts/run_unittests_flutter.ps1 +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/test_scripts/run_unittests_flutter.sh +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/test_scripts/run_unittests_golang.ps1 +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/test_scripts/run_unittests_golang.sh +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/test_scripts/run_unittests_python.ps1 +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/test_scripts/run_unittests_python.sh +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/test_scripts/run_unittests_react.ps1 +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/test_scripts/run_unittests_react.sh +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/__init__.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/conftest.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/data/acceptance_tests_warning/main_requiring_acceptance_tests.plain +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/data/acceptance_tests_warning/required_with_acceptance_tests.plain +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/data/imports/circular_imports_1.plain +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/data/imports/circular_imports_2.plain +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/data/imports/circular_imports_main.plain +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/data/imports/diamond_import_1.plain +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/data/imports/diamond_import_2.plain +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/data/imports/diamond_import_common.plain +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/data/imports/diamond_imports_main.plain +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/data/imports/import_with_functionalities.plain +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/data/imports/imports_module_with_functionalities.plain +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/data/imports/non_existent_import.plain +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/data/partial_rendering/pr_code_var.plain +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/data/partial_rendering/pr_implement.plain +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/data/partial_rendering/pr_leaf.plain +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/data/partial_rendering/pr_middle.plain +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/data/partial_rendering/pr_root.plain +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/data/partial_rendering/pr_solo.plain +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/data/plainfile/add_new_task_modal_specification.yaml +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/data/plainfile/duplicate_specification_heading.plain +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/data/plainfile/empty_functional_specs_section.plain +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/data/plainfile/invalid_specification_order.plain +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/data/plainfile/missing_non_functional_requirements.plain +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/data/plainfile/no_functional_specs_section.plain +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/data/plainfile/plain_source_with_absolute_link.plain +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/data/plainfile/plain_source_with_url_link.plain +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/data/plainfile/task_list_ui_specification.yaml +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/data/plainfile/task_manager_with_reference_links.plain +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/data/plainfile/without_non_functional_requirement.plain +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/data/plainfileparser/concept_validation_acceptance_tests.plain +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/data/plainfileparser/concept_validation_acceptance_tests_nondefined.plain +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/data/plainfileparser/concept_validation_defined_nondefined.plain +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/data/plainfileparser/concept_validation_defined_nondefined_2.plain +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/data/plainfileparser/concept_validation_definition.plain +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/data/plainfileparser/concept_validation_noconcepts.plain +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/data/plainfileparser/concept_validation_nonconcept.plain +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/data/plainfileparser/concept_validation_nondefined.plain +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/data/plainfileparser/concept_validation_redefinition.plain +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/data/plainfileparser/concept_validation_several_concepts.plain +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/data/plainfileparser/concept_validation_valid.plain +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/data/plainfileparser/exported_concepts.plain +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/data/plainfileparser/exported_concepts_base.plain +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/data/plainfileparser/exported_concepts_example.plain +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/data/plainfileparser/exported_concepts_nested.plain +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/data/plainfileparser/exported_concepts_nested_example.plain +0 -0
- /codeplain-0.3.11.dev12/tests/data/plainfileparser/exported_concepts_missing.plain → /codeplain-0.3.11.dev14/tests/data/plainfileparser/exported_concepts_not_declared.plain +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/data/plainfileparser/exported_concepts_transitive_example.plain +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/data/plainfileparser/exported_concepts_transitive_l1.plain +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/data/plainfileparser/exported_concepts_transitive_l2.plain +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/data/plainfileparser/plain_file_parser_with_comments.plain +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/data/plainfileparser/plain_file_with_comments_indented.plain +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/data/plainfileparser/regular_plain_source.plain +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/data/plainfileparser/required_concepts.plain +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/data/plainfileparser/required_concepts_defs.plain +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/data/plainfileparser/required_concepts_example.plain +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/data/plainfileparser/required_concepts_l1.plain +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/data/plainfileparser/required_concepts_l2.plain +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/data/plainfileparser/required_concepts_missing.plain +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/data/plainfileparser/required_concepts_module.plain +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/data/plainfileparser/required_concepts_partial.plain +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/data/plainfileparser/required_concepts_partial_duplicate.plain +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/data/plainfileparser/topological_sort.plain +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/data/plainfileparser/topological_sort_not_referenced.plain +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/data/requires/circular_requires_main.plain +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/data/requires/circular_requires_sub.plain +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/data/requires/diamond_requires_1.plain +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/data/requires/diamond_requires_2.plain +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/data/requires/diamond_requires_common.plain +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/data/requires/diamond_requires_main.plain +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/data/requires/independent_requires_1.plain +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/data/requires/independent_requires_2.plain +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/data/requires/independent_requires_main.plain +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/data/requires/non_existent_require.plain +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/data/requires/normal_requires_1.plain +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/data/requires/normal_requires_2.plain +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/data/requires/normal_requires_common.plain +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/data/requires/normal_requires_main.plain +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/data/sample_base64_image.txt +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/data/simple.plain +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/data/templates/block_level_include.plain +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/data/templates/code_variables.plain +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/data/templates/header.plain +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/data/templates/implement.plain +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/data/templates/implement_2.plain +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/data/templates/template_include.plain +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/data/templates/test_hardest_problem.plain +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/e2e/Dockerfile +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/e2e/conftest.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/e2e/test_hello_world_python.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/e2e/test_hello_world_python_windows.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/test_arg_provenance.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/test_change_detection.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/test_cli_output.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/test_conformance_fix_journal.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/test_console_log_styles.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/test_distill_conformance_test_memory.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/test_dry_run_link_validation.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/test_file_utils.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/test_fix_unit_tests_conformance_context.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/test_folder_path_resolution.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/test_git_utils.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/test_headless_logging.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/test_imports.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/test_log_file_name_resolution.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/test_logging_config_path_resolution.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/test_partial_rendering.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/test_path_resolution.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/test_plain2code.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/test_plain2code_state.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/test_plain2code_utils.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/test_plain_modules.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/test_plainfile.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/test_plainspec.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/test_prepare_repositories_layout.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/test_requires.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/test_resolve_config_file.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/test_script_path_resolution.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/test_system_config.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/test_telemetry.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/test_tui_components.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/test_tui_usage.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tests/test_usage_summary.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tui/__init__.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tui/components.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tui/models.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tui/plain2code_tui.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tui/plain_module_render_choice_tui.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tui/spinner.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tui/state_handlers.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tui/styles.css +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/tui/widget_helpers.py +0 -0
- {codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/usage_summary.py +0 -0
|
@@ -20,6 +20,8 @@ exclude =
|
|
|
20
20
|
per-file-ignores =
|
|
21
21
|
__init__.py: F401
|
|
22
22
|
tests/*: U100
|
|
23
|
+
# require_git() runs between imports in plain_modules.py, so the imports below it trip E402
|
|
24
|
+
plain_modules.py: E402
|
|
23
25
|
max-complexity = 15
|
|
24
26
|
enable-extensions = U100
|
|
25
27
|
# Plugin-specific configuration
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"""Verify a working git is available before GitPython is imported.
|
|
2
|
+
|
|
3
|
+
GitPython probes for the git executable on import and raises from module scope
|
|
4
|
+
if it is missing or broken, so the CLI would crash with a traceback before
|
|
5
|
+
main() could explain it.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import shutil
|
|
9
|
+
import subprocess
|
|
10
|
+
import sys
|
|
11
|
+
|
|
12
|
+
from plain2code_console import console
|
|
13
|
+
|
|
14
|
+
GIT_MISSING_MESSAGE = "git is not installed. Please install git and try again."
|
|
15
|
+
GIT_BROKEN_MESSAGE = "git is installed but not working. Please repair your git installation and try again."
|
|
16
|
+
MACOS_BROKEN_GIT_HINT = (
|
|
17
|
+
"This usually means the Command Line Tools are missing; install them with 'xcode-select --install'."
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def git_runs(git_path):
|
|
22
|
+
"""Whether `git version` succeeds. A git on PATH can still be unusable: on
|
|
23
|
+
macOS without the Command Line Tools /usr/bin/git is a stub that exits with
|
|
24
|
+
an xcrun error, and GIT_PYTHON_REFRESH=quiet does not suppress that."""
|
|
25
|
+
try:
|
|
26
|
+
return subprocess.run([git_path, "version"], capture_output=True, timeout=10).returncode == 0
|
|
27
|
+
except (OSError, subprocess.SubprocessError):
|
|
28
|
+
return False
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def require_git():
|
|
32
|
+
"""Exit with a clean message unless a working git is available."""
|
|
33
|
+
git_path = shutil.which("git")
|
|
34
|
+
if git_path is None:
|
|
35
|
+
console.error(f"{GIT_MISSING_MESSAGE}\n")
|
|
36
|
+
sys.exit(1)
|
|
37
|
+
|
|
38
|
+
if not git_runs(git_path):
|
|
39
|
+
hint = f"\n{MACOS_BROKEN_GIT_HINT}" if sys.platform == "darwin" else ""
|
|
40
|
+
console.error(f"{GIT_BROKEN_MESSAGE}{hint}\n")
|
|
41
|
+
sys.exit(1)
|
|
@@ -615,15 +615,45 @@ def parse_plain_source( # noqa: C901
|
|
|
615
615
|
f"Plain syntax error: Syntax error at line {nested_acceptance_test_heading.line_number}: {plain_spec.ACCEPTANCE_TEST_HEADING} heading should be nested under specific functional spec."
|
|
616
616
|
)
|
|
617
617
|
|
|
618
|
+
defined_concepts = set[str]()
|
|
618
619
|
if plain_source[plain_spec.DEFINITIONS] is not None:
|
|
619
620
|
with PlainRenderer() as renderer:
|
|
620
621
|
for token in plain_source[plain_spec.DEFINITIONS].children:
|
|
621
622
|
rendered_token = renderer.render(token)
|
|
622
623
|
new_concepts, _ = concept_utils.extract_concepts_from_definition(rendered_token)
|
|
624
|
+
defined_concepts.update(new_concepts)
|
|
623
625
|
for concept in new_concepts:
|
|
624
626
|
if concept in required_concepts:
|
|
625
627
|
required_concepts.remove(concept)
|
|
626
628
|
|
|
629
|
+
if EXPORTED_CONCEPTS_DIRECTIVE in plain_source_obj.metadata:
|
|
630
|
+
module_name = modules_trace[-1] if modules_trace else None
|
|
631
|
+
subject = f"Module '{module_name}'" if module_name else "Module"
|
|
632
|
+
|
|
633
|
+
for entry in plain_source_obj.metadata[EXPORTED_CONCEPTS_DIRECTIVE]:
|
|
634
|
+
exported_concepts, errors = concept_utils.extract_concepts_from_definition(entry)
|
|
635
|
+
if errors:
|
|
636
|
+
raise PlainSyntaxError(
|
|
637
|
+
f"Plain syntax error: {subject} exports an invalid concept (`{entry}`). "
|
|
638
|
+
f"Expected a concept token, e.g. :ConceptName:."
|
|
639
|
+
)
|
|
640
|
+
|
|
641
|
+
for exported_concept in exported_concepts:
|
|
642
|
+
if exported_concept in concept_utils.DEFAULT_CONCEPTS:
|
|
643
|
+
raise PlainSyntaxError(
|
|
644
|
+
f"Plain syntax error: {subject} cannot export default concept {exported_concept}. "
|
|
645
|
+
f"Only user-defined concepts can be exported."
|
|
646
|
+
)
|
|
647
|
+
|
|
648
|
+
if exported_concept not in defined_concepts:
|
|
649
|
+
message = f"Plain syntax error: {subject} exports undefined concept {exported_concept}."
|
|
650
|
+
if REQUIRES_DIRECTIVE in plain_source_obj.metadata:
|
|
651
|
+
message += (
|
|
652
|
+
" An exported concept must be defined in this module's definitions or in an "
|
|
653
|
+
"imported module; a concept inherited through requires cannot be re-exported."
|
|
654
|
+
)
|
|
655
|
+
raise PlainSyntaxError(message)
|
|
656
|
+
|
|
627
657
|
required_modules = []
|
|
628
658
|
if REQUIRES_DIRECTIVE in plain_source_obj.metadata:
|
|
629
659
|
required_modules = plain_source_obj.metadata[REQUIRES_DIRECTIVE]
|
|
@@ -710,15 +740,7 @@ def process_required_modules(
|
|
|
710
740
|
if EXPORTED_CONCEPTS_DIRECTIVE in plain_file_parse_result.plain_source_obj.metadata:
|
|
711
741
|
exported_concepts = list[str]()
|
|
712
742
|
for concept in plain_file_parse_result.plain_source_obj.metadata[EXPORTED_CONCEPTS_DIRECTIVE]:
|
|
713
|
-
|
|
714
|
-
raise PlainSyntaxError(
|
|
715
|
-
f"Plain syntax error: Default concept cannot be exported: {concept}. Only user-defined concepts can be exported."
|
|
716
|
-
)
|
|
717
|
-
|
|
718
|
-
if isinstance(concept, str):
|
|
719
|
-
exported_concepts.extend(concept_utils.extract_concepts_from_definition(concept)[0])
|
|
720
|
-
else:
|
|
721
|
-
raise PlainSyntaxError(f"Plain syntax error: Invalid exported concept: {concept}.")
|
|
743
|
+
exported_concepts.extend(concept_utils.extract_concepts_from_definition(concept)[0])
|
|
722
744
|
|
|
723
745
|
with PlainRenderer() as renderer:
|
|
724
746
|
for exported_concept in exported_concepts:
|
|
@@ -6,18 +6,18 @@ import tempfile
|
|
|
6
6
|
import zipfile
|
|
7
7
|
from functools import cached_property
|
|
8
8
|
|
|
9
|
+
from git_preflight import require_git
|
|
9
10
|
from plain2code_exceptions import (
|
|
10
|
-
GitNotInstalledError,
|
|
11
11
|
InvalidModuleArchiveError,
|
|
12
12
|
MissingPreviousFunctionalitiesError,
|
|
13
13
|
ModuleDoesNotExistError,
|
|
14
14
|
)
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
16
|
+
# Must run before GitPython is imported, which raises on a missing or broken git.
|
|
17
|
+
require_git()
|
|
18
|
+
|
|
19
|
+
from git import Repo
|
|
20
|
+
from git.exc import NoSuchPathError
|
|
21
21
|
|
|
22
22
|
import file_utils
|
|
23
23
|
import git_utils
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
---
|
|
2
|
+
exported_concepts:
|
|
3
|
+
- :UnitTests:
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
***definitions***
|
|
7
|
+
- :NewConcept: is a new concept.
|
|
8
|
+
|
|
9
|
+
***implementation reqs***
|
|
10
|
+
- The :NewConcept: must be implemented.
|
|
11
|
+
|
|
12
|
+
***functional specs***
|
|
13
|
+
- Implement a wrapper for the :NewConcept: concept.
|
codeplain-0.3.11.dev14/tests/data/plainfileparser/exported_concepts_inherited_reexported.plain
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
---
|
|
2
|
+
requires:
|
|
3
|
+
- exported_concepts
|
|
4
|
+
exported_concepts:
|
|
5
|
+
- :Concept:
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
***definitions***
|
|
9
|
+
- :DependantConcept: depends on the :Concept: concept.
|
|
10
|
+
|
|
11
|
+
***implementation reqs***
|
|
12
|
+
- The :DependantConcept: concept must be implemented.
|
|
13
|
+
|
|
14
|
+
***functional specs***
|
|
15
|
+
- Implement a wrapper for the :DependantConcept: concept.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
---
|
|
2
|
+
exported_concepts:
|
|
3
|
+
- :NewConcept:
|
|
4
|
+
- :Concept:
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
***definitions***
|
|
8
|
+
- :NewConcept: is a new concept.
|
|
9
|
+
|
|
10
|
+
***implementation reqs***
|
|
11
|
+
- The :NewConcept: must be implemented.
|
|
12
|
+
|
|
13
|
+
***functional specs***
|
|
14
|
+
- Implement a wrapper for the :NewConcept: concept.
|
codeplain-0.3.11.dev14/tests/data/plainfileparser/exported_concepts_missing_definition_example.plain
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
---
|
|
2
|
+
requires:
|
|
3
|
+
- exported_concepts_missing_definition
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
***definitions***
|
|
7
|
+
- :AnotherConcept: is a new concept.
|
|
8
|
+
|
|
9
|
+
***implementation reqs***
|
|
10
|
+
- :AnotherConcept: must be implemented.
|
|
11
|
+
|
|
12
|
+
***functional specs***
|
|
13
|
+
- Implement a wrapper for the :AnotherConcept: concept.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
---
|
|
2
|
+
exported_concepts:
|
|
3
|
+
- :NewConcept:, :OtherConcept:
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
***definitions***
|
|
7
|
+
- :NewConcept: is a new concept.
|
|
8
|
+
- :OtherConcept: is another concept.
|
|
9
|
+
|
|
10
|
+
***implementation reqs***
|
|
11
|
+
- The :NewConcept: and :OtherConcept: concepts must be implemented.
|
|
12
|
+
|
|
13
|
+
***functional specs***
|
|
14
|
+
- Implement a wrapper for the :NewConcept: and :OtherConcept: concepts.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
---
|
|
2
|
+
exported_concepts:
|
|
3
|
+
- :NewConcept:, :OtherConcept:
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
***definitions***
|
|
7
|
+
- :NewConcept: is a new concept.
|
|
8
|
+
|
|
9
|
+
***implementation reqs***
|
|
10
|
+
- The :NewConcept: concept must be implemented.
|
|
11
|
+
|
|
12
|
+
***functional specs***
|
|
13
|
+
- Implement a wrapper for the :NewConcept: concept.
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
"""Regression tests for issue #133.
|
|
2
|
+
|
|
3
|
+
When git is unusable the CLI must report a clean message and exit 1, never dump
|
|
4
|
+
a traceback. The failure is at import time (GitPython raises from module scope
|
|
5
|
+
before main() runs), so the CLI is run in a subprocess and asserted on what a
|
|
6
|
+
user would actually see. sys.executable is launched by absolute path, so
|
|
7
|
+
replacing PATH only controls which git, if any, can be found.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
import os
|
|
11
|
+
import re
|
|
12
|
+
import subprocess
|
|
13
|
+
import sys
|
|
14
|
+
from pathlib import Path
|
|
15
|
+
|
|
16
|
+
import pytest
|
|
17
|
+
|
|
18
|
+
from git_preflight import GIT_BROKEN_MESSAGE, GIT_MISSING_MESSAGE
|
|
19
|
+
|
|
20
|
+
REPO_ROOT = Path(__file__).resolve().parents[1]
|
|
21
|
+
TRACEBACK_MARKER = "Traceback (most recent call last)"
|
|
22
|
+
|
|
23
|
+
# The crash was in the import chain, so it hit every entry point equally.
|
|
24
|
+
CLI_INVOCATIONS = [["--version"], ["--status"], ["does-not-exist.plain"]]
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def run_cli(args, path_dir=None):
|
|
28
|
+
"""Run the CLI and return its exit code and output, stripped of styling and
|
|
29
|
+
with whitespace collapsed, so assertions survive console line wrapping."""
|
|
30
|
+
env = os.environ.copy()
|
|
31
|
+
# Drop GitPython overrides so the PATH search decides whether git is found.
|
|
32
|
+
env.pop("GIT_PYTHON_GIT_EXECUTABLE", None)
|
|
33
|
+
env.pop("GIT_PYTHON_REFRESH", None)
|
|
34
|
+
env.setdefault("CODEPLAIN_API_KEY", "dummy")
|
|
35
|
+
if path_dir is not None:
|
|
36
|
+
env["PATH"] = str(path_dir)
|
|
37
|
+
|
|
38
|
+
result = subprocess.run(
|
|
39
|
+
[sys.executable, "plain2code.py", *args],
|
|
40
|
+
cwd=REPO_ROOT,
|
|
41
|
+
env=env,
|
|
42
|
+
capture_output=True,
|
|
43
|
+
text=True,
|
|
44
|
+
timeout=120,
|
|
45
|
+
)
|
|
46
|
+
output = re.sub(r"\x1b\[[0-9;]*m", "", result.stdout + result.stderr)
|
|
47
|
+
return result.returncode, " ".join(output.split())
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
@pytest.fixture
|
|
51
|
+
def no_git_dir(tmp_path):
|
|
52
|
+
"""A directory containing no git at all, used as the whole PATH."""
|
|
53
|
+
d = tmp_path / "no-git"
|
|
54
|
+
d.mkdir()
|
|
55
|
+
return d
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
@pytest.fixture
|
|
59
|
+
def broken_git_dir(tmp_path):
|
|
60
|
+
"""A directory whose git resolves but always fails, used as the whole PATH.
|
|
61
|
+
This is the shape of macOS without the Command Line Tools."""
|
|
62
|
+
d = tmp_path / "broken-git"
|
|
63
|
+
d.mkdir()
|
|
64
|
+
if sys.platform == "win32":
|
|
65
|
+
(d / "git.bat").write_text("@echo off\nexit /b 127\n")
|
|
66
|
+
else:
|
|
67
|
+
git = d / "git"
|
|
68
|
+
git.write_text("#!/bin/sh\nexit 127\n")
|
|
69
|
+
git.chmod(0o755)
|
|
70
|
+
return d
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
@pytest.mark.parametrize("args", CLI_INVOCATIONS)
|
|
74
|
+
def test_missing_git_reports_cleanly(args, no_git_dir):
|
|
75
|
+
rc, output = run_cli(args, no_git_dir)
|
|
76
|
+
|
|
77
|
+
assert GIT_MISSING_MESSAGE in output, output
|
|
78
|
+
assert TRACEBACK_MARKER not in output, output
|
|
79
|
+
# GitPython's own advice about GIT_PYTHON_REFRESH must not reach the user.
|
|
80
|
+
assert "GIT_PYTHON_REFRESH" not in output, output
|
|
81
|
+
assert rc == 1, output
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
@pytest.mark.parametrize("args", CLI_INVOCATIONS)
|
|
85
|
+
def test_broken_git_reports_cleanly(args, broken_git_dir):
|
|
86
|
+
rc, output = run_cli(args, broken_git_dir)
|
|
87
|
+
|
|
88
|
+
assert GIT_BROKEN_MESSAGE in output, output
|
|
89
|
+
assert GIT_MISSING_MESSAGE not in output, output
|
|
90
|
+
assert TRACEBACK_MARKER not in output, output
|
|
91
|
+
assert rc == 1, output
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def test_cli_works_when_git_is_present():
|
|
95
|
+
rc, output = run_cli(["--version"])
|
|
96
|
+
|
|
97
|
+
assert rc == 0, output
|
|
98
|
+
assert "codeplain version" in output, output
|
|
@@ -632,6 +632,11 @@ def test_concept_validation_acceptance_tests(get_test_data_path):
|
|
|
632
632
|
)
|
|
633
633
|
|
|
634
634
|
|
|
635
|
+
def test_concept_validation_cyclic_definitions(get_test_data_path):
|
|
636
|
+
with pytest.raises(PlainSyntaxError, match="cycles in the concept graph"):
|
|
637
|
+
plain_file.plain_file_parser("cyclic_definitions.plain", [get_test_data_path("data/plainfileparser")])
|
|
638
|
+
|
|
639
|
+
|
|
635
640
|
def test_required_concepts(get_test_data_path):
|
|
636
641
|
plain_file.plain_file_parser(
|
|
637
642
|
"required_concepts_example.plain",
|
|
@@ -661,28 +666,36 @@ def test_required_concepts(get_test_data_path):
|
|
|
661
666
|
)
|
|
662
667
|
|
|
663
668
|
|
|
664
|
-
|
|
665
|
-
|
|
669
|
+
@pytest.mark.parametrize(
|
|
670
|
+
"fixture",
|
|
671
|
+
[
|
|
666
672
|
"exported_concepts_example.plain",
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
plain_file.plain_file_parser(
|
|
673
|
+
"exported_concepts_imported_exported.plain",
|
|
674
|
+
"exported_concepts_multiple_per_bullet.plain",
|
|
671
675
|
"exported_concepts_nested_example.plain",
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
)
|
|
676
|
+
],
|
|
677
|
+
)
|
|
678
|
+
def test_exported_concepts_valid(get_test_data_path, fixture):
|
|
679
|
+
plain_file.plain_file_parser(fixture, [get_test_data_path("data/plainfileparser")])
|
|
680
|
+
|
|
681
|
+
|
|
682
|
+
@pytest.mark.parametrize(
|
|
683
|
+
("fixture", "expected_word"),
|
|
684
|
+
[
|
|
685
|
+
("exported_concepts_defaults_exported.plain", "cannot export default concept"),
|
|
686
|
+
("exported_concepts_inherited_reexported.plain", "cannot be re-exported"),
|
|
687
|
+
("exported_concepts_malformed.plain", "exports an invalid concept"),
|
|
688
|
+
("exported_concepts_missing_definition_example.plain", "'exported_concepts_missing_definition' exports"),
|
|
689
|
+
("exported_concepts_missing_definition.plain", "exports undefined concept"),
|
|
690
|
+
("exported_concepts_multiple_per_bullet_undefined.plain", "exports undefined concept"),
|
|
691
|
+
("exported_concepts_no_definitions.plain", "exports undefined concept"),
|
|
692
|
+
("exported_concepts_not_declared_example.plain", "not defined"),
|
|
693
|
+
("exported_concepts_transitive_example.plain", "not defined"),
|
|
694
|
+
],
|
|
695
|
+
)
|
|
696
|
+
def test_exported_concepts_invalid(get_test_data_path, fixture, expected_word):
|
|
697
|
+
with pytest.raises(PlainSyntaxError, match=expected_word):
|
|
698
|
+
plain_file.plain_file_parser(fixture, [get_test_data_path("data/plainfileparser")])
|
|
686
699
|
|
|
687
700
|
|
|
688
701
|
def test_topological_sort(get_test_data_path):
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/.github/workflows/nofity-slack-on-main-merge.yml
RENAMED
|
File without changes
|
|
File without changes
|
{codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/.github/workflows/publish-install-script.yml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/docs/starting_a_plain_project_from_scratch.md
RENAMED
|
File without changes
|
|
File without changes
|
{codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/examples/example_hello_world_golang/config.yaml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/examples/example_hello_world_golang/run.sh
RENAMED
|
File without changes
|
{codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/examples/example_hello_world_python/config.yaml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/examples/example_hello_world_python/run.sh
RENAMED
|
File without changes
|
{codeplain-0.3.11.dev12 → codeplain-0.3.11.dev14}/examples/example_hello_world_react/config.yaml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|