Updated tests. Updated log format.

This commit is contained in:
Michael Lazar
2016-06-23 22:50:12 -07:00
parent 33257ac3d1
commit d81c981dbf
6 changed files with 82 additions and 20 deletions

View File

@@ -74,7 +74,10 @@ def main():
# if args[0] != "header:": # if args[0] != "header:":
# _http_logger.info(' '.join(args)) # _http_logger.info(' '.join(args))
# client.print = print_to_file # client.print = print_to_file
logging.basicConfig(level=logging.DEBUG, filename=config['log']) logging.basicConfig(
level=logging.DEBUG,
filename=config['log'],
format='%(asctime)s:%(levelname)s:%(filename)s:%(lineno)d:%(message)s')
else: else:
# Add an empty handler so the logger doesn't complain # Add an empty handler so the logger doesn't complain
logging.root.addHandler(logging.NullHandler()) logging.root.addHandler(logging.NullHandler())

View File

@@ -385,19 +385,26 @@ class Terminal(object):
@contextmanager @contextmanager
def open_editor(self, data=''): def open_editor(self, data=''):
""" """
Open a temporary file using the system's default editor. Open a file for editing using the system's default editor.
The data string will be written to the file before opening. This After the file has been altered, the text will be read back and lines
function will block until the editor has closed. At that point the file starting with '#' will be stripped. If an error occurs inside of the
will be read and and lines starting with '#' will be stripped. If no context manager, the file will be preserved. Otherwise, the file will
errors occur, the file will be deleted when the context manager closes. be deleted when the context manager closes.
Params:
data (str): If provided, text will be written to the file before
opening it with the editor.
Returns:
text (str): The text that the user entered into the editor.
""" """
filename = 'rtv_{:%Y%m%d_%H%M%S}.txt'.format(datetime.now()) filename = 'rtv_{:%Y%m%d_%H%M%S}.txt'.format(datetime.now())
filepath = os.path.join(tempfile.gettempdir(), filename) filepath = os.path.join(tempfile.gettempdir(), filename)
with codecs.open(filepath, 'w', 'utf-8') as fp: with codecs.open(filepath, 'w', 'utf-8') as fp:
fp.write(self.clean(data)) fp.write(data)
_logger.info('File created: {}'.format(filepath)) _logger.info('File created: {}'.format(filepath))
editor = os.getenv('RTV_EDITOR') or os.getenv('EDITOR') or 'nano' editor = os.getenv('RTV_EDITOR') or os.getenv('EDITOR') or 'nano'
@@ -426,8 +433,8 @@ class Terminal(object):
# If no errors occurred, try to remove the file # If no errors occurred, try to remove the file
try: try:
os.remove(filepath) os.remove(filepath)
except OSError as e: except OSError:
_logger.exception(e) _logger.warning('Could not delete: {}'.format(filepath))
else: else:
_logger.info('File deleted: {}'.format(filepath)) _logger.info('File deleted: {}'.format(filepath))

View File

@@ -27,7 +27,9 @@ except ImportError:
patch = partial(mock.patch, autospec=True) patch = partial(mock.patch, autospec=True)
# Turn on logging, but disable vcr from spamming # Turn on logging, but disable vcr from spamming
logging.basicConfig(level=logging.DEBUG) logging.basicConfig(
level=logging.DEBUG,
format='%(asctime)s:%(levelname)s:%(filename)s:%(lineno)d:%(message)s')
for name in ['vcr.matchers', 'vcr.stubs']: for name in ['vcr.matchers', 'vcr.stubs']:
logging.getLogger(name).disabled = True logging.getLogger(name).disabled = True

View File

@@ -178,7 +178,7 @@ def test_submission_comment(submission_page, terminal, refresh_token):
with mock.patch('praw.objects.Submission.add_comment') as add_comment, \ with mock.patch('praw.objects.Submission.add_comment') as add_comment, \
mock.patch.object(terminal, 'open_editor') as open_editor, \ mock.patch.object(terminal, 'open_editor') as open_editor, \
mock.patch('time.sleep'): mock.patch('time.sleep'):
open_editor.return_value = 'comment text' open_editor.return_value.__enter__.return_value = 'comment text'
submission_page.controller.trigger('c') submission_page.controller.trigger('c')
assert open_editor.called assert open_editor.called
@@ -233,7 +233,7 @@ def test_submission_edit(submission_page, terminal, refresh_token):
with mock.patch('praw.objects.Submission.edit') as edit, \ with mock.patch('praw.objects.Submission.edit') as edit, \
mock.patch.object(terminal, 'open_editor') as open_editor, \ mock.patch.object(terminal, 'open_editor') as open_editor, \
mock.patch('time.sleep'): mock.patch('time.sleep'):
open_editor.return_value = 'submission text' open_editor.return_value.__enter__.return_value = 'submission text'
submission_page.controller.trigger('e') submission_page.controller.trigger('e')
assert open_editor.called assert open_editor.called
@@ -249,7 +249,7 @@ def test_submission_edit(submission_page, terminal, refresh_token):
with mock.patch('praw.objects.Comment.edit') as edit, \ with mock.patch('praw.objects.Comment.edit') as edit, \
mock.patch.object(terminal, 'open_editor') as open_editor, \ mock.patch.object(terminal, 'open_editor') as open_editor, \
mock.patch('time.sleep'): mock.patch('time.sleep'):
open_editor.return_value = 'comment text' open_editor.return_value.__enter__.return_value = 'comment text'
submission_page.controller.trigger('e') submission_page.controller.trigger('e')
assert open_editor.called assert open_editor.called

