From c6a4b6d388a8281283ff8d42854bd99c83215ada Mon Sep 17 00:00:00 2001 From: Claudia Date: Sat, 6 Mar 2021 19:00:39 +0100 Subject: [PATCH] Improve template (see detailed commit message) Improve the Cookiecutter template in the following ways: - Make hello function echo the input - Add test for echoing the input - Add support for Python Fire - Add workaround for known issue [1] in Python Fire - Add workaround for an issue in the Code Runner extension - Add tasks for Visual Studio Code: - Show usage help (only if Python Fire is enabled) - Run hello - Run hello with an argument - Code Runner: ignore editor selection - Add option to skip installing dependencies [1] https://github.com/google/python-fire/issues/188#issuecomment-631419585 --- cookiecutter.json | 4 +- hooks/post_gen_project.py | 6 ++ .../.vscode/settings.json | 1 + .../.vscode/tasks.json | 68 +++++++++++++++++++ {{ cookiecutter.project_slug }}/Pipfile | 4 ++ .../src/fire_workarounds.py | 27 ++++++++ .../{{ cookiecutter.first_module_name }}.py | 19 +++++- ...st_{{ cookiecutter.first_module_name }}.py | 13 +++- 8 files changed, 136 insertions(+), 6 deletions(-) create mode 100644 {{ cookiecutter.project_slug }}/.vscode/tasks.json create mode 100644 {{ cookiecutter.project_slug }}/src/fire_workarounds.py diff --git a/cookiecutter.json b/cookiecutter.json index 1fb0c44..57d3ce9 100644 --- a/cookiecutter.json +++ b/cookiecutter.json @@ -7,5 +7,7 @@ "python_version": "3.9", "author_full_name": "", "copyright_holder_full_name": "{{ cookiecutter.author_full_name }}", - "use_pandas": "n" + "use_fire": "n", + "use_pandas": "n", + "install_dependencies_now": "y" } diff --git a/hooks/post_gen_project.py b/hooks/post_gen_project.py index a853c1a..5ef8bf0 100644 --- a/hooks/post_gen_project.py +++ b/hooks/post_gen_project.py @@ -5,6 +5,11 @@ os.unlink('.venv/.keep') shutil.rmtree('licenses') +{%- if cookiecutter.use_fire != "y" %} +os.unlink('src/fire_workarounds.py') +{%- endif %} + +{%- if cookiecutter.install_dependencies_now == "y" %} subprocess.run( 'pipenv install -d', env={ @@ -15,3 +20,4 @@ check=True, shell=True, ) +{%- endif %} diff --git a/{{ cookiecutter.project_slug }}/.vscode/settings.json b/{{ cookiecutter.project_slug }}/.vscode/settings.json index eeac632..01075a2 100644 --- a/{{ cookiecutter.project_slug }}/.vscode/settings.json +++ b/{{ cookiecutter.project_slug }}/.vscode/settings.json @@ -3,6 +3,7 @@ "python.linting.pylintEnabled": true, "python.linting.pylintPath": "./.venv/bin/pylint", "python.linting.enabled": true, + "code-runner.ignoreSelection": true, "code-runner.executorMap": { "python": "pipenv run python", }, diff --git a/{{ cookiecutter.project_slug }}/.vscode/tasks.json b/{{ cookiecutter.project_slug }}/.vscode/tasks.json new file mode 100644 index 0000000..432e8d7 --- /dev/null +++ b/{{ cookiecutter.project_slug }}/.vscode/tasks.json @@ -0,0 +1,68 @@ +{ + // See https://go.microsoft.com/fwlink/?LinkId=733558 + // for the documentation about the tasks.json format + "version": "2.0.0", + "tasks": [ + {%- if cookiecutter.use_fire == "y" %} + { + "label": "{{ cookiecutter.first_module_name }}: Show usage help", + "type": "process", + "command": "pipenv", + "args": [ + "run", + "{{ cookiecutter.first_module_name }}" + ], + "problemMatcher": [], + "group": "build", + "presentation": { + "clear": true, + "showReuseMessage": false + } + }, + {%- endif %} + { + "label": "{{ cookiecutter.first_module_name }}: Run hello", + "type": "process", + "command": "pipenv", + "args": [ + "run", + "{{ cookiecutter.first_module_name }}" + {%- if cookiecutter.use_fire == "y" %}, + "hello" + {%- endif %} + ], + "problemMatcher": [], + "group": { + "kind": "build", + "isDefault": true + }, + "presentation": { + "clear": true, + "showReuseMessage": false + } + }, + { + "label": "{{ cookiecutter.first_module_name }}: Run hello '{{ cookiecutter.author_full_name }}'", + "type": "process", + "command": "pipenv", + "args": [ + "run", + {%- if cookiecutter.use_fire == "y" %} + "{{ cookiecutter.first_module_name }}", + "hello", + "{{ cookiecutter.author_full_name }}" + {%- else %} + "python", + "-c", + "import {{ cookiecutter.first_module_name }}; print({{ cookiecutter.first_module_name }}.hello(\"{{ cookiecutter.author_full_name }}\"))" + {%- endif %} + ], + "problemMatcher": [], + "group": "build", + "presentation": { + "clear": true, + "showReuseMessage": false + } + } + ] +} diff --git a/{{ cookiecutter.project_slug }}/Pipfile b/{{ cookiecutter.project_slug }}/Pipfile index d4f83ae..10dc227 100644 --- a/{{ cookiecutter.project_slug }}/Pipfile +++ b/{{ cookiecutter.project_slug }}/Pipfile @@ -5,6 +5,10 @@ name = "pypi" [packages] {{ cookiecutter.project_slug }} = {editable = true, path = "./src"} +{%- if cookiecutter.use_fire == "y" %} +colorama = "*" +fire = "*" +{%- endif %} {%- if cookiecutter.use_pandas == "y" %} pandas = "*" {%- endif %} diff --git a/{{ cookiecutter.project_slug }}/src/fire_workarounds.py b/{{ cookiecutter.project_slug }}/src/fire_workarounds.py new file mode 100644 index 0000000..cddcc5f --- /dev/null +++ b/{{ cookiecutter.project_slug }}/src/fire_workarounds.py @@ -0,0 +1,27 @@ +"""Several workarounds for known issues in our dependencies""" + +import colorama +import fire + + +def __fire_suppress_pager(): + """Make Python Fire not use a pager when it prints a help text. + + See also: + https://github.com/google/python-fire/issues/188#issuecomment-631419585 + """ + fire.core.Display = lambda lines, out: print(*lines, file=out) + + +def __vscode_code_runner_fix_colors(): + """Work around an issue in the Code Runner extension for + Visual Studio Code, which claims to understand ANSI sequences + but doesn’t actually interpret them. + """ + colorama.init() + + +def apply(): + """Applies all known workarounds.""" + __fire_suppress_pager() + __vscode_code_runner_fix_colors() diff --git a/{{ cookiecutter.project_slug }}/src/{{ cookiecutter.first_module_name }}.py b/{{ cookiecutter.project_slug }}/src/{{ cookiecutter.first_module_name }}.py index 2c4d91f..be4fd5b 100644 --- a/{{ cookiecutter.project_slug }}/src/{{ cookiecutter.first_module_name }}.py +++ b/{{ cookiecutter.project_slug }}/src/{{ cookiecutter.first_module_name }}.py @@ -1,9 +1,22 @@ """This is the description of the {{ cookiecutter.first_module_name }} module.""" +{%- if cookiecutter.use_fire == "y" %} +import fire +import fire_workarounds +{%- endif %} -def hello(): - """Returns the string `Hello, world!` + +def hello(name='world'): + """Returns a greeting. """ - return 'Hello, world!' + return f'Hello, {name}!' + if __name__ == '__main__': +{%- if cookiecutter.use_fire == "y" %} + fire_workarounds.apply() + fire.Fire({ + "hello": hello + }) +{%- else %} print(hello()) +{%- endif %} diff --git a/{{ cookiecutter.project_slug }}/tests/test_{{ cookiecutter.first_module_name }}.py b/{{ cookiecutter.project_slug }}/tests/test_{{ cookiecutter.first_module_name }}.py index 706a50c..1b602e4 100644 --- a/{{ cookiecutter.project_slug }}/tests/test_{{ cookiecutter.first_module_name }}.py +++ b/{{ cookiecutter.project_slug }}/tests/test_{{ cookiecutter.first_module_name }}.py @@ -1,4 +1,13 @@ import {{ cookiecutter.first_module_name }} -def test_hello(): - assert {{ cookiecutter.first_module_name }}.hello() == 'Hello, world!' + +def test_hello_with_author_name(): + assert {{ cookiecutter.first_module_name }} \ + .hello('{{ cookiecutter.author_full_name }}') \ + == 'Hello, {{ cookiecutter.author_full_name }}!' + + +def test_hello_with_no_arguments(): + assert {{ cookiecutter.first_module_name }} \ + .hello() \ + == 'Hello, world!'