From 16ab77fc2cecca2cdeab9ffb53e64556dc1dcd71 Mon Sep 17 00:00:00 2001 From: Tobin Date: Tue, 31 Mar 2015 00:20:44 -0500 Subject: [PATCH] ran autopep8 --- rtv/__init__.py | 2 +- rtv/__main__.py | 17 ++++++++++------- rtv/config.py | 2 +- rtv/content.py | 43 +++++++++++++++++++++++++++++++------------ rtv/curses_helpers.py | 16 ++++++++++++---- rtv/docs.py | 2 +- rtv/exceptions.py | 12 +++++++++++- rtv/helpers.py | 9 ++++++++- rtv/page.py | 23 +++++++++++++++-------- rtv/submission.py | 33 ++++++++++++++++++--------------- rtv/subreddit.py | 28 +++++++++++++++++----------- 11 files changed, 125 insertions(+), 62 deletions(-) diff --git a/rtv/__init__.py b/rtv/__init__.py index 2004061..a85dee2 100644 --- a/rtv/__init__.py +++ b/rtv/__init__.py @@ -3,4 +3,4 @@ from .__version__ import __version__ __title__ = 'Reddit Terminal Viewer' __author__ = 'Michael Lazar' __license__ = 'The MIT License (MIT)' -__copyright__ = '(c) 2015 Michael Lazar' \ No newline at end of file +__copyright__ = '(c) 2015 Michael Lazar' diff --git a/rtv/__main__.py b/rtv/__main__.py index 5066d8c..bf8779c 100644 --- a/rtv/__main__.py +++ b/rtv/__main__.py @@ -18,6 +18,7 @@ from .docs import * __all__ = [] + def load_config(): """ Search for a configuration file at the location ~/.rtv and attempt to load @@ -34,11 +35,12 @@ def load_config(): return defaults + def command_line(): parser = argparse.ArgumentParser( prog='rtv', description=SUMMARY, - epilog=CONTROLS+HELP, + epilog=CONTROLS + HELP, formatter_class=argparse.RawDescriptionHelpFormatter) parser.add_argument('-s', dest='subreddit', help='subreddit name') @@ -56,15 +58,16 @@ def command_line(): return args + def main(): "Main entry point" - + # logging.basicConfig(level=logging.DEBUG, filename='rtv.log') locale.setlocale(locale.LC_ALL, '') args = command_line() local_config = load_config() - + # Fill in empty arguments with config file values. Paramaters explicitly # typed on the command line will take priority over config file params. for key, val in local_config.items(): @@ -84,11 +87,11 @@ def main(): # PRAW will prompt for password if it is None reddit.login(args.username, args.password) with curses_session() as stdscr: - if args.link: - page = SubmissionPage(stdscr, reddit, url=args.link) - page.loop() - page = SubredditPage(stdscr, reddit, args.subreddit) + if args.link: + page = SubmissionPage(stdscr, reddit, url=args.link) page.loop() + page = SubredditPage(stdscr, reddit, args.subreddit) + page.loop() except praw.errors.InvalidUserPass: print('Invalid password for username: {}'.format(args.username)) except requests.ConnectionError: diff --git a/rtv/config.py b/rtv/config.py index 20223d2..8bad1ff 100644 --- a/rtv/config.py +++ b/rtv/config.py @@ -2,4 +2,4 @@ Global configuration settings """ -unicode = False \ No newline at end of file +unicode = False diff --git a/rtv/content.py b/rtv/content.py index b9657f1..bdebb6d 100644 --- a/rtv/content.py +++ b/rtv/content.py @@ -8,6 +8,7 @@ from .helpers import humanize_timestamp, wrap_text, strip_subreddit_url __all__ = ['SubredditContent', 'SubmissionContent'] + class BaseContent(object): def get(self, index, n_cols): @@ -40,7 +41,8 @@ class BaseContent(object): retval = [] while stack: item = stack.pop(0) - if isinstance(item, praw.objects.MoreComments) and (item.count==0): + if isinstance(item, praw.objects.MoreComments) and ( + item.count == 0): continue nested = getattr(item, 'replies', None) if nested: @@ -70,9 +72,16 @@ class BaseContent(object): data['body'] = comment.body data['created'] = humanize_timestamp(comment.created_utc) data['score'] = '{} pts'.format(comment.score) - data['author'] = (comment.author.name if getattr(comment, 'author') else '[deleted]') - data['is_author'] = (data['author'] == getattr(comment.submission, 'author')) - data['flair'] = (comment.author_flair_text if comment.author_flair_text else '') + data['author'] = ( + comment.author.name if getattr( + comment, + 'author') else '[deleted]') + data['is_author'] = ( + data['author'] == getattr( + comment.submission, + 'author')) + data['flair'] = ( + comment.author_flair_text if comment.author_flair_text else '') data['likes'] = comment.likes return data @@ -94,7 +103,10 @@ class BaseContent(object): data['created'] = humanize_timestamp(sub.created_utc) data['comments'] = '{} comments'.format(sub.num_comments) data['score'] = '{} pts'.format(sub.score) - data['author'] = (sub.author.name if getattr(sub, 'author') else '[deleted]') + data['author'] = ( + sub.author.name if getattr( + sub, + 'author') else '[deleted]') data['permalink'] = sub.permalink data['subreddit'] = strip_subreddit_url(sub.permalink) data['flair'] = (sub.link_flair_text if sub.link_flair_text else '') @@ -104,7 +116,9 @@ class BaseContent(object): return data + class SubmissionContent(BaseContent): + """ Grab a submission from PRAW and lazily store comments to an internal list for repeat access. @@ -155,9 +169,13 @@ class SubmissionContent(BaseContent): elif index == -1: data = self._submission_data - data['split_title'] = textwrap.wrap(data['title'], width=n_cols-2) - data['split_text'] = wrap_text(data['text'], width=n_cols-2) - data['n_rows'] = len(data['split_title'])+len(data['split_text'])+5 + data['split_title'] = textwrap.wrap( + data['title'], + width=n_cols - + 2) + data['split_text'] = wrap_text(data['text'], width=n_cols - 2) + data['n_rows'] = len( + data['split_title']) + len(data['split_text']) + 5 data['offset'] = 0 else: @@ -191,7 +209,7 @@ class SubmissionContent(BaseContent): elif data['type'] == 'Comment': cache = [data] count = 1 - for d in self.iterate(index+1, 1, n_cols): + for d in self.iterate(index + 1, 1, n_cols): if d['level'] <= data['level']: break @@ -204,10 +222,10 @@ class SubmissionContent(BaseContent): comment['count'] = count comment['level'] = data['level'] comment['body'] = 'Hidden'.format(count) - self._comment_data[index:index+len(cache)] = [comment] + self._comment_data[index:index + len(cache)] = [comment] elif data['type'] == 'HiddenComment': - self._comment_data[index:index+1] = data['cache'] + self._comment_data[index:index + 1] = data['cache'] elif data['type'] == 'MoreComments': with self._loader(): @@ -215,13 +233,14 @@ class SubmissionContent(BaseContent): comments = self.flatten_comments(comments, root_level=data['level']) comment_data = [self.strip_praw_comment(c) for c in comments] - self._comment_data[index:index+1] = comment_data + self._comment_data[index:index + 1] = comment_data else: raise ValueError('% type not recognized' % data['type']) class SubredditContent(BaseContent): + """ Grabs a subreddit from PRAW and lazily stores submissions to an internal list for repeat access. diff --git a/rtv/curses_helpers.py b/rtv/curses_helpers.py index 9e5d811..f9a2085 100644 --- a/rtv/curses_helpers.py +++ b/rtv/curses_helpers.py @@ -23,6 +23,7 @@ UARROW = u'\u25b2'.encode('utf-8') DARROW = u'\u25bc'.encode('utf-8') BULLET = u'\u2022'.encode('utf-8') + def show_notification(stdscr, message): """ Overlay a message box on the center of the screen and wait for user input. @@ -57,13 +58,16 @@ def show_notification(stdscr, message): window = None stdscr.refresh() + def show_help(stdscr): """ Overlay a message box with the help screen. """ show_notification(stdscr, HELP.split("\n")) + class LoadScreen(object): + """ Display a loading dialog while waiting for a blocking action to complete. @@ -128,10 +132,10 @@ class LoadScreen(object): n_rows, n_cols = self._stdscr.getmaxyx() s_row = (n_rows - 3) // 2 s_col = (n_cols - message_len - 1) // 2 - window = self._stdscr.derwin(3, message_len+2, s_row, s_col) + window = self._stdscr.derwin(3, message_len + 2, s_row, s_col) while True: - for i in range(len(trail)+1): + for i in range(len(trail) + 1): if not self._is_running: window.clear() @@ -145,7 +149,9 @@ class LoadScreen(object): window.refresh() time.sleep(interval) + class Color(object): + """ Color attributes for curses. """ @@ -158,7 +164,7 @@ class Color(object): 'MAGENTA': (curses.COLOR_MAGENTA, -1), 'CYAN': (curses.COLOR_CYAN, -1), 'WHITE': (curses.COLOR_WHITE, -1), - } + } @classmethod def init(cls): @@ -182,6 +188,7 @@ class Color(object): levels = [cls.MAGENTA, cls.CYAN, cls.GREEN, cls.YELLOW] return levels[level % len(levels)] + def text_input(window, allow_resize=True): """ Transform a window into a text box that will accept user input and loop @@ -192,7 +199,7 @@ def text_input(window, allow_resize=True): """ window.clear() - + # Set cursor mode to 1 because 2 doesn't display on some terminals curses.curs_set(1) @@ -223,6 +230,7 @@ def text_input(window, allow_resize=True): curses.curs_set(0) return strip_textpad(out) + @contextmanager def curses_session(): """ diff --git a/rtv/docs.py b/rtv/docs.py index 4089ee7..b47a31b 100644 --- a/rtv/docs.py +++ b/rtv/docs.py @@ -42,7 +42,7 @@ Subreddit Mode Submission Mode `LEFT` or `h` : Return to subreddit mode `RIGHT` or `l` : Fold the selected comment, or load additional comments - `c` : Comment/reply on the selected item + `c` : Comment/reply on the selected item """ COMMENT_FILE = """ diff --git a/rtv/exceptions.py b/rtv/exceptions.py index c8b980a..d502975 100644 --- a/rtv/exceptions.py +++ b/rtv/exceptions.py @@ -1,17 +1,27 @@ class SubmissionError(Exception): + "Submission could not be loaded" + def __init__(self, url): self.url = url + class SubredditError(Exception): + "Subreddit could not be reached" + def __init__(self, name): self.name = name + class ProgramError(Exception): + "Problem executing an external program" + def __init__(self, name): self.name = name + class EscapeInterrupt(Exception): - "Signal that the ESC key has been pressed" \ No newline at end of file + + "Signal that the ESC key has been pressed" diff --git a/rtv/helpers.py b/rtv/helpers.py index 5f54068..582901a 100644 --- a/rtv/helpers.py +++ b/rtv/helpers.py @@ -11,6 +11,7 @@ from .exceptions import ProgramError __all__ = ['open_browser', 'clean', 'wrap_text', 'strip_textpad', 'strip_subreddit_url', 'humanize_timestamp', 'open_editor'] + def open_editor(data=''): """ Open a temporary file using the system's default editor. @@ -39,6 +40,7 @@ def open_editor(data=''): return text + def open_browser(url): """ Call webbrowser.open_new_tab(url) and redirect stdout/stderr to devnull. @@ -52,6 +54,7 @@ def open_browser(url): with open(os.devnull, 'ab+', 0) as null: subprocess.check_call(args, stdout=null, stderr=null) + def clean(string): """ Required reading! @@ -75,6 +78,7 @@ def clean(string): string = string.encode(encoding, 'replace') return string + def wrap_text(text, width): """ Wrap text paragraphs to the given character width while preserving newlines. @@ -87,6 +91,7 @@ def wrap_text(text, width): out.extend(lines) return out + def strip_textpad(text): """ Attempt to intelligently strip excess whitespace from the output of a @@ -121,6 +126,7 @@ def strip_textpad(text): out = '\n'.join(stack) return out + def strip_subreddit_url(permalink): """ Strip a subreddit name from the subreddit's permalink. @@ -131,6 +137,7 @@ def strip_subreddit_url(permalink): subreddit = permalink.split('/')[4] return '/r/{}'.format(subreddit) + def humanize_timestamp(utc_timestamp, verbose=False): """ Convert a utc timestamp into a human readable relative-time. @@ -154,4 +161,4 @@ def humanize_timestamp(utc_timestamp, verbose=False): if months < 12: return ('%d months ago' % months) if verbose else ('%dmonth' % months) years = months // 12 - return ('%d years ago' % years) if verbose else ('%dyr' % years) \ No newline at end of file + return ('%d years ago' % years) if verbose else ('%dyr' % years) diff --git a/rtv/page.py b/rtv/page.py index d1f31eb..be55910 100644 --- a/rtv/page.py +++ b/rtv/page.py @@ -9,7 +9,9 @@ from .curses_helpers import Color, show_notification, show_help __all__ = ['Navigator'] + class Navigator(object): + """ Handles math behind cursor movement and screen paging. """ @@ -45,7 +47,7 @@ class Navigator(object): valid, redraw = True, False - forward = ((direction*self.step) > 0) + forward = ((direction * self.step) > 0) if forward: if self.page_index < 0: @@ -73,11 +75,12 @@ class Navigator(object): else: self.page_index -= self.step if self._is_valid(self.absolute_index): - # We have reached the beginning of the page - move the index + # We have reached the beginning of the page - move the + # index redraw = True else: self.page_index += self.step - valid = False # Revert + valid = False # Revert return valid, redraw @@ -99,6 +102,7 @@ class Navigator(object): class BaseController(object): + """ Event handler for triggering functions with curses keypresses. @@ -148,6 +152,7 @@ class BaseController(object): class BasePage(object): + """ Base terminal viewer incorperates a cursor to navigate content """ @@ -229,7 +234,7 @@ class BasePage(object): # Note: 2 argument form of derwin breaks PDcurses on Windows 7! self._header_window = self.stdscr.derwin(1, n_cols, 0, 0) - self._content_window = self.stdscr.derwin(n_rows-1, n_cols, 1, 0) + self._content_window = self.stdscr.derwin(n_rows - 1, n_cols, 1, 0) self.stdscr.erase() self._draw_header() @@ -249,12 +254,13 @@ class BasePage(object): self._header_window.bkgd(' ', attr) sub_name = self.content.name.replace('/r/front', 'Front Page ') - self._header_window.addnstr(0, 0, clean(sub_name), n_cols-1) + self._header_window.addnstr(0, 0, clean(sub_name), n_cols - 1) if self.reddit.user is not None: username = self.reddit.user.name s_col = (n_cols - len(username) - 1) - # Only print the username if it fits in the empty space on the right + # Only print the username if it fits in the empty space on the + # right if (s_col - 1) >= len(sub_name): n = (n_cols - s_col - 1) self._header_window.addnstr(0, s_col, clean(username), n) @@ -278,7 +284,7 @@ class BasePage(object): # and draw upwards. current_row = (n_rows - 1) if inverted else 0 available_rows = (n_rows - 1) if inverted else n_rows - for data in self.content.iterate(page_index, step, n_cols-2): + for data in self.content.iterate(page_index, step, n_cols - 2): window_rows = min(available_rows, data['n_rows']) window_cols = n_cols - data['offset'] start = current_row - window_rows if inverted else current_row @@ -313,7 +319,8 @@ class BasePage(object): self._remove_cursor() valid, redraw = self.nav.move(direction, len(self._subwindows)) - if not valid: curses.flash() + if not valid: + curses.flash() # Note: ACS_VLINE doesn't like changing the attribute, so always redraw. # if redraw: self._draw_content() diff --git a/rtv/submission.py b/rtv/submission.py index a854ddd..43899d6 100644 --- a/rtv/submission.py +++ b/rtv/submission.py @@ -58,7 +58,10 @@ class SubmissionPage(BasePage): @SubmissionController.register(curses.KEY_F5, 'r') def refresh_content(self): url = self.content.name - self.content = SubmissionContent.from_url(self.reddit, url, self.loader) + self.content = SubmissionContent.from_url( + self.reddit, + url, + self.loader) self.nav = Navigator(self.content.get, page_index=-1) @SubmissionController.register(curses.KEY_ENTER, 10, 'o') @@ -139,12 +142,12 @@ class SubmissionPage(BasePage): text = clean('{author} '.format(**data)) attr = curses.A_BOLD attr |= (Color.BLUE if not data['is_author'] else Color.GREEN) - win.addnstr(row, 1, text, n_cols-1, attr) + win.addnstr(row, 1, text, n_cols - 1, attr) if data['flair']: text = clean('{flair} '.format(**data)) attr = curses.A_BOLD | Color.YELLOW - win.addnstr(text, n_cols-win.getyx()[1], attr) + win.addnstr(text, n_cols - win.getyx()[1], attr) if data['likes'] is None: text, attr = BULLET, curses.A_BOLD @@ -152,16 +155,16 @@ class SubmissionPage(BasePage): text, attr = UARROW, (curses.A_BOLD | Color.GREEN) else: text, attr = DARROW, (curses.A_BOLD | Color.RED) - win.addnstr(text, n_cols-win.getyx()[1], attr) + win.addnstr(text, n_cols - win.getyx()[1], attr) text = clean(' {score} {created}'.format(**data)) - win.addnstr(text, n_cols-win.getyx()[1]) + win.addnstr(text, n_cols - win.getyx()[1]) n_body = len(data['split_body']) - for row, text in enumerate(data['split_body'], start=offset+1): + for row, text in enumerate(data['split_body'], start=offset + 1): if row in valid_rows: text = clean(text) - win.addnstr(row, 1, text, n_cols-1) + win.addnstr(row, 1, text, n_cols - 1) # Unfortunately vline() doesn't support custom color so we have to # build it one segment at a time. @@ -170,8 +173,8 @@ class SubmissionPage(BasePage): x = 0 # http://bugs.python.org/issue21088 if (sys.version_info.major, - sys.version_info.minor, - sys.version_info.micro) == (3, 4, 0): + sys.version_info.minor, + sys.version_info.micro) == (3, 4, 0): x, y = y, x win.addch(y, x, curses.ACS_VLINE, attr) @@ -185,9 +188,9 @@ class SubmissionPage(BasePage): n_cols -= 1 text = clean('{body}'.format(**data)) - win.addnstr(0, 1, text, n_cols-1) + win.addnstr(0, 1, text, n_cols - 1) text = clean(' [{count}]'.format(**data)) - win.addnstr(text, n_cols-win.getyx()[1], curses.A_BOLD) + win.addnstr(text, n_cols - win.getyx()[1], curses.A_BOLD) # Unfortunately vline() doesn't support custom color so we have to # build it one segment at a time. @@ -200,7 +203,7 @@ class SubmissionPage(BasePage): def draw_submission(win, data): n_rows, n_cols = win.getmaxyx() - n_cols -= 3 # one for each side of the border + one for offset + n_cols -= 3 # one for each side of the border + one for offset # Don't print at all if there is not enough room to fit the whole sub if data['n_rows'] > n_rows: @@ -217,9 +220,9 @@ class SubmissionPage(BasePage): win.addnstr(row, 1, text, n_cols, attr) attr = curses.A_BOLD | Color.YELLOW text = clean(' {flair}'.format(**data)) - win.addnstr(text, n_cols-win.getyx()[1], attr) + win.addnstr(text, n_cols - win.getyx()[1], attr) text = clean(' {created} {subreddit}'.format(**data)) - win.addnstr(text, n_cols-win.getyx()[1]) + win.addnstr(text, n_cols - win.getyx()[1]) row = len(data['split_title']) + 2 attr = curses.A_UNDERLINE | Color.BLUE @@ -235,4 +238,4 @@ class SubmissionPage(BasePage): text = clean('{score} {comments}'.format(**data)) win.addnstr(row, 1, text, n_cols, curses.A_BOLD) - win.border() \ No newline at end of file + win.border() diff --git a/rtv/subreddit.py b/rtv/subreddit.py index b811a07..5587bca 100644 --- a/rtv/subreddit.py +++ b/rtv/subreddit.py @@ -7,7 +7,7 @@ from .page import BasePage, Navigator, BaseController from .submission import SubmissionPage from .content import SubredditContent from .helpers import clean, open_browser -from .curses_helpers import (BULLET, UARROW, DARROW, Color, LoadScreen, +from .curses_helpers import (BULLET, UARROW, DARROW, Color, LoadScreen, text_input, show_notification) __all__ = ['opened_links', 'SubredditController', 'SubredditPage'] @@ -57,9 +57,15 @@ class SubredditPage(BasePage): attr = curses.A_BOLD | Color.CYAN prompt = 'Enter Subreddit: /r/' n_rows, n_cols = self.stdscr.getmaxyx() - self.stdscr.addstr(n_rows-1, 0, prompt, attr) + self.stdscr.addstr(n_rows - 1, 0, prompt, attr) self.stdscr.refresh() - window = self.stdscr.derwin(1, n_cols-len(prompt),n_rows-1, len(prompt)) + window = self.stdscr.derwin( + 1, + n_cols - + len(prompt), + n_rows - + 1, + len(prompt)) window.attrset(attr) out = text_input(window) @@ -102,7 +108,7 @@ class SubredditPage(BasePage): for row, text in enumerate(data['split_title'], start=offset): if row in valid_rows: text = clean(text) - win.addnstr(row, 1, text, n_cols-1, curses.A_BOLD) + win.addnstr(row, 1, text, n_cols - 1, curses.A_BOLD) row = n_title + offset if row in valid_rows: @@ -110,12 +116,12 @@ class SubredditPage(BasePage): link_color = Color.MAGENTA if seen else Color.BLUE attr = curses.A_UNDERLINE | link_color text = clean('{url}'.format(**data)) - win.addnstr(row, 1, text, n_cols-1, attr) + win.addnstr(row, 1, text, n_cols - 1, attr) row = n_title + offset + 1 if row in valid_rows: text = clean('{score} '.format(**data)) - win.addnstr(row, 1, text, n_cols-1) + win.addnstr(row, 1, text, n_cols - 1) if data['likes'] is None: text, attr = BULLET, curses.A_BOLD @@ -123,16 +129,16 @@ class SubredditPage(BasePage): text, attr = UARROW, curses.A_BOLD | Color.GREEN else: text, attr = DARROW, curses.A_BOLD | Color.RED - win.addnstr(text, n_cols-win.getyx()[1], attr) + win.addnstr(text, n_cols - win.getyx()[1], attr) text = clean(' {created} {comments}'.format(**data)) - win.addnstr(text, n_cols-win.getyx()[1]) + win.addnstr(text, n_cols - win.getyx()[1]) row = n_title + offset + 2 if row in valid_rows: text = clean('{author}'.format(**data)) - win.addnstr(row, 1, text, n_cols-1, curses.A_BOLD) + win.addnstr(row, 1, text, n_cols - 1, curses.A_BOLD) text = clean(' {subreddit}'.format(**data)) - win.addnstr(text, n_cols-win.getyx()[1], Color.YELLOW) + win.addnstr(text, n_cols - win.getyx()[1], Color.YELLOW) text = clean(' {flair}'.format(**data)) - win.addnstr(text, n_cols-win.getyx()[1], Color.RED) + win.addnstr(text, n_cols - win.getyx()[1], Color.RED)