Generalized exception handling to handle strange errors like captchas.

This commit is contained in:
Michael Lazar
2015-12-03 18:15:53 -08:00
parent ea05235ddc
commit 9c6d3ab542
3 changed files with 29 additions and 39 deletions

View File

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

View File

@@ -12,10 +12,10 @@ import threading
from contextlib import contextmanager from contextlib import contextmanager
import six import six
import praw from praw.errors import PRAWException
import requests from requests import RequestException
from . import exceptions from .exceptions import RTVError
_logger = logging.getLogger(__name__) _logger = logging.getLogger(__name__)
@@ -111,25 +111,6 @@ class LoadScreen(object):
>>> assert isinstance(terminal.loader.exception, KeyboardInterrupt) >>> assert isinstance(terminal.loader.exception, KeyboardInterrupt)
""" """
HANDLED_EXCEPTIONS = [
(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): def __init__(self, terminal):
self.exception = None self.exception = None
@@ -186,19 +167,27 @@ class LoadScreen(object):
self._animator.join() self._animator.join()
self._terminal.stdscr.refresh() self._terminal.stdscr.refresh()
if self.catch_exception and e is not None: if e is None or not self.catch_exception:
# Log the exception and attach it so the caller can inspect it # Skip exception handling
self.exception = e return
_logger.info('Loader caught: {0} - {1}'.format(type(e).__name__, e))
# If an error occurred, display a notification on the screen self.exception = e
for base, message in self.HANDLED_EXCEPTIONS: exc_name = type(e).__name__
if isinstance(e, base): _logger.info('Loader caught: {0} - {1}'.format(exc_name, e))
if message:
self._terminal.show_notification(message) # Some exceptions we want to swallow and display a notification
break handled_exceptions = (RTVError, PRAWException, RequestException)
else: if isinstance(e, handled_exceptions):
return # Re-raise unhandled exceptions # Pass the message straight through to the user
return True # Otherwise swallow the exception and continue message = six.text_type(e).split('/n') if 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): def animate(self, delay, interval, message, trail):

View File

@@ -124,7 +124,8 @@ class SubredditPage(Page):
title, content = text.split('\n', 1) title, content = text.split('\n', 1)
with self.term.loader(message='Posting', delay=0): 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 # Give reddit time to process the submission
time.sleep(2.0) time.sleep(2.0)
if self.term.loader.exception: if self.term.loader.exception: