Skip to content

Commit

Permalink
Fix UnboundLocalError in `aiida.cmdline.utils.edit_multiline_templa…
Browse files Browse the repository at this point in the history
…te` (#4436)

If `click.edit` returns a falsy value, the following conditional would
be skipped and the `value` variable would be undefined causing an
`UnboundLocalError` to be raised. This bug was reported by @blokhin but
the exact conditions under which it occurred are not clear.

Cherry-pick: 861a39f
  • Loading branch information
sphuber committed Nov 6, 2020
1 parent 0a7039e commit 78cf6e1
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 6 deletions.
9 changes: 5 additions & 4 deletions aiida/cmdline/utils/multi_line_input.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,19 @@ def edit_multiline_template(template_name, comment_marker='#=', extension=None,
:param comment_marker: the set of symbols that mark a comment line that should be stripped from the final value
:param extension: the file extension to give to the rendered template file.
:param kwargs: keywords that will be passed to the template rendering engine.
:return: the final string value entered in the editor with all comment lines stripped.
:return: the final string value entered in the editor with all comment lines stripped or an empty string if the
``click.edit`` returned ``None``.
"""
from aiida.cmdline.utils.templates import env
template = env.get_template(template_name)
rendered = template.render(**kwargs)
content = click.edit(rendered, extension=extension)

if content:
if content is not None:
# Remove all comments, which are all lines that start with the comment marker
value = re.sub(r'(^' + re.escape(comment_marker) + '.*$\n)+', '', content, flags=re.M).strip()
return re.sub(r'(^' + re.escape(comment_marker) + '.*$\n)+', '', content, flags=re.M).strip()

return value
return ''


def edit_comment(old_cmt=''):
Expand Down
24 changes: 22 additions & 2 deletions tests/cmdline/utils/test_multiline.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,12 @@
# For further information on the license, see the LICENSE.txt file #
# For further information please visit http://www.aiida.net #
###########################################################################
# pylint: disable=unused-argument
# pylint: disable=unused-argument,invalid-name
"""Unit tests for editing pre and post bash scripts, comments, etc."""
import click
import pytest

from aiida.cmdline.utils.multi_line_input import edit_comment
from aiida.cmdline.utils.multi_line_input import edit_comment, edit_multiline_template

COMMAND = 'sleep 1 ; vim -c "g!/^#=/s/$/Test" -cwq' # Appends `Test` to every line NOT starting with `#=`

Expand All @@ -27,3 +28,22 @@ def test_edit_comment(non_interactive_editor):
old_comment = 'OldComment'
new_comment = edit_comment(old_cmt=old_comment)
assert new_comment == old_comment + 'Test'


@pytest.mark.parametrize('non_interactive_editor', (COMMAND,), indirect=True)
def test_edit_multiline_template_empty(non_interactive_editor, monkeypatch):
"""Test ``edit_multiline_template`` returns empty string when `click.edit` returns empty value e.g. ``None``."""

def edit(*args, **kwargs):
return None

monkeypatch.setattr(click, 'edit', edit)

assert edit_multiline_template(template_name='multiline.tpl') == ''


@pytest.mark.parametrize('non_interactive_editor', (COMMAND,), indirect=True)
def test_edit_multiline_template(non_interactive_editor):
"""Test ``edit_multiline_template`` returns empty string when `click.edit` returns empty value e.g. ``None``."""
# The template will contain two empty lines, and those will get `Test` appended to it
assert edit_multiline_template(template_name='multiline.tpl') == 'Test\nTest'

0 comments on commit 78cf6e1

Please sign in to comment.