From bd6f9d8ffd27ad8172704484095021138d1aa84d Mon Sep 17 00:00:00 2001 From: JensDiemer Date: Thu, 9 Nov 2023 19:31:56 +0100 Subject: [PATCH] Bugfix "reverse" if context contains a list e.g.: `applied_migrations` is a list ;) --- README.md | 3 +- manageprojects/__init__.py | 2 +- manageprojects/cli/cli_app.py | 4 ++ manageprojects/cookiecutter_generator.py | 52 ++++++++++++++----- manageprojects/cookiecutter_templates.py | 2 + .../tests/test_cookiecutter_generator.py | 1 + 6 files changed, 49 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index e1c4ff5..5d76e1e 100644 --- a/README.md +++ b/README.md @@ -321,7 +321,8 @@ See also git tags: https://github.com/jedie/manageprojects/tags [comment]: <> (✂✂✂ auto generated history start ✂✂✂) -* [**dev**](https://github.com/jedie/manageprojects/compare/v0.15.2...main) +* [v0.15.3](https://github.com/jedie/manageprojects/compare/v0.15.2...v0.15.3) + * 2023-11-09 - Bugfix "reverse" if context contains a list * 2023-11-07 - Update requirements * [v0.15.2](https://github.com/jedie/manageprojects/compare/v0.15.1...v0.15.2) * 2023-11-01 - Update requirements diff --git a/manageprojects/__init__.py b/manageprojects/__init__.py index 8b92357..045fa68 100644 --- a/manageprojects/__init__.py +++ b/manageprojects/__init__.py @@ -3,5 +3,5 @@ Manage Python / Django projects """ -__version__ = '0.15.2' +__version__ = '0.15.3' __author__ = 'Jens Diemer ' diff --git a/manageprojects/cli/cli_app.py b/manageprojects/cli/cli_app.py index 36c8de5..6525823 100644 --- a/manageprojects/cli/cli_app.py +++ b/manageprojects/cli/cli_app.py @@ -11,6 +11,7 @@ import rich_click as click from bx_py_utils.path import assert_is_dir, assert_is_file from cli_base.cli_tools.subprocess_utils import verbose_check_call +from cli_base.cli_tools.verbosity import OPTION_KWARGS_VERBOSE from cli_base.cli_tools.version_info import print_version from rich import print # noqa from rich_click import RichGroup @@ -281,10 +282,12 @@ def clone_project( **OPTION_ARGS_DEFAULT_FALSE, help='Overwrite existing files.', ) +@click.option('-v', '--verbosity', **OPTION_KWARGS_VERBOSE) def reverse( project_path: Path, destination: Path, overwrite: bool, + verbosity: int, ): """ Create a cookiecutter template from a managed project. @@ -298,6 +301,7 @@ def reverse( project_path=project_path, destination=destination, overwrite=overwrite, + verbosity=verbosity, ) diff --git a/manageprojects/cookiecutter_generator.py b/manageprojects/cookiecutter_generator.py index 23f7b1b..7045f00 100644 --- a/manageprojects/cookiecutter_generator.py +++ b/manageprojects/cookiecutter_generator.py @@ -26,23 +26,47 @@ def generate_reverse_info(*, cookiecutter_context: dict) -> tuple: return tuple(reverse_info) -def replace_path(*, path: Path, reverse_info: tuple) -> Path: - new_parts = [] - for part in path.parts: - for src_str, dst_str in reverse_info: - part = part.replace(src_str, dst_str) - new_parts.append(part) +def replace_str(content: str, reverse_info: tuple, verbosity: int = 0) -> str: + origin_content = content + for src_str, dst_str in reverse_info: + if isinstance(src_str, str) and isinstance(dst_str, str): + content = content.replace(src_str, dst_str) + elif verbosity > 2: + if not isinstance(src_str, str): + print(f'Ignore {src_str=} for {content=}') + if not isinstance(dst_str, str): + print(f'Ignore {dst_str=} for {content=}') + + if verbosity > 2 and content != origin_content: + print(f'Convert: {origin_content} -> {content}') + + return content + + +def replace_path(*, path: Path, reverse_info: tuple, verbosity: int = 0) -> Path: + new_parts = [replace_str(part, reverse_info=reverse_info, verbosity=verbosity) for part in path.parts] return Path(*new_parts) -def build_dst_path(*, source_path: Path, item: Path, destination: Path, reverse_info: tuple): +def build_dst_path( + *, + source_path: Path, + item: Path, + destination: Path, + reverse_info: tuple, + verbosity: int = 0, +): rel_path = item.relative_to(source_path) - new_path = replace_path(path=rel_path, reverse_info=reverse_info) + if verbosity > 1: + print(f'Store: {rel_path}', end=' ') + new_path = replace_path(path=rel_path, reverse_info=reverse_info, verbosity=verbosity) + if verbosity > 1: + print(f'-> {new_path}') dst_path = destination / new_path return dst_path -def copy_replaced(src_path, dst_path, reverse_info): +def copy_replaced(src_path, dst_path, reverse_info: tuple, verbosity: int = 0): dst_parent = dst_path.parent dst_parent.mkdir(parents=True, exist_ok=True) @@ -54,9 +78,7 @@ def copy_replaced(src_path, dst_path, reverse_info): print('copy as binary file') shutil.copy2(src_path, dst_path) else: - for src_str, dst_str in reverse_info: - content = content.replace(src_str, dst_str) - + content = replace_str(content, reverse_info=reverse_info, verbosity=verbosity) dst_path.write_text(content, encoding='UTF-8') @@ -66,6 +88,7 @@ def create_cookiecutter_template( destination: Path, cookiecutter_context: dict, overwrite: bool = False, + verbosity: int = 0, ): source_path = source_path.resolve() assert_is_dir(source_path) @@ -81,16 +104,19 @@ def create_cookiecutter_template( file_paths = git.ls_files(verbose=True) for item in file_paths: + if verbosity > 1: + print(f'Convert: {item}') dst_path = build_dst_path( source_path=source_path, item=item, destination=destination, reverse_info=reverse_info, + verbosity=verbosity, ) if item.is_dir(): dst_path.mkdir(parents=True, exist_ok=True) elif item.is_file(): print(item.relative_to(source_path), '->', dst_path) - copy_replaced(src_path=item, dst_path=dst_path, reverse_info=reverse_info) + copy_replaced(src_path=item, dst_path=dst_path, reverse_info=reverse_info, verbosity=verbosity) else: print(f'Ignore: {item}') diff --git a/manageprojects/cookiecutter_templates.py b/manageprojects/cookiecutter_templates.py index a38b5a9..c6fe560 100644 --- a/manageprojects/cookiecutter_templates.py +++ b/manageprojects/cookiecutter_templates.py @@ -255,6 +255,7 @@ def reverse_managed_project( project_path: Path, destination: Path, overwrite: bool = False, + verbosity: int = 0, ): """ Create a cookiecutter template from a managed project. @@ -275,4 +276,5 @@ def reverse_managed_project( destination=destination, cookiecutter_context=cookiecutter_context, overwrite=overwrite, + verbosity=verbosity, ) diff --git a/manageprojects/tests/test_cookiecutter_generator.py b/manageprojects/tests/test_cookiecutter_generator.py index 3617ab6..cab6e1c 100644 --- a/manageprojects/tests/test_cookiecutter_generator.py +++ b/manageprojects/tests/test_cookiecutter_generator.py @@ -58,6 +58,7 @@ def test_replace_path(self): reverse_info=( ('foo', '{{ package_name }}'), ('bar', '{{ dir_name }}'), + (['877e2ec', 'be3f649', 'c1a9d97'], '{{ cookiecutter.applied_migrations }}'), ), ) self.assertEqual(path, Path('{{ package_name }}/{{ dir_name }}/baz'))