diff --git a/bx_py_utils/doc_write/README.md b/bx_py_utils/doc_write/README.md index 6e28af8..c2ef25e 100644 --- a/bx_py_utils/doc_write/README.md +++ b/bx_py_utils/doc_write/README.md @@ -47,7 +47,9 @@ Add a section `[tool.doc_write]` to your `pyproject.toml` to configure Doc-Write docstring_prefix = 'DocWrite:' output_base_path = './docs/' search_paths = ['./foo/', './bar/'] +delete_obsolete_files = false # Delete obsolete files in output_base_path ``` +Warning: Turn `delete_obsolete_files` only on if output_base_path is excursively used by Doc-Write. ### Howto @@ -68,6 +70,9 @@ Notes: * The created created Markdown file is relative to `output_base_path` (defined in `pyproject.toml`) +* If `delete_obsolete_files` is set to `true` in `pyproject.toml`, + then all `*.md` files in `output_base_path` that are not in `doc_paths` will be deleted. + * Headlines will be sorted, so they appears ordered by the level. * All Doc-String without the `{prefix}` will be ignored. diff --git a/bx_py_utils/doc_write/api.py b/bx_py_utils/doc_write/api.py index ffb784f..48b2329 100644 --- a/bx_py_utils/doc_write/api.py +++ b/bx_py_utils/doc_write/api.py @@ -37,6 +37,8 @@ class FooBar: def generate(base_path: Path | None = None) -> list[Path]: config: DocuwriteConfig = get_docu_write_cfg(base_path=base_path) + output_base_path: Path = config.output_base_path + doc_paths = [] docs_data = collect_docstrings(config=config) for rel_file_path, data in sorted(docs_data.items()): @@ -49,12 +51,25 @@ def generate(base_path: Path | None = None) -> list[Path]: docs.append('\n\n'.join(docstrings)) merged_doc = '\n\n'.join(docs) - """ DocWrite: bx_py_utils/doc_write/README.md ### Notes + """DocWrite: bx_py_utils/doc_write/README.md ### Notes * The created created Markdown file is relative to `output_base_path` (defined in `pyproject.toml`) """ - out_path = config.output_base_path / rel_file_path + out_path = output_base_path / rel_file_path logger.info('Write %s', out_path) out_path.parent.mkdir(parents=True, exist_ok=True) out_path.write_text(merged_doc, encoding='UTF-8') doc_paths.append(out_path) + + if config.delete_obsolete_files: + """DocWrite: bx_py_utils/doc_write/README.md ### Notes + * If `delete_obsolete_files` is set to `true` in `pyproject.toml`, + then all `*.md` files in `output_base_path` that are not in `doc_paths` will be deleted. + """ + current_files = set(doc_paths) + existing_files = set(output_base_path.rglob('**/*.md')) + obsolete_files = existing_files - current_files + for obsolete_file in obsolete_files: + logger.info('Delete %s', obsolete_files) + obsolete_file.unlink() + return doc_paths diff --git a/bx_py_utils/doc_write/cfg.py b/bx_py_utils/doc_write/cfg.py index 7e38a0f..550fbf8 100644 --- a/bx_py_utils/doc_write/cfg.py +++ b/bx_py_utils/doc_write/cfg.py @@ -24,13 +24,16 @@ class DocuwriteConfig: docstring_prefix = 'DocWrite:' output_base_path = './docs/' search_paths = ['./foo/', './bar/'] + delete_obsolete_files = false # Delete obsolete files in output_base_path ``` + Warning: Turn `delete_obsolete_files` only on if output_base_path is excursively used by Doc-Write. """ base_path: Path search_paths: list[Path] output_base_path: Path docstring_prefix: str = 'DocWrite:' + delete_obsolete_files: bool = False # Delete obsolete files in output_base_path def __post_init__(self): self.base_path = self.base_path.resolve(strict=True) diff --git a/bx_py_utils_tests/tests/test_doc_write_api.py b/bx_py_utils_tests/tests/test_doc_write_api.py index 75b91f4..9b4fde3 100644 --- a/bx_py_utils_tests/tests/test_doc_write_api.py +++ b/bx_py_utils_tests/tests/test_doc_write_api.py @@ -5,6 +5,7 @@ from bx_py_utils.doc_write.api import generate from bx_py_utils.doc_write.cfg import DocuwriteConfig, get_docu_write_cfg +from bx_py_utils.path import assert_is_file class DocuWriteApiTestCase(TestCase): @@ -71,11 +72,16 @@ def test_happy_path(self): ), ) + # Create an "obsolete" file: + obsolete_md_path = temp_path / 'docs/test/obsolete.md' + obsolete_md_path.parent.mkdir(parents=True, exist_ok=False) + obsolete_md_path.touch() + created_readme_path = temp_path / 'docs/test/README.md' self.assertIs(created_readme_path.exists(), False) doc_paths = generate(base_path=temp_path) self.assertEqual(doc_paths, [created_readme_path]) - generated_content = created_readme_path.read_text(encoding='UTF-8') + generated_content = created_readme_path.read_text() self.assertEqual( generated_content, inspect.cleandoc( @@ -92,3 +98,19 @@ def test_happy_path(self): """ ), ) + + # The default is not to delete obsolete files -> does it still exists? + assert_is_file(obsolete_md_path) + + # Activate deleting of obsolete files: + with pyproject_toml_path.open('a') as f: + f.write('\ndelete_obsolete_files = true\n') + + # Run again and delete obsolete files: + generate(base_path=temp_path) + + # Obsolete file removed? + self.assertIs(obsolete_md_path.exists(), False) + + # readme is still the same? + self.assertEqual(created_readme_path.read_text(), generated_content) diff --git a/pyproject.toml b/pyproject.toml index c5793ee..a33c598 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "bx_py_utils" -version = "90" +version = "91" description = "Various Python utility functions" homepage = "https://github.com/boxine/bx_py_utils/" authors = [