Error handling.
This commit is contained in:
@@ -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
12
rtv/errors.py
Normal 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
|
||||
46
rtv/main.py
46
rtv/main.py
@@ -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)
|
||||
|
||||
22
rtv/page.py
22
rtv/page.py
@@ -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()
|
||||
|
||||
|
||||
@@ -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):
|
||||
|
||||
24
rtv/utils.py
24
rtv/utils.py
@@ -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):
|
||||
|
||||
Reference in New Issue
Block a user