diff --git a/tests/data/author/docs/a_folder/folder_level_1/folder_level_2-1/a_v1.md b/tests/data/author/docs/a_folder/folder_level_1/folder_level_2-1/a_v1.md new file mode 100644 index 000000000..8cf0b8460 --- /dev/null +++ b/tests/data/author/docs/a_folder/folder_level_1/folder_level_2-1/a_v1.md @@ -0,0 +1,14 @@ +--- +authors: tmp +owner: tmp +valid: + from: null + to: null +x-trestle-template-type: a +x-trestle-template-version: 1.0.0 +--- +# System architecture + +## Overview + +## Security model diff --git a/tests/data/author/docs/a_folder/folder_level_1/folder_level_2-1/a_v2.md b/tests/data/author/docs/a_folder/folder_level_1/folder_level_2-1/a_v2.md new file mode 100644 index 000000000..56aedd2ee --- /dev/null +++ b/tests/data/author/docs/a_folder/folder_level_1/folder_level_2-1/a_v2.md @@ -0,0 +1,14 @@ +--- +authors: tmp +owner: tmp +valid: + from: null + to: null +x-trestle-template-type: a +x-trestle-template-version: 2.0.0 +--- +# System architecture + +## Overview + +## Security model diff --git a/tests/data/author/docs/a_folder/folder_level_1/folder_level_2-1/b.md b/tests/data/author/docs/a_folder/folder_level_1/folder_level_2-1/b.md new file mode 100644 index 000000000..b6acf1d2a --- /dev/null +++ b/tests/data/author/docs/a_folder/folder_level_1/folder_level_2-1/b.md @@ -0,0 +1,17 @@ +--- +authors: tmp +owner: tmp +valid: + from: + to: +x-trestle-template-type: b +x-trestle-template-version: 1.1.1 +--- + +# Network architectures + +## External interconnections + +## Corporate interconnections + +## Out of scope interconnections diff --git a/tests/data/author/docs/a_folder/folder_level_1/folder_level_2-2/a_v3.md b/tests/data/author/docs/a_folder/folder_level_1/folder_level_2-2/a_v3.md new file mode 100644 index 000000000..d16998ff3 --- /dev/null +++ b/tests/data/author/docs/a_folder/folder_level_1/folder_level_2-2/a_v3.md @@ -0,0 +1,14 @@ +--- +authors: tmp +owner: tmp +valid: + from: null + to: null +x-trestle-template-type: a +x-trestle-template-version: 3.0.0 +--- +# System architecture + +## Overview + +## Security model diff --git a/tests/data/author/docs/a_folder/folder_level_1/folder_level_2-2/b.md b/tests/data/author/docs/a_folder/folder_level_1/folder_level_2-2/b.md new file mode 100644 index 000000000..4576e3e55 --- /dev/null +++ b/tests/data/author/docs/a_folder/folder_level_1/folder_level_2-2/b.md @@ -0,0 +1,17 @@ +--- +authors: tmp +owner: tmp +valid: + from: + to: +x-trestle-template-type: b +x-trestle-template-version: 1.0.0 +--- + +# Network architecture + +## External interconnections + +## Corporate interconnections + +## Out of scope interconnections diff --git a/tests/data/author/docs/a_folder_template/1.0.0/a.md b/tests/data/author/docs/a_folder_template/1.0.0/a.md new file mode 100644 index 000000000..8cf0b8460 --- /dev/null +++ b/tests/data/author/docs/a_folder_template/1.0.0/a.md @@ -0,0 +1,14 @@ +--- +authors: tmp +owner: tmp +valid: + from: null + to: null +x-trestle-template-type: a +x-trestle-template-version: 1.0.0 +--- +# System architecture + +## Overview + +## Security model diff --git a/tests/data/author/docs/a_folder_template/1.0.0/b.md b/tests/data/author/docs/a_folder_template/1.0.0/b.md new file mode 100644 index 000000000..4576e3e55 --- /dev/null +++ b/tests/data/author/docs/a_folder_template/1.0.0/b.md @@ -0,0 +1,17 @@ +--- +authors: tmp +owner: tmp +valid: + from: + to: +x-trestle-template-type: b +x-trestle-template-version: 1.0.0 +--- + +# Network architecture + +## External interconnections + +## Corporate interconnections + +## Out of scope interconnections diff --git a/tests/data/author/docs/a_folder_template/1.1.1/b.md b/tests/data/author/docs/a_folder_template/1.1.1/b.md new file mode 100644 index 000000000..b6acf1d2a --- /dev/null +++ b/tests/data/author/docs/a_folder_template/1.1.1/b.md @@ -0,0 +1,17 @@ +--- +authors: tmp +owner: tmp +valid: + from: + to: +x-trestle-template-type: b +x-trestle-template-version: 1.1.1 +--- + +# Network architectures + +## External interconnections + +## Corporate interconnections + +## Out of scope interconnections diff --git a/tests/data/author/docs/a_folder_template/2.0.0/a.md b/tests/data/author/docs/a_folder_template/2.0.0/a.md new file mode 100644 index 000000000..56aedd2ee --- /dev/null +++ b/tests/data/author/docs/a_folder_template/2.0.0/a.md @@ -0,0 +1,14 @@ +--- +authors: tmp +owner: tmp +valid: + from: null + to: null +x-trestle-template-type: a +x-trestle-template-version: 2.0.0 +--- +# System architecture + +## Overview + +## Security model diff --git a/tests/data/author/docs/a_folder_template/3.0.0/a.md b/tests/data/author/docs/a_folder_template/3.0.0/a.md new file mode 100644 index 000000000..d16998ff3 --- /dev/null +++ b/tests/data/author/docs/a_folder_template/3.0.0/a.md @@ -0,0 +1,14 @@ +--- +authors: tmp +owner: tmp +valid: + from: null + to: null +x-trestle-template-type: a +x-trestle-template-version: 3.0.0 +--- +# System architecture + +## Overview + +## Security model diff --git a/tests/trestle/core/commands/author/docs_test.py b/tests/trestle/core/commands/author/docs_test.py index 3a2db9e8a..f5c1d0d2e 100644 --- a/tests/trestle/core/commands/author/docs_test.py +++ b/tests/trestle/core/commands/author/docs_test.py @@ -721,3 +721,42 @@ def test_template_validate_flags_invalid_body( command_validate = 'trestle author docs template-validate -tn test_task -hv' execute_command_and_assert(command_validate, 1, monkeypatch) + + +def test_multiple_dif_templates_recursive( + testdata_dir: pathlib.Path, tmp_trestle_dir: pathlib.Path, monkeypatch: MonkeyPatch +) -> None: + """Test instance folder with multiple different template types inside a > 1 folder hierarchy.""" + task_template_folder = tmp_trestle_dir / '.trestle/author/test_task/' + test_template_folder = testdata_dir / 'author/docs/a_folder_template' + test_instances_folder = testdata_dir / 'author/docs/a_folder' + task_instance_folder = tmp_trestle_dir / 'test_task/' + + shutil.copytree(test_template_folder, task_template_folder) + + shutil.copytree(test_instances_folder, task_instance_folder) + + command_validate = 'trestle author docs validate -tn test_task -r -vtt' + execute_command_and_assert(command_validate, 0, monkeypatch) + + # Remove template type from instance and test to fail + task_markdown = task_instance_folder / 'folder_level_1/folder_level_2-1/a_v1.md' + md_api = MarkdownAPI() + header, tree = md_api.processor.process_markdown(task_markdown) + del header['x-trestle-template-type'] + + md_api.write_markdown_with_header(task_markdown, header, tree.content.raw_text) + + execute_command_and_assert(command_validate, 1, monkeypatch) + # set template type to arch-design again + header['x-trestle-template-type'] = 'a' + + # Modify template headeing from instance and test to fail + a_node = tree.get_node_for_key('# System architecture', True) + + assert a_node + + tree.content.raw_text = tree.content.raw_text.replace('# System architecture', '# Not the heading expected') + md_api.write_markdown_with_header(task_markdown, header, tree.content.raw_text) + + execute_command_and_assert(command_validate, 1, monkeypatch) diff --git a/trestle/core/commands/author/docs.py b/trestle/core/commands/author/docs.py index 75a02d381..f341cea38 100644 --- a/trestle/core/commands/author/docs.py +++ b/trestle/core/commands/author/docs.py @@ -84,6 +84,13 @@ def _init_arguments(self) -> None: action='store_true' ) + self.add_argument( + author_const.TEMPLATE_TYPE_VALIDATE_SHORT, + author_const.TEMPLATE_TYPE_VALIDATE_LONG, + help=author_const.TEMPLATE_TYPE_VALIDATE_HELP, + action='store_true' + ) + def _run(self, args: argparse.Namespace) -> int: try: status = 1 @@ -110,7 +117,8 @@ def _run(self, args: argparse.Namespace) -> int: args.recurse, args.readme_validate, args.template_version, - args.ignore + args.ignore, + args.validate_template_type ) return status @@ -199,7 +207,8 @@ def _validate_dir( recurse: bool, readme_validate: bool, template_version: Optional[str] = None, - ignore: Optional[str] = None + ignore: Optional[str] = None, + validate_by_type_field: bool = False ) -> int: """ Validate md files in a directory with option to recurse. @@ -238,7 +247,26 @@ def _validate_dir( versione_template_dir = TemplateVersioning.get_versioned_template_dir( self.template_dir, instance_version ) - template_file = versione_template_dir / self.template_name + # checks on naming template name out of type header if needed + if validate_by_type_field: + # get template name out of its type which essentially needs to be the same + template_name = md_api.processor.fetch_value_from_header( + item_path, author_const.TEMPLATE_TYPE_HEADER + ) + # throw an error if template type is not present + if template_name is None: + logger.error( + f'INVALID: Instance file {item_path} does not have' + f' {author_const.TEMPLATE_TYPE_HEADER}' + ' field in its header and can not be validated using optional parameter validate' + ' template type field' + ) + status = 1 + return status + template_name = template_name + '.md' + template_file = versione_template_dir / template_name + else: # continues regular flow without template type + template_file = versione_template_dir / self.template_name if not template_file.is_file(): raise TrestleError( f'Required template file: {self.rel_dir(template_file)} does not exist. Exiting.' @@ -265,7 +293,8 @@ def _validate_dir( recurse, readme_validate, template_version, - ignore + ignore, + validate_by_type_field ) if rc != 0: status = rc @@ -280,7 +309,8 @@ def validate( recurse: bool, readme_validate: bool, template_version: str, - ignore: str + ignore: str, + validate_by_type_field: bool ) -> int: """ Validate task. @@ -306,5 +336,6 @@ def validate( recurse, readme_validate, template_version, - ignore + ignore, + validate_by_type_field )