<s> from __future__ import unicode_literals <EOL> import re <EOL> import os <EOL> import time <EOL> import signal <EOL> import inspect <EOL> import weakref <EOL> import logging <EOL> import threading <EOL> import curses <EOL> import curses . ascii <EOL> from contextlib import contextmanager <EOL> import six <EOL> import praw <EOL> import requests <EOL> from . import exceptions <EOL> _logger = logging . getLogger ( __name__ ) <EOL> @ contextmanager <EOL> def curses_session ( ) : <EOL> """<STR_LIT>""" <EOL> try : <EOL> os . environ [ '<STR_LIT>' ] = '<STR_LIT>' <EOL> stdscr = curses . initscr ( ) <EOL> curses . noecho ( ) <EOL> curses . cbreak ( ) <EOL> stdscr . keypad ( <NUM_LIT:1> ) <EOL> try : <EOL> curses . start_color ( ) <EOL> except : <EOL> pass <EOL> curses . curs_set ( <NUM_LIT:0> ) <EOL> curses . use_default_colors ( ) <EOL> yield stdscr <EOL> finally : <EOL> if '<STR_LIT>' in locals ( ) : <EOL> stdscr . keypad ( <NUM_LIT:0> ) <EOL> curses . echo ( ) <EOL> curses . nocbreak ( ) <EOL> curses . endwin ( ) <EOL> class LoadScreen ( object ) : <EOL> """<STR_LIT>""" <EOL> EXCEPTION_MESSAGES = [ <EOL> ( exceptions . RTVError , '<STR_LIT>' ) , <EOL> ( praw . errors . OAuthException , '<STR_LIT>' ) , <EOL> ( praw . errors . OAuthScopeRequired , '<STR_LIT>' ) , <EOL> ( praw . errors . LoginRequired , '<STR_LIT>' ) , <EOL> ( praw . errors . InvalidCaptcha , '<STR_LIT>' ) , <EOL> ( praw . errors . PRAWException , '<STR_LIT>' ) , <EOL> ( requests . exceptions . RequestException , '<STR_LIT>' ) , <EOL> ] <EOL> def __init__ ( self , terminal ) : <EOL> self . exception = None <EOL> self . catch_exception = None <EOL> self . depth = <NUM_LIT:0> <EOL> self . _terminal = weakref . proxy ( terminal ) <EOL> self . _args = None <EOL> self . _animator = None <EOL> self . _is_running = None <EOL> def __call__ ( <EOL> self , <EOL> message = '<STR_LIT>' , <EOL> trail = '<STR_LIT>' , <EOL> delay = <NUM_LIT:0.5> , <EOL> interval = <NUM_LIT> , <EOL> catch_exception = True ) : <EOL> """<STR_LIT>""" <EOL> if self . depth > <NUM_LIT:0> : <EOL> return self <EOL> self . exception = None <EOL> self . catch_exception = catch_exception <EOL> self . _args = ( delay , interval , message , trail ) <EOL> return self <EOL> def __enter__ ( self ) : <EOL> self . depth += <NUM_LIT:1> <EOL> if self . depth > <NUM_LIT:1> : <EOL> return self <EOL> self . _animator = threading . Thread ( target = self . animate , args = self . _args ) <EOL> self . _animator . daemon = True <EOL> self . _is_running = True <EOL> self . _animator . start ( ) <EOL> return self <EOL> def __exit__ ( self , exc_type , e , exc_tb ) : <EOL> self . depth -= <NUM_LIT:1> <EOL> if self . depth > <NUM_LIT:0> : <EOL> return <EOL> self . _is_running = False <EOL> self . _animator . join ( ) <EOL> if e is None or not self . catch_exception : <EOL> return <EOL> self . exception = e <EOL> exc_name = type ( e ) . __name__ <EOL> _logger . info ( '<STR_LIT>' . format ( exc_name , e ) ) <EOL> if isinstance ( e , KeyboardInterrupt ) : <EOL> return True <EOL> for e_type , message in self . EXCEPTION_MESSAGES : <EOL> if isinstance ( e , e_type ) : <EOL> self . _terminal . show_notification ( message . format ( e ) ) <EOL> return True <EOL> def animate ( self , delay , interval , message , trail ) : <EOL> with self . _terminal . no_delay ( ) : <EOL> start = time . time ( ) <EOL> while ( time . time ( ) - start ) < delay : <EOL> if self . _terminal . getch ( ) == self . _terminal . ESCAPE : <EOL> os . kill ( os . getpid ( ) , signal . SIGINT ) <EOL> self . _is_running = False <EOL> if not self . _is_running : <EOL> return <EOL> time . sleep ( <NUM_LIT> ) <EOL> message_len = len ( message ) + len ( trail ) <EOL> n_rows , n_cols = self . _terminal . stdscr . getmaxyx ( ) <EOL> s_row = ( n_rows - <NUM_LIT:3> ) // <NUM_LIT:2> <EOL> s_col = ( n_cols - message_len - <NUM_LIT:1> ) // <NUM_LIT:2> <EOL> window = curses . newwin ( <NUM_LIT:3> , message_len + <NUM_LIT:2> , s_row , s_col ) <EOL> with self . _terminal . no_delay ( ) : <EOL> while True : <EOL> for i in range ( len ( trail ) + <NUM_LIT:1> ) : <EOL> if not self . _is_running : <EOL> window . erase ( ) <EOL> del window <EOL> self . _terminal . stdscr . touchwin ( ) <EOL> self . _terminal . stdscr . refresh ( ) <EOL> return <EOL> window . erase ( ) <EOL> window . border ( ) <EOL> self . _terminal . add_line ( window , message + trail [ : i ] , <NUM_LIT:1> , <NUM_LIT:1> ) <EOL> window . refresh ( ) <EOL> for _ in range ( int ( interval / <NUM_LIT> ) ) : <EOL> if self . _terminal . getch ( ) == self . _terminal . ESCAPE : <EOL> os . kill ( os . getpid ( ) , signal . SIGINT ) <EOL> self . _is_running = False <EOL> break <EOL> time . sleep ( <NUM_LIT> ) <EOL> class Color ( object ) : <EOL> """<STR_LIT>""" <EOL> RED = curses . A_NORMAL <EOL> GREEN = curses . A_NORMAL <EOL> YELLOW = curses . A_NORMAL <EOL> BLUE = curses . A_NORMAL <EOL> MAGENTA = curses . A_NORMAL <EOL> CYAN = curses . A_NORMAL <EOL> WHITE = curses . A_NORMAL <EOL> _colors = { <EOL> '<STR_LIT>' : ( curses . COLOR_RED , - <NUM_LIT:1> ) , <EOL> '<STR_LIT>' : ( curses . COLOR_GREEN , - <NUM_LIT:1> ) , <EOL> '<STR_LIT>' : ( curses . COLOR_YELLOW , - <NUM_LIT:1> ) , <EOL> '<STR_LIT>' : ( curses . COLOR_BLUE , - <NUM_LIT:1> ) , <EOL> '<STR_LIT>' : ( curses . COLOR_MAGENTA , - <NUM_LIT:1> ) , <EOL> '<STR_LIT>' : ( curses . COLOR_CYAN , - <NUM_LIT:1> ) , <EOL> '<STR_LIT>' : ( curses . COLOR_WHITE , - <NUM_LIT:1> ) , <EOL> } <EOL> @ classmethod <EOL> def init ( cls ) : <EOL> """<STR_LIT>""" <EOL> for index , ( attr , code ) in enumerate ( cls . _colors . items ( ) , start = <NUM_LIT:1> ) : <EOL> curses . init_pair ( index , code [ <NUM_LIT:0> ] , code [ <NUM_LIT:1> ] ) <EOL> setattr ( cls , attr , curses . color_pair ( index ) ) <EOL> @ classmethod <EOL> def get_level ( cls , level ) : <EOL> levels = [ cls . MAGENTA , cls . CYAN , cls . GREEN , cls . YELLOW ] <EOL> return levels [ level % len ( levels ) ] <EOL> class Navigator ( object ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( <EOL> self , <EOL> valid_page_cb , <EOL> page_index = <NUM_LIT:0> , <EOL> cursor_index = <NUM_LIT:0> , <EOL> inverted = False , <EOL> top_item_height = None ) : <EOL> """<STR_LIT>""" <EOL> self . page_index = page_index <EOL> self . cursor_index = cursor_index <EOL> self . inverted = inverted <EOL> self . top_item_height = top_item_height <EOL> self . _page_cb = valid_page_cb <EOL> @ property <EOL> def step ( self ) : <EOL> return <NUM_LIT:1> if not self . inverted else - <NUM_LIT:1> <EOL> @ property <EOL> def position ( self ) : <EOL> return self . page_index , self . cursor_index , self . inverted <EOL> @ property <EOL> def absolute_index ( self ) : <EOL> """<STR_LIT>""" <EOL> return self . page_index + ( self . step * self . cursor_index ) <EOL> def move ( self , direction , n_windows ) : <EOL> """<STR_LIT>""" <EOL> assert direction in ( - <NUM_LIT:1> , <NUM_LIT:1> ) <EOL> valid , redraw = True , False <EOL> forward = ( ( direction * self . step ) > <NUM_LIT:0> ) <EOL> if forward : <EOL> if self . page_index < <NUM_LIT:0> : <EOL> if self . _is_valid ( <NUM_LIT:0> ) : <EOL> self . page_index = <NUM_LIT:0> <EOL> self . cursor_index = <NUM_LIT:0> <EOL> redraw = True <EOL> else : <EOL> valid = False <EOL> else : <EOL> self . cursor_index += <NUM_LIT:1> <EOL> if not self . _is_valid ( self . absolute_index ) : <EOL> self . cursor_index -= <NUM_LIT:1> <EOL> valid = False <EOL> elif self . cursor_index >= ( n_windows - <NUM_LIT:1> ) : <EOL> self . flip ( self . cursor_index ) <EOL> self . cursor_index = <NUM_LIT:0> <EOL> self . top_item_height = None <EOL> redraw = True <EOL> else : <EOL> if self . cursor_index > <NUM_LIT:0> : <EOL> self . cursor_index -= <NUM_LIT:1> <EOL> if self . top_item_height and self . cursor_index == <NUM_LIT:0> : <EOL> self . top_item_height = None <EOL> redraw = True <EOL> else : <EOL> self . page_index -= self . step <EOL> if self . _is_valid ( self . absolute_index ) : <EOL> self . top_item_height = None <EOL> redraw = True <EOL> else : <EOL> self . page_index += self . step <EOL> valid = False <EOL> return valid , redraw <EOL> def move_page ( self , direction , n_windows ) : <EOL> """<STR_LIT>""" <EOL> assert direction in ( - <NUM_LIT:1> , <NUM_LIT:1> ) <EOL> assert n_windows >= <NUM_LIT:0> <EOL> if ( self . absolute_index < <NUM_LIT:0> ) | ( n_windows == <NUM_LIT:0> ) : <EOL> valid , redraw = self . move ( direction , n_windows ) <EOL> else : <EOL> if self . absolute_index < n_windows and direction < <NUM_LIT:0> : <EOL> self . page_index = - <NUM_LIT:1> <EOL> self . cursor_index = <NUM_LIT:0> <EOL> self . inverted = False <EOL> if not self . _is_valid ( self . absolute_index ) : <EOL> self . page_index = <NUM_LIT:0> <EOL> valid = True <EOL> else : <EOL> if ( ( direction > <NUM_LIT:0> ) & ( self . inverted is True ) ) | ( ( direction < <NUM_LIT:0> ) & ( self . inverted is False ) ) : <EOL> self . page_index += ( self . step * ( n_windows - <NUM_LIT:1> ) ) <EOL> self . inverted = not self . inverted <EOL> self . cursor_index = ( n_windows - ( direction < <NUM_LIT:0> ) ) - self . cursor_index <EOL> valid = False <EOL> adj = <NUM_LIT:0> <EOL> while not valid : <EOL> n_move = n_windows - adj <EOL> if n_move == <NUM_LIT:0> : <EOL> break <EOL> self . page_index += n_move * direction <EOL> valid = self . _is_valid ( self . absolute_index ) <EOL> if not valid : <EOL> self . page_index -= n_move * direction <EOL> adj += <NUM_LIT:1> <EOL> redraw = True <EOL> return valid , redraw <EOL> def flip ( self , n_windows ) : <EOL> """<STR_LIT>""" <EOL> assert n_windows >= <NUM_LIT:0> <EOL> self . page_index += ( self . step * n_windows ) <EOL> self . cursor_index = n_windows <EOL> self . inverted = not self . inverted <EOL> self . top_item_height = None <EOL> def _is_valid ( self , page_index ) : <EOL> """<STR_LIT>""" <EOL> try : <EOL> self . _page_cb ( page_index ) <EOL> except IndexError : <EOL> return False <EOL> else : <EOL> return True <EOL> class Controller ( object ) : <EOL> """<STR_LIT>""" <EOL> character_map = { } <EOL> def __init__ ( self , instance , keymap = None ) : <EOL> self . instance = instance <EOL> self . parents = inspect . getmro ( type ( self ) ) [ : - <NUM_LIT:1> ] <EOL> if not keymap : <EOL> return <EOL> for controller in self . parents : <EOL> for command , func in controller . character_map . copy ( ) . items ( ) : <EOL> if isinstance ( command , Command ) : <EOL> for key in keymap . get ( command ) : <EOL> val = keymap . parse ( key ) <EOL> if controller . character_map . get ( val , func ) != func : <EOL> raise exceptions . ConfigError ( <EOL> "<STR_LIT>" <EOL> "<STR_LIT>" <EOL> "<STR_LIT:%s>" % ( key , controller . __name__ ) ) <EOL> controller . character_map [ val ] = func <EOL> def trigger ( self , char , * args , ** kwargs ) : <EOL> if isinstance ( char , six . string_types ) and len ( char ) == <NUM_LIT:1> : <EOL> char = ord ( char ) <EOL> func = None <EOL> for controller in self . parents : <EOL> if func : <EOL> break <EOL> func = controller . character_map . get ( char ) <EOL> for controller in self . parents : <EOL> if func : <EOL> break <EOL> func = controller . character_map . get ( None ) <EOL> return func ( self . instance , * args , ** kwargs ) if func else None <EOL> @ classmethod <EOL> def register ( cls , * chars ) : <EOL> def inner ( f ) : <EOL> for char in chars : <EOL> if isinstance ( char , six . string_types ) and len ( char ) == <NUM_LIT:1> : <EOL> cls . character_map [ ord ( char ) ] = f <EOL> else : <EOL> cls . character_map [ char ] = f <EOL> return f <EOL> return inner <EOL> class Command ( object ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , val ) : <EOL> self . val = val . upper ( ) <EOL> def __repr__ ( self ) : <EOL> return '<STR_LIT>' % self . val <EOL> def __eq__ ( self , other ) : <EOL> return repr ( self ) == repr ( other ) <EOL> def __ne__ ( self , other ) : <EOL> return not self == other <EOL> def __hash__ ( self ) : <EOL> return hash ( repr ( self ) ) <EOL> class KeyMap ( object ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , bindings ) : <EOL> self . _keymap = None <EOL> self . set_bindings ( bindings ) <EOL> def set_bindings ( self , bindings ) : <EOL> self . _keymap = { } <EOL> for command , keys in bindings . items ( ) : <EOL> if not isinstance ( command , Command ) : <EOL> command = Command ( command ) <EOL> self . _keymap [ command ] = keys <EOL> def get ( self , command ) : <EOL> if not isinstance ( command , Command ) : <EOL> command = Command ( command ) <EOL> try : <EOL> return self . _keymap [ command ] <EOL> except KeyError : <EOL> raise exceptions . ConfigError ( '<STR_LIT>' <EOL> '<STR_LIT>' % command . val ) <EOL> @ staticmethod <EOL> def parse ( key ) : <EOL> """<STR_LIT>""" <EOL> try : <EOL> if isinstance ( key , int ) : <EOL> return key <EOL> elif re . match ( '<STR_LIT>' , key ) : <EOL> return getattr ( curses , key [ <NUM_LIT:1> : - <NUM_LIT:1> ] ) <EOL> elif re . match ( '<STR_LIT>' , key ) : <EOL> return getattr ( curses . ascii , key [ <NUM_LIT:1> : - <NUM_LIT:1> ] ) <EOL> elif key . startswith ( '<STR_LIT>' ) : <EOL> return int ( key , <NUM_LIT:16> ) <EOL> else : <EOL> code = ord ( key ) <EOL> if <NUM_LIT:0> <= code <= <NUM_LIT:255> : <EOL> return code <EOL> raise exceptions . ConfigError ( '<STR_LIT>' <EOL> '<STR_LIT>' % key ) <EOL> except ( AttributeError , ValueError , TypeError ) : <EOL> raise exceptions . ConfigError ( '<STR_LIT>' <EOL> '<STR_LIT>' % key ) </s>
