From b8794e35994810835a489747d69c2415ee557e16 Mon Sep 17 00:00:00 2001 From: Michael Lazar Date: Sun, 1 Feb 2015 02:02:22 -0800 Subject: [PATCH] Refactored page initialization, content initialization, and loading. --- rtv/content.py | 38 ++++++++++++++++++++++++-------------- rtv/main.py | 14 ++++++-------- rtv/page.py | 18 +++++++++++++----- rtv/submission.py | 29 +++++++++++++---------------- rtv/subreddit.py | 35 ++++++++++++++++------------------- rtv/utils.py | 37 +++++++++++++++++++------------------ 6 files changed, 91 insertions(+), 80 deletions(-) diff --git a/rtv/content.py b/rtv/content.py index c704c6c..6321564 100644 --- a/rtv/content.py +++ b/rtv/content.py @@ -135,7 +135,7 @@ class SubmissionContent(BaseContent): def __init__( self, submission, - loader=default_loader(), + loader=default_loader, indent_size=2, max_indent_level=4): @@ -143,26 +143,35 @@ class SubmissionContent(BaseContent): self.max_indent_level = max_indent_level self._loader = loader + self._submissin = submission self._submission_data = self.strip_praw_submission(submission) self.name = self._submission_data['permalink'] - with loader: + with self._loader(): comments = self.flatten_comments(submission.comments) self._comment_data = [self.strip_praw_comment(c) for c in comments] @classmethod def from_url( cls, - r, + reddit, url, - loader=default_loader(), + loader=default_loader, indent_size=2, max_indent_level=4): - with loader: - submission = r.get_submission(url) + with loader(): + submission = reddit.get_submission(url) return cls(submission, loader, indent_size, max_indent_level) + def reset(self): + + self._submissin.refresh() + self._submission_data = self.strip_praw_submission(submission) + self.name = self._submission_data['permalink'] + comments = self.flatten_comments(submission.comments) + self._comment_data = [self.strip_praw_comment(c) for c in comments] + def get(self, index, n_cols=70): """ Grab the `i`th submission, with the title field formatted to fit inside @@ -227,7 +236,7 @@ class SubmissionContent(BaseContent): elif data['type'] == 'MoreComments': - with self._loader: + with self._loader(): comments = data['object'].comments() comments = self.flatten_comments(comments, root_level=data['level']) comment_data = [self.strip_praw_comment(c) for c in comments] @@ -249,23 +258,24 @@ class SubredditContent(BaseContent): list for repeat access. """ - def __init__(self, name, submission_generator, loader=default_loader()): + def __init__(self, name, submissions, loader=default_loader): self.name = name self._loader = loader - self._submissions = submission_generator + self._submissions = submissions self._submission_data = [] @classmethod - def from_name(cls, r, name, loader=default_loader()): + def from_name(cls, reddit, name, loader=default_loader): if name == 'front': - return cls('Front Page', r.get_front_page(limit=None), loader) + return cls('Front Page', reddit.get_front_page(limit=None), loader) if name == 'all': - sub = r.get_subreddit(name) + sub = reddit.get_subreddit(name) else: - sub = r.get_subreddit(name, fetch=True) + with loader(): + sub = reddit.get_subreddit(name, fetch=True) return cls('/r/'+sub.display_name, sub.get_hot(limit=None), loader) @@ -281,7 +291,7 @@ class SubredditContent(BaseContent): while index >= len(self._submission_data): try: - with self._loader: + with self._loader(): submission = self._submissions.next() except StopIteration: raise IndexError diff --git a/rtv/main.py b/rtv/main.py index ac26b97..cdcc835 100644 --- a/rtv/main.py +++ b/rtv/main.py @@ -1,7 +1,7 @@ import argparse import praw -from utils import curses_session, LoadScreen -from content import SubredditContent + +from utils import curses_session from subreddit import SubredditPage parser = argparse.ArgumentParser(description='Reddit Terminal Viewer') @@ -13,17 +13,15 @@ group.add_argument('-p', dest='password', help='reddit password') def main(args): - r = praw.Reddit(user_agent='reddit terminal viewer v0.0') - r.config.decode_html_entities = True + reddit = praw.Reddit(user_agent='reddit terminal viewer v0.0') + reddit.config.decode_html_entities = True if args.username and args.password: - r.login(args.username, args.password) + reddit.login(args.username, args.password) with curses_session() as stdscr: - loader = LoadScreen(stdscr) - content = SubredditContent(r, subreddit=args.subreddit, loader=loader) - page = SubredditPage(stdscr, content) + page = SubredditPage(stdscr, reddit, args.subreddit) page.loop() if __name__ == '__main__': diff --git a/rtv/page.py b/rtv/page.py index 47d7db0..ffb2df8 100644 --- a/rtv/page.py +++ b/rtv/page.py @@ -79,14 +79,12 @@ class BasePage(object): self.stdscr = stdscr self.content = content - self.nav = Navigator(self.content.get, **kwargs) + self._header_window = None + self._content_window = None self._subwindows = None - def draw(self): - raise NotImplementedError - def move_cursor_up(self): self._move_cursor(-1) @@ -106,12 +104,22 @@ class BasePage(object): continue self.stdscr.nodelay(0) + def draw(self): + + n_rows, n_cols = self.stdscr.getmaxyx() + 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.add_cursor() + def draw_header(self): n_rows, n_cols = self._header_window.getmaxyx() self._header_window.erase() - self._header_window.addnstr(0, 0, self.content.display_name, n_cols-1) + self._header_window.addnstr(0, 0, self.content.name, n_cols-1) def draw_content(self): """ diff --git a/rtv/submission.py b/rtv/submission.py index 4864956..6a3ac7e 100644 --- a/rtv/submission.py +++ b/rtv/submission.py @@ -1,18 +1,25 @@ -import praw import curses import sys +from content import SubmissionContent from page import BasePage -from utils import curses_session +from utils import LoadScreen class SubmissionPage(BasePage): - def __init__(self, stdscr, content): + def __init__(self, stdscr, reddit, url=None, submission=None): + + self.loader = LoadScreen(stdscr) + + if url is not None: + content = SubmissionContent.from_url(reddit, url, self.loader) + elif submission is not None: + content = SubmissionContent(submission, self.loader) + else: + raise ValueError('Must specify url or submission') - page_index, cursor_index = -1, 1 super(SubmissionPage, self).__init__( - stdscr, content, - page_index=page_index, cursor_index=cursor_index) + stdscr, content, page_index=-1, cursor_index=1) def loop(self): @@ -61,16 +68,6 @@ class SubmissionPage(BasePage): self.stdscr.clear() self.draw() - def draw(self): - - n_rows, n_cols = self.stdscr.getmaxyx() - 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.add_cursor() - def draw_item(self, win, data, inverted=False): if data['type'] == 'MoreComments': diff --git a/rtv/subreddit.py b/rtv/subreddit.py index e5ea044..631501e 100644 --- a/rtv/subreddit.py +++ b/rtv/subreddit.py @@ -1,15 +1,22 @@ -import praw -import textwrap import curses import sys from page import BasePage from submission import SubmissionPage -from content import SubmissionContent -from utils import curses_session, text_input +from content import SubredditContent +from utils import LoadScreen, text_input class SubredditPage(BasePage): + def __init__(self, stdscr, reddit, name): + + self.reddit = reddit + self.name = name + self.loader = LoadScreen(stdscr) + + content = SubredditContent.from_name(reddit, name, self.loader) + super(SubredditPage, self).__init__(stdscr, content) + def loop(self): self.draw() @@ -47,11 +54,12 @@ class SubredditPage(BasePage): else: curses.beep() - def refresh_content(self, subreddit=None): + def refresh_content(self, name=None): self.nav.page_index, self.nav.cursor_index = 0, 0 self.nav.inverted = False - self.content.reset(subreddit=subreddit) + self.name = name if name else self.name + self.content = SubredditContent.from_name(self.reddit, self.name, self.loader) self.stdscr.clear() self.draw() @@ -67,26 +75,15 @@ class SubredditPage(BasePage): if out is None: self.draw() else: - self.refresh_content(subreddit=out) + self.refresh_content(name=out) def open_submission(self): "Select the current submission to view posts" submission = self.content.get(self.nav.absolute_index)['object'] - content = SubmissionContent(submission, loader=self.content.loader) - page = SubmissionPage(self.stdscr, content) + page = SubmissionPage(self.stdscr, self.reddit, submission=submission) page.loop() - def draw(self): - - n_rows, n_cols = self.stdscr.getmaxyx() - 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.add_cursor() - @staticmethod def draw_item(win, data, inverted=False): diff --git a/rtv/utils.py b/rtv/utils.py index 86d2cfe..a6ccb35 100644 --- a/rtv/utils.py +++ b/rtv/utils.py @@ -42,26 +42,27 @@ def text_input(window): class LoadScreen(object): - def __init__( - self, - stdscr, - message='Downloading', - trail='...', - delay=0.5, - interval=0.4): + def __init__(self, stdscr): self._stdscr = stdscr - self.message = message - self.delay = delay - self.interval=interval - self.trail = trail + self._args = None self._animator = None self._is_running = None + def __call__( + self, + delay=0.5, + interval=0.4, + message='Downloading', + trail='...'): + + self._args = (delay, interval, message, trail) + return self + def __enter__(self): - self._animator = threading.Thread(target=self.animate) + self._animator = threading.Thread(target=self.animate, args=self._args) self._animator.daemon = True self._is_running = True @@ -72,23 +73,23 @@ class LoadScreen(object): self._is_running = False self._animator.join() - def animate(self): + def animate(self, delay, interval, message, trail): # Delay before starting animation to avoid wasting resources if the # wait time is very short start = time.time() - while (time.time() - start) < self.delay: + while (time.time() - start) < delay: if not self._is_running: return - message_len = len(self.message) + len(self.trail) + message_len = len(message) + len(trail) n_rows, n_cols = self._stdscr.getmaxyx() s_row = (n_rows - 2) / 2 s_col = (n_cols - message_len - 1) / 2 window = self._stdscr.derwin(3, message_len+2, s_row, s_col) while True: - for i in xrange(len(self.trail)+1): + for i in xrange(len(trail)+1): if not self._is_running: # TODO: figure out why this isn't removing the screen @@ -98,9 +99,9 @@ class LoadScreen(object): window.erase() window.border() - window.addstr(1, 1, self.message + self.trail[:i]) + window.addstr(1, 1, message + trail[:i]) window.refresh() - time.sleep(self.interval) + time.sleep(interval) @contextmanager