Merge branch 'master' into browser_osx

Conflicts:
	rtv/objects.py
This commit is contained in:
Michael Lazar
2015-12-03 21:18:40 -08:00
6 changed files with 45 additions and 57 deletions

View File

@@ -65,10 +65,9 @@ def main():
with curses_session() as stdscr:
term = Terminal(stdscr, config['ascii'])
with term.loader(catch_exception=False):
reddit = praw.Reddit(
user_agent=user_agent,
decode_html_entities=False,
disable_update_check=True)
reddit = praw.Reddit(user_agent=user_agent,
decode_html_entities=False,
disable_update_check=True)
# Authorize on launch if the refresh token is present
oauth = OAuthHelper(reddit, term, config)
@@ -76,13 +75,18 @@ def main():
oauth.authorize()
with term.loader():
page = SubredditPage(
reddit, term, config, oauth,
name=config['subreddit'], url=config['link'])
page = SubredditPage(reddit, term, config, oauth,
config['subreddit'])
if term.loader.exception:
return
# Open the supplied submission link before opening the subreddit
if config['link']:
page.open_submission(url=config['link'])
# Launch the subreddit page
page.loop()
except Exception as e:
_logger.exception(e)
raise

View File

@@ -339,7 +339,7 @@ class SubredditContent(Content):
try:
self.get(0)
except IndexError:
raise exceptions.SubredditError('Unable to retrieve subreddit')
raise exceptions.SubredditError('No submissions')
@classmethod
def from_name(cls, reddit, name, loader, order=None, query=None):
@@ -361,7 +361,7 @@ class SubredditContent(Content):
if name == 'me':
if not reddit.is_oauth_session():
raise exceptions.AccountError('Could not access user account')
raise exceptions.AccountError('Not logged in')
elif order:
submissions = reddit.user.get_submitted(sort=order)
else:
@@ -443,7 +443,7 @@ class SubscriptionContent(Content):
try:
self.get(0)
except IndexError:
raise exceptions.SubscriptionError('Unable to load subscriptions')
raise exceptions.SubscriptionError('No subscriptions')
@classmethod
def from_user(cls, reddit, loader):

View File

