Error handling.

This commit is contained in:
Michael Lazar
2015-02-01 03:10:03 -08:00
parent 1449536504
commit 4ff4b98236
6 changed files with 116 additions and 29 deletions

View File

@@ -4,6 +4,8 @@ from contextlib import contextmanager
import praw
from errors import SubmissionURLError, SubredditNameError
def clean(unicode_string):
"""
Convert unicode string into ascii-safe characters.
@@ -159,8 +161,12 @@ class SubmissionContent(BaseContent):
indent_size=2,
max_indent_level=4):
with loader():
submission = reddit.get_submission(url)
try:
with loader():
submission = reddit.get_submission(url)
except praw.errors.APIException:
raise SubmissionURLError(url)
return cls(submission, loader, indent_size, max_indent_level)
@@ -273,9 +279,13 @@ class SubredditContent(BaseContent):
if name == 'all':
sub = reddit.get_subreddit(name)
else:
with loader():
sub = reddit.get_subreddit(name, fetch=True)
try:
with loader():
sub = reddit.get_subreddit(name, fetch=True)
except praw.errors.ClientException:
raise SubredditNameError(name)
return cls('/r/'+sub.display_name, sub.get_hot(limit=None), loader)

12
rtv/errors.py Normal file
View File

@@ -0,0 +1,12 @@
class EscapePressed(Exception):
pass
class SubmissionURLError(Exception):
def __init__(self, url):
self.url = url
class SubredditNameError(Exception):
def __init__(self, name):
self.name = name

View File

@@ -1,30 +1,58 @@
import argparse
import praw
from requests.exceptions import ConnectionError
from errors import SubmissionURLError, SubredditNameError
from utils import curses_session
from subreddit import SubredditPage
from submission import SubmissionPage
parser = argparse.ArgumentParser(description='Reddit Terminal Viewer')
parser.add_argument('-s', dest='subreddit', default='front', help='subreddit name')
parser.add_argument('-l', dest='link', help='full link to a specific submission')
parser.add_argument('-l', dest='link', help='full link to a submission')
group = parser.add_argument_group('authentication (optional)')
group.add_argument('-u', dest='username', help='reddit username')
group.add_argument('-p', dest='password', help='reddit password')
group.add_argument('--debug', action='store_true')
def main(args):
reddit = praw.Reddit(user_agent='reddit terminal viewer v0.0')
reddit.config.decode_html_entities = True
try:
reddit = praw.Reddit(user_agent='reddit terminal viewer v0.0')
reddit.config.decode_html_entities = True
if args.username and args.password:
reddit.login(args.username, args.password)
if args.username and args.password:
reddit.login(args.username, args.password)
with curses_session() as stdscr:
with curses_session() as stdscr:
page = SubredditPage(stdscr, reddit, args.subreddit)
page.loop()
if args.link:
# Go directly to submission
page = SubmissionPage(stdscr, reddit, url=args.link)
page.loop()
page = SubredditPage(stdscr, reddit, args.subreddit)
page.loop()
except KeyboardInterrupt:
return
except ConnectionError:
print 'Timeout: Could not connect to website'
except SubmissionURLError as e:
print 'Could not reach submission URL: {}'.format(e.url)
except SubredditNameError as e:
print 'Could not reach subreddit: {}'.format(e.name)
# except Exception:
# if not args.debug:
# print 'Unhandled exception'
# else:
# raise
if __name__ == '__main__':
args = parser.parse_args()
main(args)
main(args)

View File

@@ -75,6 +75,9 @@ class BasePage(object):
Base terminal viewer incorperates a cursor to navigate content
"""
MIN_HEIGHT = 10
MIN_WIDTH = 20
def __init__(self, stdscr, content, **kwargs):
self.stdscr = stdscr
@@ -107,21 +110,27 @@ class BasePage(object):
def draw(self):
n_rows, n_cols = self.stdscr.getmaxyx()
if n_rows < self.MIN_HEIGHT or n_cols < self.MIN_WIDTH:
return
self._header_window = self.stdscr.derwin(1, n_cols, 0, 0)
self._content_window = self.stdscr.derwin(1, 0)
self.draw_header()
self.draw_content()
self._draw_header()
self._draw_content()
self.add_cursor()
def draw_header(self):
def draw_item(self, window, data, inverted):
raise NotImplementedError
def _draw_header(self):
n_rows, n_cols = self._header_window.getmaxyx()
self._header_window.erase()
self._header_window.addnstr(0, 0, self.content.name, n_cols-1)
def draw_content(self):
def _draw_content(self):
"""
Loop through submissions and fill up the content page.
"""
@@ -153,9 +162,6 @@ class BasePage(object):
self._content_window.refresh()
def draw_item(self, window, data, inverted):
raise NotImplementedError
def _move_cursor(self, direction):
self.remove_cursor()
@@ -167,7 +173,7 @@ class BasePage(object):
# If we don't redraw, ACS_VLINE gets screwed up when changing the
# attr back to normal. There may be a way around this.
if True: #if redraw
self.draw_content()
self._draw_content()
self.add_cursor()

View File

@@ -1,10 +1,11 @@
import curses
import sys
from errors import SubredditNameError
from page import BasePage
from submission import SubmissionPage
from content import SubredditContent
from utils import LoadScreen, text_input
from utils import LoadScreen, text_input, display_message
class SubredditPage(BasePage):
@@ -56,11 +57,21 @@ class SubredditPage(BasePage):
def refresh_content(self, name=None):
self.nav.page_index, self.nav.cursor_index = 0, 0
self.nav.inverted = False
self.name = name if name else self.name
self.content = SubredditContent.from_name(self.reddit, self.name, self.loader)
self.stdscr.clear()
name = name or self.name
try:
self.content = SubredditContent.from_name(
self.reddit, name, self.loader)
except SubredditNameError:
display_message(self.stdscr, 'Invalid Subreddit')
else:
self.nav.page_index, self.nav.cursor_index = 0, 0
self.nav.inverted = False
self.name = name
#self.stdscr.clear()
self.draw()
def prompt_subreddit(self):

View File

@@ -5,8 +5,7 @@ import threading
from curses import textpad
from contextlib import contextmanager
class EscapePressed(Exception):
pass
from errors import EscapePressed
def text_input(window):
"""
@@ -40,6 +39,27 @@ def text_input(window):
return out
def display_message(stdscr, message):
"Display a message box at the center of the screen and wait for a keypress"
message_len = len(message)
n_rows, n_cols = stdscr.getmaxyx()
s_row = (n_rows - 2) / 2
s_col = (n_cols - message_len - 1) / 2
window = stdscr.derwin(3, message_len+2, s_row, s_col)
window.erase()
window.border()
window.addstr(1, 1, message)
window.refresh()
stdscr.getch()
window.clear()
window = None
stdscr.refresh()
class LoadScreen(object):
def __init__(self, stdscr):