View File

@@ -148,7 +148,7 @@ def test_subreddit_post(subreddit_page, terminal, reddit, refresh_token):
# Post a submission with a title but with no body # Post a submission with a title but with no body
subreddit_page.refresh_content(name='python') subreddit_page.refresh_content(name='python')
with mock.patch.object(terminal, 'open_editor'): with mock.patch.object(terminal, 'open_editor'):
terminal.open_editor.return_value = 'title' terminal.open_editor.return_value.__enter__.return_value = 'title'
subreddit_page.controller.trigger('c') subreddit_page.controller.trigger('c')
text = 'Canceled'.encode('utf-8') text = 'Canceled'.encode('utf-8')
terminal.stdscr.subwin.addstr.assert_called_with(1, 1, text) terminal.stdscr.subwin.addstr.assert_called_with(1, 1, text)
@@ -160,7 +160,7 @@ def test_subreddit_post(subreddit_page, terminal, reddit, refresh_token):
mock.patch.object(reddit, 'submit'), \ mock.patch.object(reddit, 'submit'), \
mock.patch('rtv.page.Page.loop') as loop, \ mock.patch('rtv.page.Page.loop') as loop, \
mock.patch('time.sleep'): mock.patch('time.sleep'):
terminal.open_editor.return_value = 'test\ncontent' terminal.open_editor.return_value.__enter__.return_value = 'test\ncont'
reddit.submit.return_value = submission reddit.submit.return_value = submission
subreddit_page.controller.trigger('c') subreddit_page.controller.trigger('c')
assert reddit.submit.called assert reddit.submit.called

View File

@@ -10,6 +10,7 @@ import pytest
from rtv.docs import HELP, COMMENT_EDIT_FILE from rtv.docs import HELP, COMMENT_EDIT_FILE
from rtv.objects import Color from rtv.objects import Color
from rtv.exceptions import TemporaryFileError
try: try:
from unittest import mock from unittest import mock
@@ -269,7 +270,10 @@ def test_prompt_y_or_n(terminal, stdscr):
assert curses.flash.called assert curses.flash.called
def test_open_editor(terminal): @pytest.mark.parametrize('ascii', [True, False])
def test_open_editor(terminal, ascii):
terminal.ascii = ascii
comment = COMMENT_EDIT_FILE.format(content='#| This is a comment! ❤') comment = COMMENT_EDIT_FILE.format(content='#| This is a comment! ❤')
data = {'filename': None} data = {'filename': None}
@@ -284,11 +288,57 @@ def test_open_editor(terminal):
with mock.patch('subprocess.Popen', autospec=True) as Popen: with mock.patch('subprocess.Popen', autospec=True) as Popen:
Popen.side_effect = side_effect Popen.side_effect = side_effect
reply_text = terminal.open_editor(comment) with terminal.open_editor(comment) as reply_text:
assert reply_text == 'This is an amended comment! ❤' assert reply_text == 'This is an amended comment! ❤'
assert os.path.isfile(data['filename'])
assert curses.endwin.called
assert curses.doupdate.called
assert not os.path.isfile(data['filename']) assert not os.path.isfile(data['filename'])
assert curses.endwin.called
assert curses.doupdate.called
def test_open_editor_error(terminal):
with mock.patch('subprocess.Popen', autospec=True) as Popen, \
mock.patch.object(terminal, 'show_notification'):
# Invalid editor
Popen.side_effect = OSError
with terminal.open_editor('hello') as text:
assert text == 'hello'
assert 'Could not open' in terminal.show_notification.call_args[0][0]
data = {'filename': None}
def side_effect(args):
data['filename'] = args[1]
return mock.Mock()
# Temporary File Errors don't delete the file
Popen.side_effect = side_effect
with terminal.open_editor('test'):
assert os.path.isfile(data['filename'])
raise TemporaryFileError()
assert os.path.isfile(data['filename'])
os.remove(data['filename'])
# Other Exceptions don't delete the file *and* are propagated
Popen.side_effect = side_effect
with pytest.raises(ValueError):
with terminal.open_editor('test'):
assert os.path.isfile(data['filename'])
raise ValueError()
assert os.path.isfile(data['filename'])
os.remove(data['filename'])
# Gracefully handle the case when we can't remove the file
with mock.patch.object(os, 'remove'):
os.remove.side_effect = OSError
with terminal.open_editor():
pass
assert os.remove.called
assert os.path.isfile(data['filename'])
os.remove(data['filename'])
def test_open_browser(terminal): def test_open_browser(terminal):