@@ -12,10 +12,10 @@ import threading
from contextlib import contextmanager
import six
import praw
import requests
from praw.errors import PRAWException
from requests import RequestException
from . import exceptions
from .exceptions import RTVError
_logger = logging.getLogger(__name__)
@@ -111,26 +111,6 @@ class LoadScreen(object):
>>> assert isinstance(terminal.loader.exception, KeyboardInterrupt)
"""
HANDLED_EXCEPTIONS = [
(exceptions.BrowserError, 'Could not open browser'),
(exceptions.SubscriptionError, 'No Subscriptions'),
(exceptions.AccountError, 'Unable to Access Account'),
(exceptions.SubredditError, 'Invalid Subreddit'),
(praw.errors.InvalidSubreddit, 'Invalid Subreddit'),
(praw.errors.InvalidComment, 'Invalid Comment'),
(praw.errors.InvalidSubmission, 'Invalid Submission'),
(praw.errors.OAuthAppRequired, 'Invalid OAuth data'),
(praw.errors.OAuthException, 'Invalid OAuth data'),
(praw.errors.LoginOrScopeRequired, 'Not Logged In'),
(praw.errors.ClientException, 'Reddit Client Error'),
(praw.errors.NotFound, 'Not Found'),
(praw.errors.APIException, 'Reddit API Error'),
(praw.errors.HTTPException, 'Reddit HTTP Error'),
(requests.HTTPError, 'Unexpected HTTP Error'),
(requests.ConnectionError, 'Connection Error'),
(KeyboardInterrupt, None),
]
def __init__(self, terminal):
self.exception = None
@@ -187,19 +167,27 @@ class LoadScreen(object):
self._animator.join()
self._terminal.stdscr.refresh()
if self.catch_exception and e is not None:
# Log the exception and attach it so the caller can inspect it
self.exception = e
_logger.info('Loader caught: {0} - {1}'.format(type(e).__name__, e))
# If an error occurred, display a notification on the screen
for base, message in self.HANDLED_EXCEPTIONS:
if isinstance(e, base):
if message:
self._terminal.show_notification(message)
break
else:
return # Re-raise unhandled exceptions
return True # Otherwise swallow the exception and continue
if e is None or not self.catch_exception:
# Skip exception handling
return
self.exception = e
exc_name = type(e).__name__
_logger.info('Loader caught: {0} - {1}'.format(exc_name, e))
# Some exceptions we want to swallow and display a notification
handled_exceptions = (RTVError, PRAWException, RequestException)
if isinstance(e, handled_exceptions):
# Pass the message straight through to the user
message = six.text_type(e).split('/n') if str(e) else exc_name
self._terminal.show_notification(message)
return True
elif isinstance(e, KeyboardInterrupt):
# Don't need to print anything for this one
return True
else:
# Allow the exception to re-raise
return None
def animate(self, delay, interval, message, trail):

View File

@@ -19,7 +19,7 @@ class SubredditController(PageController):
class SubredditPage(Page):
def __init__(self, reddit, term, config, oauth, name, url=None):
def __init__(self, reddit, term, config, oauth, name):
"""
Params:
name (string): Name of subreddit to open
@@ -31,9 +31,6 @@ class SubredditPage(Page):
self.controller = SubredditController(self)
self.nav = Navigator(self.content.get)
if url:
self.open_submission(url=url)
@SubredditController.register(curses.KEY_F5, 'r')
def refresh_content(self, name=None, order=None):
"Re-download all submissions and reset the page index"
@@ -127,7 +124,8 @@ class SubredditPage(Page):
title, content = text.split('\n', 1)
with self.term.loader(message='Posting', delay=0):
submission = self.reddit.submit(name, title, text=content)
submission = self.reddit.submit(name, title, text=content,
raise_captcha_exception=True)
# Give reddit time to process the submission
time.sleep(2.0)
if self.term.loader.exception:

View File

@@ -77,8 +77,7 @@ def test_oauth_authorize_with_refresh_token(oauth, stdscr, refresh_token):
exception = OAuthException('', '')
oauth.reddit.refresh_access_information.side_effect = exception
oauth.authorize()
message = 'Invalid OAuth data'.encode('utf-8')
stdscr.derwin().addstr.assert_called_with(1, 1, message)
assert isinstance(oauth.term.loader.exception, OAuthException)
assert oauth.http_server is None
@@ -149,8 +148,7 @@ def test_oauth_authorize(oauth, reddit, stdscr, refresh_token):
exception = OAuthException('', '')
oauth.reddit.get_access_information.side_effect = exception
oauth.authorize()
message = 'Invalid OAuth data'.encode('utf-8')
stdscr.derwin().addstr.assert_called_with(1, 1, message)
assert isinstance(oauth.term.loader.exception, OAuthException)
assert not oauth.config.save_refresh_token.called

View File

@@ -53,7 +53,7 @@ def test_objects_load_screen_exception_handled(terminal, stdscr, ascii):
assert not terminal.loader._is_running
assert not terminal.loader._animator.is_alive()
assert isinstance(terminal.loader.exception, requests.ConnectionError)
error_message = 'Connection Error'.encode('ascii' if ascii else 'utf-8')
error_message = 'ConnectionError'.encode('ascii' if ascii else 'utf-8')
stdscr.subwin.addstr.assert_called_with(1, 1, error_message)
@@ -152,7 +152,7 @@ def test_objects_load_screen_nested_complex(terminal, stdscr, ascii):
assert terminal.loader.depth == 0
assert not terminal.loader._is_running
assert not terminal.loader._animator.is_alive()
error_message = 'Connection Error'.encode('ascii' if ascii else 'utf-8')
error_message = 'ConnectionError'.encode('ascii' if ascii else 'utf-8')
stdscr.subwin.addstr.assert_called_once_with(1, 1, error_message)