diff --git a/_version.py b/_version.py index b5c9b6c..f3291e9 100644 --- a/_version.py +++ b/_version.py @@ -1 +1 @@ -__version__ = "0.2.12" +__version__ = "0.2.14" diff --git a/codeplain_REST_api.py b/codeplain_REST_api.py index 3fd9b1f..b17e600 100644 --- a/codeplain_REST_api.py +++ b/codeplain_REST_api.py @@ -156,11 +156,11 @@ def render_functional_requirement( run_state: RunState, ) -> dict[str, str]: """ - Renders the content of a functional requirement based on the provided ID, + Renders the content of a functionality based on the provided ID, corresponding sections from a Plain document, and existing files' content. Args: - frid (str): The unique identifier for the functional requirement to be rendered. + frid (str): The unique identifier for the functionality to be rendered. plain_source_tree (dict): A dictionary containing the plain source tree. linked_resources (dict): A dictionary where the keys represent filenames of linked resources and the values are dictionaries containing @@ -170,7 +170,7 @@ def render_functional_requirement( and the values are the content of those files. memory_files_content (dict): A dictionary where the keys represent memory filenames and the values are the content of those files. - module_name (str): The name of the module to render the functional requirement for. + module_name (str): The name of the module to render the functionality for. required_modules (dict): A dictionary where the keys represent module names and the values are lists of functionalities implemented in those modules. run_state (RunState): The current state of the rendering process. @@ -390,7 +390,7 @@ def render_acceptance_tests( Renders acceptance tests based on the provided parameters. Args: - frid (str): The unique identifier for the functional requirement. + frid (str): The unique identifier for the functionality. plain_source_tree (dict): A dictionary containing the plain source tree. linked_resources (dict): A dictionary where the keys represent resource names and the values are the content of those resources. diff --git a/docs/plain2code_cli.md b/docs/plain2code_cli.md index cc55bb5..373526b 100644 --- a/docs/plain2code_cli.md +++ b/docs/plain2code_cli.md @@ -27,10 +27,10 @@ options: Name of the log file. Defaults to 'codeplain.log'.Always resolved relative to the plain file directory.If file on this path already exists, the already existing log file will be overwritten by the current logs. --render-range RENDER_RANGE - Specify a range of functional requirements to render (e.g. `1` , `2`, `3`). Use comma to separate start and end IDs. If only one ID is provided, only that requirement is rendered. Range is + Specify a range of functionalities to render (e.g. `1` , `2`, `3`). Use comma to separate start and end IDs. If only one ID is provided, only that requirement is rendered. Range is inclusive of both start and end IDs. --render-from RENDER_FROM - Continue generation starting from this specific functional requirement (e.g. `2`). The requirement with this ID will be included in the output. The ID must match one of the functional requirements + Continue generation starting from this specific functionality (e.g. `2`). The requirement with this ID will be included in the output. The ID must match one of the functionalities in your plain file. --force-render Force re-render of all the required modules. --unittests-script UNITTESTS_SCRIPT diff --git a/git_utils.py b/git_utils.py index e0cb216..1140cca 100644 --- a/git_utils.py +++ b/git_utils.py @@ -7,22 +7,20 @@ import file_utils from plain2code_exceptions import InvalidGitRepositoryError -FUNCTIONAL_REQUIREMENT_IMPLEMENTED_COMMIT_MESSAGE = ( - "[Codeplain] Implemented code and unit tests for functional requirement {}" -) -REFACTORED_CODE_COMMIT_MESSAGE = "[Codeplain] Refactored code after implementing functional requirement {}" +FUNCTIONAL_REQUIREMENT_IMPLEMENTED_COMMIT_MESSAGE = "[Codeplain] Implemented code and unit tests for functionality {}" +REFACTORED_CODE_COMMIT_MESSAGE = "[Codeplain] Refactored code after implementing functionality {}" CONFORMANCE_TESTS_PASSED_COMMIT_MESSAGE = ( "[Codeplain] Fixed issues in the implementation code identified during conformance testing" ) # Following messages are used as checkpoints in the git history # Changing them will break backwards compatibility so change them with care -FUNCTIONAL_REQUIREMENT_FINISHED_COMMIT_MESSAGE = "[Codeplain] Functional requirement ID (FRID):{} fully implemented" +FUNCTIONAL_REQUIREMENT_FINISHED_COMMIT_MESSAGE = "[Codeplain] functionality ID (FRID):{} fully implemented" INITIAL_COMMIT_MESSAGE = "[Codeplain] Initial module commit" BASE_FOLDER_COMMIT_MESSAGE = "[Codeplain] Initialize build with Base Folder content" -RENDERED_FRID_MESSAGE = "Changes related to Functional requirement ID (FRID): {}" +RENDERED_FRID_MESSAGE = "Changes related to functionality ID (FRID): {}" MODULE_NAME_MESSAGE = "Module name: {}" RENDER_ID_MESSAGE = "Render ID: {}" @@ -244,7 +242,7 @@ def diff(repo_path: Union[str, os.PathLike], previous_frid: str = None) -> dict: Args: repo_path (str | os.PathLike): Path to the git repository - previous_frid (str): Functional requirement ID (FRID) of the previous commit + previous_frid (str): functionality ID (FRID) of the previous commit Returns: dict: Dictionary with file names as keys and their clean diff strings as values @@ -285,7 +283,7 @@ def _get_commit_with_frid(repo: Repo, frid: str, module_name: Optional[str] = No Args: repo (Repo): Git repository object - frid (str): Functional requirement ID + frid (str): functionality ID module_name (Optional[str]): Module name to filter by. If provided, only returns commits that have both the FRID and module name. diff --git a/plain2code.py b/plain2code.py index 4a60558..420032a 100644 --- a/plain2code.py +++ b/plain2code.py @@ -86,12 +86,12 @@ def _get_frids_range(plain_source, start, end=None): start = str(start) if start not in frids: - raise InvalidFridArgument(f"Invalid start functional requirement ID: {start}. Valid IDs are: {frids}.") + raise InvalidFridArgument(f"Invalid start functionality ID: {start}. Valid IDs are: {frids}.") if end is not None: end = str(end) if end not in frids: - raise InvalidFridArgument(f"Invalid end functional requirement ID: {end}. Valid IDs are: {frids}.") + raise InvalidFridArgument(f"Invalid end functionality ID: {end}. Valid IDs are: {frids}.") end_idx = frids.index(end) + 1 else: @@ -99,9 +99,7 @@ def _get_frids_range(plain_source, start, end=None): start_idx = frids.index(start) if start_idx >= end_idx: - raise InvalidFridArgument( - f"Start functional requirement ID: {start} must be before end functional requirement ID: {end}." - ) + raise InvalidFridArgument(f"Start functionality ID: {start} must be before end functionality ID: {end}.") return frids[start_idx:end_idx] diff --git a/plain2code_arguments.py b/plain2code_arguments.py index 3e3217f..de2b7b5 100644 --- a/plain2code_arguments.py +++ b/plain2code_arguments.py @@ -1,6 +1,5 @@ import argparse import os -import re from plain2code_console import console from plain2code_exceptions import AmbiguousConfigFileError @@ -59,14 +58,14 @@ def non_empty_string(s): def frid_string(s): - """Validate that the string contains only numbers separated by dots.""" + """Validate that the FRID is an integer.""" if not s: - raise argparse.ArgumentTypeError("The functional requirement ID cannot be empty.") + raise argparse.ArgumentTypeError("The functionality ID cannot be empty.") - if not re.match(r"^\d+(\.\d+)*$", s): - raise argparse.ArgumentTypeError( - "Functional requirement ID string must contain only numbers optionally separated by dots (e.g. '1', '1.2.3')" - ) + try: + int(s) + except ValueError: + raise argparse.ArgumentTypeError("Functionality ID string must be a number.") return s @@ -77,7 +76,7 @@ def frid_range_string(s): parts = s.split(",") if len(parts) > 2: - raise argparse.ArgumentTypeError("Range must contain at most two functional requirement IDs separated by comma") + raise argparse.ArgumentTypeError("Range must contain at most two functionality IDs separated by comma") for part in parts: frid_string(part) @@ -205,15 +204,15 @@ def create_parser(): render_range_group.add_argument( "--render-range", type=frid_range_string, - help="Specify a range of functional requirements to render (e.g. `1` , `2`, `3`). " - "Use comma to separate start and end IDs. If only one ID is provided, only that requirement is rendered. " + help="Specify a range of functionalities to render (e.g. `1` , `2`, `3`). " + "Use comma to separate start and end IDs. If only one ID is provided, only that functionality is rendered. " "Range is inclusive of both start and end IDs.", ) render_range_group.add_argument( "--render-from", type=frid_string, - help="Continue generation starting from this specific functional requirement (e.g. `2`). " - "The requirement with this ID will be included in the output. The ID must match one of the functional requirements in your plain file.", + help="Continue generation starting from this specific functionality (e.g. `2`). " + "The requirement with this ID will be included in the output. The ID must match one of the functionalities in your plain file.", ) parser.add_argument( diff --git a/plain2code_utils.py b/plain2code_utils.py index d094786..635fa79 100644 --- a/plain2code_utils.py +++ b/plain2code_utils.py @@ -6,8 +6,8 @@ AMBIGUITY_CAUSES = { "reference_resource_ambiguity": "Ambiguity is in the reference resources", "definition_ambiguity": "Ambiguity is in the definitions", - "non_functional_requirement_ambiguity": "Ambiguity is in the non-functional requirements", - "functional_requirement_ambiguity": "Ambiguity is in the functional requirements", + "non_functional_requirement_ambiguity": "Ambiguity is in the implementation reqs", + "functional_requirement_ambiguity": "Ambiguity is in the functionality", "other": "Ambiguity in the other parts of the specification", } @@ -23,7 +23,7 @@ def print_dry_run_output(plain_source_tree: dict, render_range: Optional[list[st functional_requirement_text = specifications[plain_spec.FUNCTIONAL_REQUIREMENTS][-1] console.info( "-------------------------------------\n" - f"Rendering functional requirement {frid}\n" + f"Rendering functionality {frid}\n" f"{functional_requirement_text}\n" "-------------------------------------\n" ) diff --git a/plain_file.py b/plain_file.py index 3e51abc..2b27187 100644 --- a/plain_file.py +++ b/plain_file.py @@ -136,7 +136,7 @@ def check_if_functional_requirements_are_specified(plain_source, non_functional_ found_functional_requirements = plain_spec.FUNCTIONAL_REQUIREMENTS in plain_source if found_functional_requirements and len(non_functional_requirements) == 0: - raise PlainSyntaxError("Syntax error: Functional requirement with no non-functional requirements specified.") + raise PlainSyntaxError("Syntax error: functionality with no implementation reqs specified.") return found_functional_requirements @@ -183,16 +183,16 @@ def _is_acceptance_test_heading(token) -> tuple[bool, str | None]: def _process_single_acceptance_test_requirement(functional_requirement: mistletoe.block_token.ListItem): """ - Process a single functional requirement to extract acceptance tests. + Process a single functionality to extract acceptance tests. Expected functional_requirement properties: - Is a list item - If acceptance tests are specified, it has 3 children: - - List item element with functional requirement instructions/text + - List item element with functionality instructions/text - Paragraph with `***Acceptance test:***` heading - List of acceptance tests - If acceptance tests are not specified, it has 1 child: - - List item element with functional requirement instructions/text + - List item element with functionality instructions/text """ new_children = [] functional_requirement_children = iter(functional_requirement.children) @@ -205,7 +205,7 @@ def _process_single_acceptance_test_requirement(functional_requirement: mistleto if acceptance_test_heading_problem: # Handle the case when the heading is not valid. This case includes cases such as: # - Writing `acceptance test` instead of `acceptance tests` (or any other syntax diffs). - # - Instead of specifying `acceptance tests` below the functional requirement, creator of the plain file + # - Instead of specifying `acceptance tests` below the functionality, creator of the plain file # might have specified some other building block (e.g. `implementation reqs`) raise PlainSyntaxError(acceptance_test_heading_problem) @@ -213,7 +213,7 @@ def _process_single_acceptance_test_requirement(functional_requirement: mistleto if acceptance_tests_found_already: # Handle edge case of duplicated ***acceptance tests*** heading raise PlainSyntaxError( - f"Syntax error at line {functional_requirement_child.line_number}: Duplicate 'acceptance tests' heading found within the same functional requirement. Only one block of acceptance tests is allowed per functional requirement." + f"Syntax error at line {functional_requirement_child.line_number}: Duplicate 'acceptance tests' heading found within the same functionality. Only one block of acceptance tests is allowed per functionality." ) try: @@ -237,20 +237,20 @@ def _process_single_acceptance_test_requirement(functional_requirement: mistleto # Regular token, keep it new_children.append(functional_requirement_child) - # Assign the children property to all the children of the functional requirement from previous, with exception + # Assign the children property to all the children of the functionality from previous, with exception # of those we parsed as acceptance tests functional_requirement.children = type(functional_requirement.children)(new_children) def process_acceptance_tests(plain_source): - # Early returns for cases without functional requirements + # Early returns for cases without functionalities if plain_spec.FUNCTIONAL_REQUIREMENTS not in plain_source: return frs = plain_source[plain_spec.FUNCTIONAL_REQUIREMENTS] if not hasattr(frs, "children"): return - # Process each functional requirement + # Process each functionality for functional_requirement in frs.children: if not hasattr(functional_requirement, "children"): continue @@ -343,7 +343,7 @@ def process_imports( ) if check_if_functional_requirements_are_specified(plain_file_parse_result.plain_source, []): - raise PlainSyntaxError("Imported module must not contain functional requirements.") + raise PlainSyntaxError("Imported module must not contain functionalities.") for specification_heading in plain_file_parse_result.plain_source: if specification_heading not in plain_spec.ALLOWED_IMPORT_SPECIFICATION_HEADINGS: @@ -649,7 +649,7 @@ def plain_file_parser( # noqa: C901 ) if not check_if_functional_requirements_are_specified(plain_file_parse_result.plain_source, []): - raise PlainSyntaxError("Syntax error: No functional requirements specified.") + raise PlainSyntaxError("Syntax error: No functionality specified.") exported_definitions = process_required_modules( plain_file_parse_result.required_modules, diff --git a/plain_spec.py b/plain_spec.py index 036ca7b..c5e938b 100644 --- a/plain_spec.py +++ b/plain_spec.py @@ -164,7 +164,7 @@ def get_next_frid(plain_source_tree, frid): if temp_frid == frid: return next(functional_requirements, None) - raise Exception(f"Functional requirement {frid} does not exist.") + raise Exception(f"Functionality {frid} does not exist.") def get_previous_frid(plain_source_tree, frid): @@ -175,7 +175,7 @@ def get_previous_frid(plain_source_tree, frid): previous_frid = temp_frid - raise Exception(f"Functional requirement {frid} does not exist.") + raise Exception(f"Functionality {frid} does not exist.") def get_frids_before(plain_source_tree, target_frid: str) -> list[str]: @@ -314,7 +314,7 @@ def get_specifications_for_frid(plain_source_tree, frid, replace_code_variables= replace_code_variables, ) if result is None: - raise Exception(f"Functional requirement {frid} does not exist.") + raise Exception(f"Functionality {frid} does not exist.") specifications = { DEFINITIONS: definitions, diff --git a/render_machine/actions/analyze_specification_ambiguity.py b/render_machine/actions/analyze_specification_ambiguity.py index 25a3d0c..a02e3b0 100644 --- a/render_machine/actions/analyze_specification_ambiguity.py +++ b/render_machine/actions/analyze_specification_ambiguity.py @@ -46,11 +46,11 @@ def execute(self, render_context: RenderContext, _previous_action_payload: Any | if rendering_analysis: # TODO: Before this output is exposed to the user, we should check the 'guidance' field using LLM in the same way as we do conflicting requirements. console.info( - f"Specification ambiguity detected! {AMBIGUITY_CAUSES[rendering_analysis['cause']]} of the functional requirement {render_context.frid_context.frid}." + f"Specification ambiguity detected! {AMBIGUITY_CAUSES[rendering_analysis['cause']]} of the functionality {render_context.frid_context.frid}." ) console.info(rendering_analysis["guidance"]) else: console.warning( - f"No specification ambiguity detected for functional requirement {render_context.frid_context.frid}." + f"No specification ambiguity detected for functionality {render_context.frid_context.frid}." ) return self.SUCCESSFUL_OUTCOME, None diff --git a/render_machine/actions/exit_with_error.py b/render_machine/actions/exit_with_error.py index 951ff38..0179734 100644 --- a/render_machine/actions/exit_with_error.py +++ b/render_machine/actions/exit_with_error.py @@ -18,7 +18,7 @@ def execute(self, render_context: RenderContext, previous_action_payload: Any | if render_context.frid_context is not None: console.info( - f"To continue rendering from the last successfully rendered functional requirement, provide the [red]--render-from {render_context.frid_context.frid}[/red] flag." + f"To continue rendering from the last successfully rendered functionality, provide the [red]--render-from {render_context.frid_context.frid}[/red] flag." ) if render_context.run_state.render_id is not None: diff --git a/render_machine/actions/fix_conformance_test.py b/render_machine/actions/fix_conformance_test.py index 4d0b046..076c195 100644 --- a/render_machine/actions/fix_conformance_test.py +++ b/render_machine/actions/fix_conformance_test.py @@ -17,7 +17,7 @@ class FixConformanceTest(BaseAction): def execute(self, render_context: RenderContext, previous_action_payload: Any | None): console.info( - f"Fixing conformance test for functional requirement {render_context.conformance_tests_running_context.current_testing_frid} in module {render_context.conformance_tests_running_context.current_testing_module_name}." + f"Fixing conformance test for functionality {render_context.conformance_tests_running_context.current_testing_frid} in module {render_context.conformance_tests_running_context.current_testing_module_name}." ) if not previous_action_payload.get("previous_conformance_tests_issue"): @@ -32,9 +32,9 @@ def execute(self, render_context: RenderContext, previous_action_payload: Any | ) if render_context.conformance_tests_running_context.current_testing_frid == render_context.frid_context.frid: - console_message = f"Fixing conformance test for functional requirement {render_context.conformance_tests_running_context.current_testing_frid} in module {render_context.conformance_tests_running_context.current_testing_module_name}." + console_message = f"Fixing conformance test for functionality {render_context.conformance_tests_running_context.current_testing_frid} in module {render_context.conformance_tests_running_context.current_testing_module_name}." else: - console_message = f"While implementing functional requirement {render_context.frid_context.frid}, conformance tests for functional requirement {render_context.conformance_tests_running_context.current_testing_frid} in module {render_context.conformance_tests_running_context.current_testing_module_name} broke. Fixing them..." + console_message = f"While implementing functionality {render_context.frid_context.frid}, conformance tests for functionality {render_context.conformance_tests_running_context.current_testing_frid} in module {render_context.conformance_tests_running_context.current_testing_module_name} broke. Fixing them..." existing_files, existing_files_content = ImplementationCodeHelpers.fetch_existing_files( render_context.build_folder diff --git a/render_machine/actions/fix_unit_tests.py b/render_machine/actions/fix_unit_tests.py index 190301e..8541a6e 100644 --- a/render_machine/actions/fix_unit_tests.py +++ b/render_machine/actions/fix_unit_tests.py @@ -34,7 +34,7 @@ def execute(self, render_context: RenderContext, previous_action_payload: Any | ) with console.status( - f"[{console.INFO_STYLE}]Fixing unit tests issue for functional requirement {render_context.frid_context.frid}...\n" + f"[{console.INFO_STYLE}]Fixing unit tests issue for functionality {render_context.frid_context.frid}...\n" ): response_files = render_context.codeplain_api.fix_unittests_issue( render_context.frid_context.frid, diff --git a/render_machine/actions/refactor_code.py b/render_machine/actions/refactor_code.py index 83be868..78bf068 100644 --- a/render_machine/actions/refactor_code.py +++ b/render_machine/actions/refactor_code.py @@ -27,7 +27,7 @@ def execute(self, render_context: RenderContext, _previous_action_payload: Any | style=console.INPUT_STYLE, ) with console.status( - f"[{console.INFO_STYLE}]Refactoring the generated code for functional requirement {render_context.frid_context.frid}..." + f"[{console.INFO_STYLE}]Refactoring the generated code for functionality {render_context.frid_context.frid}..." ): response_files = render_context.codeplain_api.refactor_source_files_if_needed( frid=render_context.frid_context.frid, diff --git a/render_machine/actions/render_conformance_tests.py b/render_machine/actions/render_conformance_tests.py index a14a252..89c8b5b 100644 --- a/render_machine/actions/render_conformance_tests.py +++ b/render_machine/actions/render_conformance_tests.py @@ -34,7 +34,7 @@ def _render_conformance_tests(self, render_context: RenderContext): if not render_context.conformance_tests_running_context.current_conformance_tests_exist(): with console.status( - f"[{console.INFO_STYLE}]Generating folder name for conformance tests for functional requirement {render_context.conformance_tests_running_context.current_testing_frid}...\n" + f"[{console.INFO_STYLE}]Generating folder name for conformance tests for functionality {render_context.conformance_tests_running_context.current_testing_frid}...\n" ): fr_subfolder_name = render_context.codeplain_api.generate_folder_name_from_functional_requirement( frid=render_context.conformance_tests_running_context.current_testing_frid, @@ -96,7 +96,7 @@ def _render_conformance_tests(self, render_context: RenderContext): all_acceptance_tests = render_context.frid_context.specifications.get(plain_spec.ACCEPTANCE_TESTS, []) with console.status( - f"[{console.INFO_STYLE}]Rendering conformance test for functional requirement {render_context.conformance_tests_running_context.current_testing_frid}...\n" + f"[{console.INFO_STYLE}]Rendering conformance test for functionality {render_context.conformance_tests_running_context.current_testing_frid}...\n" ): response_files, implementation_plan_summary = render_context.codeplain_api.render_conformance_tests( render_context.frid_context.frid, @@ -152,7 +152,7 @@ def _render_acceptance_test(self, render_context: RenderContext): console.info(f"Generating acceptance test:\n {acceptance_test}") with console.status( - f"[{console.INFO_STYLE}]Generating acceptance test for functional requirement {render_context.frid_context.frid}...\n" + f"[{console.INFO_STYLE}]Generating acceptance test for functionality {render_context.frid_context.frid}...\n" ): response_files = render_context.codeplain_api.render_acceptance_tests( render_context.frid_context.frid, diff --git a/render_machine/actions/render_functional_requirement.py b/render_machine/actions/render_functional_requirement.py index 069d576..8b15bef 100644 --- a/render_machine/actions/render_functional_requirement.py +++ b/render_machine/actions/render_functional_requirement.py @@ -41,7 +41,7 @@ def execute(self, render_context: RenderContext, _previous_action_payload: Any | ) with console.status( - f"[{console.INFO_STYLE}]Generating functional requirement {render_context.frid_context.frid}...\n" + f"[{console.INFO_STYLE}]Generating functionality {render_context.frid_context.frid}...\n" ): response_files = render_context.codeplain_api.render_functional_requirement( render_context.frid_context.frid, @@ -55,7 +55,7 @@ def execute(self, render_context: RenderContext, _previous_action_payload: Any | render_context.run_state, ) except FunctionalRequirementTooComplex as e: - error_message = f"The functional requirement:\n{render_context.frid_context.functional_requirement_text}\n is too complex to be implemented. Please break down the functional requirement into smaller parts ({str(e)})." + error_message = f"The functionality:\n{render_context.frid_context.functional_requirement_text}\n is too complex to be implemented. Please break down the functionality into smaller parts ({str(e)})." if e.proposed_breakdown: error_message += "\nProposed breakdown:" for _, part in e.proposed_breakdown["functional_requirements"].items(): diff --git a/render_machine/actions/run_conformance_tests.py b/render_machine/actions/run_conformance_tests.py index e6a8e58..ad1f683 100644 --- a/render_machine/actions/run_conformance_tests.py +++ b/render_machine/actions/run_conformance_tests.py @@ -34,7 +34,7 @@ def execute(self, render_context: RenderContext, _previous_action_payload: Any | console.info( f"Running conformance tests script {render_context.conformance_tests_script} " + f"for {conformance_tests_folder_name} (" - + f"functional requirement {render_context.conformance_tests_running_context.current_testing_frid} " + + f"functionality {render_context.conformance_tests_running_context.current_testing_frid} " + f"in module {render_context.conformance_tests_running_context.current_testing_module_name}" + ")." ) diff --git a/render_machine/actions/summarize_conformance_tests.py b/render_machine/actions/summarize_conformance_tests.py index 0e3bedc..e400d12 100644 --- a/render_machine/actions/summarize_conformance_tests.py +++ b/render_machine/actions/summarize_conformance_tests.py @@ -9,7 +9,7 @@ class SummarizeConformanceTests(BaseAction): SUCCESSFUL_OUTCOME = "conformance_tests_summarized" def execute(self, render_context: RenderContext, _previous_action_payload: Any | None): - console.info(f"Summarizing conformance tests for functional requirement {render_context.frid_context.frid}.") + console.info(f"Summarizing conformance tests for functionality {render_context.frid_context.frid}.") _, existing_conformance_test_files_content = ( render_context.conformance_tests.fetch_existing_conformance_test_files( @@ -21,7 +21,7 @@ def execute(self, render_context: RenderContext, _previous_action_payload: Any | ) with console.status( - f"[{console.INFO_STYLE}]Summarizing finished conformance tests for functional requirement {render_context.frid_context.frid}...\n" + f"[{console.INFO_STYLE}]Summarizing finished conformance tests for functionality {render_context.frid_context.frid}...\n" ): summary = render_context.codeplain_api.summarize_finished_conformance_tests( frid=render_context.frid_context.frid, diff --git a/render_machine/render_context.py b/render_machine/render_context.py index 6fc45f9..66522bd 100644 --- a/render_machine/render_context.py +++ b/render_machine/render_context.py @@ -172,7 +172,7 @@ def check_frid_iteration_limit(self): return if self.frid_context.functional_requirement_render_attempts >= MAX_CODE_GENERATION_RETRIES: - error_msg = f"Unittests could not be fixed after rendering the functional requirement {self.frid_context.frid} for the {MAX_CODE_GENERATION_RETRIES} times." + error_msg = f"Unittests could not be fixed after rendering the functionality {self.frid_context.frid} for the {MAX_CODE_GENERATION_RETRIES} times." self.dispatch_error(error_msg) self.frid_context.functional_requirement_render_attempts += 1 @@ -180,8 +180,8 @@ def check_frid_iteration_limit(self): if self.frid_context.functional_requirement_render_attempts > 1: # this if is intended just for logging console.info( - f"Unittests could not be fixed after rendering the functional requirement. " - f"Restarting rendering the functional requirement {self.frid_context.frid} from scratch." + f"Unittests could not be fixed after rendering the functionality. " + f"Restarting rendering the functionality {self.frid_context.frid} from scratch." ) def finish_implementing_frid(self): @@ -310,13 +310,13 @@ def start_fixing_unit_tests_in_conformance_tests(self): self.functional_requirements_render_attempts_failed_unit_during_conformance_tests >= MAX_FUNCTIONAL_REQUIREMENT_RENDER_ATTEMPTS_FAILED_UNIT_DURING_CONFORMANCE_TESTS ): - error_msg = f"Failed to adjust unit tests after implementation code was update while fixing conformance tests for functional requirement {self.frid_context.frid} for the {MAX_FUNCTIONAL_REQUIREMENT_RENDER_ATTEMPTS_FAILED_UNIT_DURING_CONFORMANCE_TESTS} times." + error_msg = f"Failed to adjust unit tests after implementation code was update while fixing conformance tests for functionality {self.frid_context.frid} for the {MAX_FUNCTIONAL_REQUIREMENT_RENDER_ATTEMPTS_FAILED_UNIT_DURING_CONFORMANCE_TESTS} times." self.dispatch_error(error_msg) else: console.info( - f"Failed to adjust unit tests after implementation code was update while fixing conformance tests for functional requirement {self.frid_context.frid}." + f"Failed to adjust unit tests after implementation code was update while fixing conformance tests for functionality {self.frid_context.frid}." ) - console.info(f"Restarting rendering the functional requirement {self.frid_context.frid} from scratch.") + console.info(f"Restarting rendering the functionality {self.frid_context.frid} from scratch.") self.machine.dispatch(triggers.RESTART_FRID_PROCESSING) def start_fixing_unit_tests_in_refactoring(self): @@ -336,7 +336,7 @@ def start_refactoring_code(self): if self.frid_context.refactoring_iteration >= MAX_REFACTORING_ITERATIONS: if self.verbose: console.info( - f"Refactoring iterations limit of {MAX_REFACTORING_ITERATIONS} reached for functional requirement {self.frid_context.frid}." + f"Refactoring iterations limit of {MAX_REFACTORING_ITERATIONS} reached for functionality {self.frid_context.frid}." ) self.machine.dispatch(triggers.PROCEED_FRID_PROCESSING) @@ -370,7 +370,7 @@ def start_conformance_tests_for_frid(self): if self.conformance_tests_running_context.regenerating_conformance_tests: if self.verbose: console.info( - f"Recreating conformance tests for functional requirement {self.conformance_tests_running_context.current_testing_frid}." + f"Recreating conformance tests for functionality {self.conformance_tests_running_context.current_testing_frid}." ) existing_conformance_tests_folder = self.conformance_tests_running_context.get_conformance_tests_json( diff --git a/tests/data/plainfile/invalid_specification_order.plain b/tests/data/plainfile/invalid_specification_order.plain index 61dcd85..a5d0f3d 100644 --- a/tests/data/plainfile/invalid_specification_order.plain +++ b/tests/data/plainfile/invalid_specification_order.plain @@ -1,7 +1,7 @@ > Example of a Plain file with invalid specification order. ***implementation reqs*** -- Test non-functional requirement +- Test implementation requirement ***definitions*** - Test definition diff --git a/tests/data/plainfile/missing_non_functional_requirements.plain b/tests/data/plainfile/missing_non_functional_requirements.plain index 6f3c0f1..8c4aa76 100644 --- a/tests/data/plainfile/missing_non_functional_requirements.plain +++ b/tests/data/plainfile/missing_non_functional_requirements.plain @@ -2,4 +2,4 @@ - Test definition ***functional specs*** -- Test functional requirement +- Test functionality diff --git a/tests/data/plainfile/without_non_functional_requirement.plain b/tests/data/plainfile/without_non_functional_requirement.plain index b8e3a33..1aca180 100644 --- a/tests/data/plainfile/without_non_functional_requirement.plain +++ b/tests/data/plainfile/without_non_functional_requirement.plain @@ -2,4 +2,4 @@ ***functional specs*** -- Simple functional requirement +- Simple functionality diff --git a/tests/data/plainfileparser/plain_file_parser_with_comments.plain b/tests/data/plainfileparser/plain_file_parser_with_comments.plain index b5df900..e1320b2 100644 --- a/tests/data/plainfileparser/plain_file_parser_with_comments.plain +++ b/tests/data/plainfileparser/plain_file_parser_with_comments.plain @@ -1,8 +1,8 @@ ***definitions*** ***implementation reqs*** ->- First non-functional requirement. -- Second non-functional requirement. +>- First implementation requirement. +- Second implementation requirement. ***functional specs*** - Display "hello, world" diff --git a/tests/data/plainfileparser/plain_file_with_comments_indented.plain b/tests/data/plainfileparser/plain_file_with_comments_indented.plain index 877c8e9..58faf5b 100644 --- a/tests/data/plainfileparser/plain_file_with_comments_indented.plain +++ b/tests/data/plainfileparser/plain_file_with_comments_indented.plain @@ -1,8 +1,8 @@ ***definitions*** ***implementation reqs*** -- First non-functional requirement. -- Second non-functional requirement. +- First implementation requirement. +- Second implementation requirement. > This is a comment diff --git a/tests/data/plainfileparser/regular_plain_source.plain b/tests/data/plainfileparser/regular_plain_source.plain index 954b898..71f673c 100644 --- a/tests/data/plainfileparser/regular_plain_source.plain +++ b/tests/data/plainfileparser/regular_plain_source.plain @@ -2,9 +2,9 @@ ***implementation reqs*** -- First non-functional requirement. +- First implementation requirement. -- Second non-functional requirement. +- Second implementation requirement. ***functional specs*** diff --git a/tests/data/requires/diamond_requires_common.plain b/tests/data/requires/diamond_requires_common.plain index a18962f..bd06f03 100644 --- a/tests/data/requires/diamond_requires_common.plain +++ b/tests/data/requires/diamond_requires_common.plain @@ -1,7 +1,7 @@ ***implementation reqs*** -- Base non-functional requirement. +- Base implementation requirement. ***functional specs*** -- A base functional requirement. \ No newline at end of file +- A base functionality. \ No newline at end of file diff --git a/tests/data/requires/normal_requires_common.plain b/tests/data/requires/normal_requires_common.plain index a18962f..bd06f03 100644 --- a/tests/data/requires/normal_requires_common.plain +++ b/tests/data/requires/normal_requires_common.plain @@ -1,7 +1,7 @@ ***implementation reqs*** -- Base non-functional requirement. +- Base implementation requirement. ***functional specs*** -- A base functional requirement. \ No newline at end of file +- A base functionality. \ No newline at end of file diff --git a/tests/data/simple.plain b/tests/data/simple.plain index 16dd5a1..81f440c 100644 --- a/tests/data/simple.plain +++ b/tests/data/simple.plain @@ -1,7 +1,7 @@ ***implementation reqs*** -- Simple non-functional requirement +- Simple implementation requirement ***functional specs*** -- Simple functional requirement +- Simple functionality diff --git a/tests/data/templates/code_variables.plain b/tests/data/templates/code_variables.plain index 55608c9..a290ec2 100644 --- a/tests/data/templates/code_variables.plain +++ b/tests/data/templates/code_variables.plain @@ -3,8 +3,8 @@ - :concept: is a concept. ***implementation reqs*** -- First non-functional requirement. -- Second non-functional requirement. +- First implementation requirement. +- Second implementation requirement. ***functional specs*** - Implement {% include "implement.plain", variable_name: "nice" %} diff --git a/tests/data/templates/header.plain b/tests/data/templates/header.plain index ce6e55d..c223f7a 100644 --- a/tests/data/templates/header.plain +++ b/tests/data/templates/header.plain @@ -3,5 +3,5 @@ - :concept: is a concept. ***implementation reqs*** -- First non-functional requirement {{variable_name_1 | code_variable}}. -- Second non-functional requirement {{variable_name_2 | code_variable}}. \ No newline at end of file +- First implementation requirement {{variable_name_1 | code_variable}}. +- Second implementation requirement {{variable_name_2 | code_variable}}. \ No newline at end of file diff --git a/tests/test_git_utils.py b/tests/test_git_utils.py index 0fc7b6f..226a442 100644 --- a/tests/test_git_utils.py +++ b/tests/test_git_utils.py @@ -322,7 +322,7 @@ def test_add_all_files_and_commit(temp_repo): # Verify commit message commit = commits[0] assert "Test commit" in commit.message - assert "Changes related to Functional requirement ID (FRID): FR123" in commit.message + assert "Changes related to functionality ID (FRID): FR123" in commit.message assert "Render ID: render-id" in commit.message # Verify files were committed @@ -334,12 +334,12 @@ def test_add_all_files_and_commit(temp_repo): repo = add_all_files_and_commit(temp_repo, "Commit changes on existing file", None, "FR4") commits = list(repo.iter_commits()) assert len(commits) == 4 - assert "Changes related to Functional requirement ID (FRID): FR4" in commits[0].message + assert "Changes related to functionality ID (FRID): FR4" in commits[0].message repo = add_all_files_and_commit(temp_repo, "Empty commit", None, "FR5") commits = list(repo.iter_commits()) assert len(commits) == 5 - assert "Changes related to Functional requirement ID (FRID): FR5" in commits[0].message + assert "Changes related to functionality ID (FRID): FR5" in commits[0].message def test_revert_changes(temp_repo): diff --git a/tests/test_plainfile.py b/tests/test_plainfile.py index 4980d46..d4e70fd 100644 --- a/tests/test_plainfile.py +++ b/tests/test_plainfile.py @@ -17,7 +17,7 @@ def __init__(self, *args, loose=False): def _create_mock_fr_content(content="Implement the entry point for ...", line_number=32): - """Helper to create a mock functional requirement content paragraph.""" + """Helper to create a mock functionality content paragraph.""" mock_fr_content_text = MagicMock(spec=RawText) mock_fr_content_text.content = content @@ -68,7 +68,7 @@ def _create_mock_at_list(content="The App shouldn't show logging...", line_numbe @patch("plain_file._process_single_acceptance_test_requirement") def test_process_acceptance_tests_no_functional_requirements_key(mock_process_single): - """Tests early return when functional requirements key is missing.""" + """Tests early return when functionality key is missing.""" plain_source_tree = {} process_acceptance_tests(plain_source_tree) @@ -88,7 +88,7 @@ def test_process_acceptance_tests_frs_lacks_children_attr(mock_process_single): @patch("plain_file._process_single_acceptance_test_requirement") def test_process_acceptance_tests_no_sections_direct_frs(mock_process_single): - """Tests processing of top-level functional requirements when no sections exist.""" + """Tests processing of top-level functionality when no sections exist.""" mock_fr_item1_with_children = MagicMock(name="FRItem1_WithChildren") mock_fr_item1_with_children.children = MagicMock(name="ChildrenOfFRItem1") @@ -139,7 +139,7 @@ def test_psart_no_acceptance_tests_present(): def test_psart_empty_children_list_in_fr(): - """Tests behavior when the functional requirement itself has no children.""" + """Tests behavior when the functionality itself has no children.""" functional_requirement_mock = MagicMock(spec=ListItem) functional_requirement_mock.line_number = 1 functional_requirement_mock.children = [] @@ -188,7 +188,7 @@ def test_psart_with_valid_acceptance_tests(): mock_at_heading_paragraph = _create_mock_at_heading_paragraph() mock_at_list = _create_mock_at_list() - # Set up children of the functional requirement + # Set up children of the functionality functional_requirement_mock.children = [mock_fr_content, mock_at_heading_paragraph, mock_at_list] is_acceptance_test_heading, acceptance_test_heading_problem = plain_file._is_acceptance_test_heading( @@ -220,7 +220,7 @@ def test_psart_with_invalid_acceptance_test_heading(): # Change the content of the raw text to be invalid mock_at_heading_paragraph.children[0].children[0].children[0].content = "Acceptance test" # missing colon - # Set up children of the functional requirement with just the invalid heading + # Set up children of the functionality with just the invalid heading functional_requirement_mock.children = [mock_at_heading_paragraph] # Verify that invalid heading is detected @@ -248,7 +248,7 @@ def test_psart_with_duplicate_acceptance_test_heading(): mock_at_heading_paragraph1 = _create_mock_at_heading_paragraph(line_number=34) mock_at_heading_paragraph2 = _create_mock_at_heading_paragraph(line_number=38) - # Set up children of the functional requirement with duplicate AT headings + # Set up children of the functionality with duplicate AT headings functional_requirement_mock.children = [ mock_fr_content, mock_at_heading_paragraph1, @@ -258,7 +258,7 @@ def test_psart_with_duplicate_acceptance_test_heading(): ] # Call the function under test and expect a PlainSyntaxError about duplicate headings - expected_error_message = f"Syntax error at line {mock_at_heading_paragraph2.line_number}: Duplicate 'acceptance tests' heading found within the same functional requirement. Only one block of acceptance tests is allowed per functional requirement." + expected_error_message = f"Syntax error at line {mock_at_heading_paragraph2.line_number}: Duplicate 'acceptance tests' heading found within the same functionality. Only one block of acceptance tests is allowed per functionality." with pytest.raises(PlainSyntaxError) as exc_info: plain_file._process_single_acceptance_test_requirement(functional_requirement_mock) diff --git a/tests/test_plainfileparser.py b/tests/test_plainfileparser.py index 7f374a3..90d6ddf 100644 --- a/tests/test_plainfileparser.py +++ b/tests/test_plainfileparser.py @@ -20,8 +20,8 @@ def test_regular_plain_source(get_test_data_path): assert plain_sections == { "definitions": [], "implementation reqs": [ - {"markdown": "- First non-functional requirement."}, - {"markdown": "- Second non-functional requirement."}, + {"markdown": "- First implementation requirement."}, + {"markdown": "- Second implementation requirement."}, ], "functional specs": [{"markdown": '- Display "hello, world"'}], } @@ -76,7 +76,7 @@ def test_plain_file_parser_with_comments(get_test_data_path): ) assert plain_sections == { "definitions": [], - "implementation reqs": [{"markdown": "- Second non-functional requirement."}], + "implementation reqs": [{"markdown": "- Second implementation requirement."}], "functional specs": [{"markdown": '- Display "hello, world"'}], } @@ -89,8 +89,8 @@ def test_plain_file_parser_with_comments_indented(get_test_data_path): assert plain_sections == { "definitions": [], "implementation reqs": [ - {"markdown": "- First non-functional requirement."}, - {"markdown": "- Second non-functional requirement."}, + {"markdown": "- First implementation requirement."}, + {"markdown": "- Second implementation requirement."}, ], "functional specs": [{"markdown": '- Display "hello, world"'}], } @@ -176,7 +176,7 @@ def test_duplicate_specification_heading(get_test_data_path): def test_missing_non_functional_requirements(get_test_data_path): with pytest.raises( Exception, - match="Syntax error: Functional requirement with no non-functional requirements specified.", + match="Syntax error: functionality with no implementation reqs specified.", ): plain_file.plain_file_parser( "missing_non_functional_requirements.plain", @@ -187,7 +187,7 @@ def test_missing_non_functional_requirements(get_test_data_path): def test_without_non_functional_requirement(get_test_data_path): with pytest.raises( Exception, - match="Syntax error: Functional requirement with no non-functional requirements specified.", + match="Syntax error: functionality with no implementation reqs specified.", ): plain_file.plain_file_parser( "without_non_functional_requirement.plain", @@ -203,8 +203,8 @@ def test_indented_include_tags(): - This is a definition. ***implementation reqs*** -- First non-functional requirement. -- Second non-functional requirement. +- First implementation requirement. +- Second implementation requirement. > This is a comment > This is a with an include tag {% include "template.plain" %} @@ -218,7 +218,7 @@ def test_indented_include_tags(): - Implement {% include "implement.plain" %} """ loaded_templates = { - "template.plain": "- This is a functional requirement inside a template.", + "template.plain": "- This is a functionality inside a template.", "implement.plain": """something nice and useful - the nice thing should be really nice - the useful thing should be really useful""", @@ -231,8 +231,8 @@ def test_indented_include_tags(): - This is a definition. ***implementation reqs*** -- First non-functional requirement. -- Second non-functional requirement. +- First implementation requirement. +- Second implementation requirement. > This is a comment > This is a with an include tag {% include 'template.plain' %} @@ -241,10 +241,10 @@ def test_indented_include_tags(): - Implement something nice and useful - the nice thing should be really nice - the useful thing should be really useful -- This is a functional requirement inside a template. +- This is a functionality inside a template. - Display "hello, world" - - This is a functional requirement inside a template. - - This is a functional requirement inside a template. + - This is a functionality inside a template. + - This is a functionality inside a template. - Implement something nice and useful - the nice thing should be really nice - the useful thing should be really useful @@ -289,8 +289,8 @@ def test_code_variables(load_test_data, get_test_data_path): - :concept: is a concept. ***implementation reqs*** -- First non-functional requirement. -- Second non-functional requirement. +- First implementation requirement. +- Second implementation requirement. ***functional specs*** - Implement something nice and useful @@ -304,8 +304,8 @@ def test_code_variables(load_test_data, get_test_data_path): expected_plain_source = { "definitions": [{"markdown": "- :concept: is a concept."}], "implementation reqs": [ - {"markdown": "- First non-functional requirement."}, - {"markdown": "- Second non-functional requirement."}, + {"markdown": "- First implementation requirement."}, + {"markdown": "- Second implementation requirement."}, ], "functional specs": [ { @@ -331,8 +331,8 @@ def test_code_variables(load_test_data, get_test_data_path): - :concept: is a concept. ***implementation reqs*** -- First non-functional requirement {keys[0]}. -- Second non-functional requirement {keys[1]}. +- First implementation requirement {keys[0]}. +- Second implementation requirement {keys[1]}. ***functional specs*** - Implement something nice and useful @@ -347,11 +347,11 @@ def test_code_variables(load_test_data, get_test_data_path): "definitions": [{"markdown": "- :concept: is a concept."}], "implementation reqs": [ { - "markdown": "- First non-functional requirement {{ variable_name_1 }}.", + "markdown": "- First implementation requirement {{ variable_name_1 }}.", "code_variables": [{"name": "variable_name_1", "value": "nice_1"}], }, { - "markdown": "- Second non-functional requirement {{ variable_name_1 }}.", + "markdown": "- Second implementation requirement {{ variable_name_1 }}.", "code_variables": [{"name": "variable_name_1", "value": "nice_2"}], }, ], diff --git a/tests/test_plainspec.py b/tests/test_plainspec.py index fa62263..83ee4bd 100644 --- a/tests/test_plainspec.py +++ b/tests/test_plainspec.py @@ -26,7 +26,7 @@ def test_get_first_functional_requirement_simple(get_test_data_path): def test_get_next_frid_not_exists(get_test_data_path): _, plain_source, _ = plain_file.plain_file_parser("simple.plain", [get_test_data_path("data/")]) - with pytest.raises(Exception, match="Functional requirement 2 does not exist."): + with pytest.raises(Exception, match="Functionality 2 does not exist."): plain_spec.get_next_frid(plain_source, "2") @@ -39,7 +39,7 @@ def test_get_next_frid_simple(get_test_data_path): def test_get_previous_frid_not_exists(get_test_data_path): _, plain_source, _ = plain_file.plain_file_parser("simple.plain", [get_test_data_path("data/")]) - with pytest.raises(Exception, match="Functional requirement 2 does not exist."): + with pytest.raises(Exception, match="Functionality 2 does not exist."): plain_spec.get_previous_frid(plain_source, "2") @@ -52,7 +52,7 @@ def test_get_previous_frid_no_previous_frid(get_test_data_path): def test_get_specifications_simple(get_test_data_path): _, plain_source, _ = plain_file.plain_file_parser("simple.plain", [get_test_data_path("data/")]) - with pytest.raises(Exception, match="Functional requirement a does not exist."): + with pytest.raises(Exception, match="Functionality a does not exist."): plain_spec.get_specifications_for_frid(plain_source, "a") frid = plain_spec.get_first_frid(plain_source) @@ -61,7 +61,7 @@ def test_get_specifications_simple(get_test_data_path): assert specifications == { "definitions": [], - "implementation reqs": ["- Simple non-functional requirement"], + "implementation reqs": ["- Simple implementation requirement"], "test reqs": [], - "functional specs": ["- Simple functional requirement"], + "functional specs": ["- Simple functionality"], } diff --git a/tui/state_handlers.py b/tui/state_handlers.py index d9eb2b3..7c578ee 100644 --- a/tui/state_handlers.py +++ b/tui/state_handlers.py @@ -195,7 +195,7 @@ def handle(self, segments: list[str], snapshot: RenderContextSnapshot, previous_ if segments[2] != States.POSTPROCESSING_CONFORMANCE_TESTS.value: if segments[2] == States.CONFORMANCE_TESTING_INITIALISED.value: if snapshot.conformance_tests_running_context.conformance_test_phase_index == 0: - rendering_text = f"Rendering conformance tests for functional requirement {snapshot.conformance_tests_running_context.current_testing_frid}" + rendering_text = f"Rendering conformance tests for functionality {snapshot.conformance_tests_running_context.current_testing_frid}" update_progress_item_substates( self.tui, TUIComponents.FRID_PROGRESS_CONFORMANCE_TEST.value, @@ -216,7 +216,7 @@ def handle(self, segments: list[str], snapshot: RenderContextSnapshot, previous_ [Substate("Preparing testing environment for conformance tests")], ) elif segments[2] == States.CONFORMANCE_TEST_ENV_PREPARED.value: - running_text = f"Running conformance tests for functional requirement {snapshot.conformance_tests_running_context.current_testing_frid}" + running_text = f"Running conformance tests for functionality {snapshot.conformance_tests_running_context.current_testing_frid}" if snapshot.conformance_tests_running_context.current_testing_module_name != snapshot.module_name: running_text += ( f" of module {snapshot.conformance_tests_running_context.current_testing_module_name}" @@ -226,7 +226,7 @@ def handle(self, segments: list[str], snapshot: RenderContextSnapshot, previous_ self.tui, TUIComponents.FRID_PROGRESS_CONFORMANCE_TEST.value, [Substate(running_text)] ) elif segments[2] == States.CONFORMANCE_TEST_FAILED.value: - fixing_text = f"Fixing conformance tests for functional requirement {snapshot.conformance_tests_running_context.current_testing_frid}" + fixing_text = f"Fixing conformance tests for functionality {snapshot.conformance_tests_running_context.current_testing_frid}" if snapshot.conformance_tests_running_context.current_testing_module_name != snapshot.module_name: fixing_text += ( f" of module {snapshot.conformance_tests_running_context.current_testing_module_name}"