<s> from __future__ import unicode_literals <EOL> from collections import defaultdict <EOL> import inspect <EOL> import re <EOL> import six <EOL> import click <EOL> from . . aliases import aliases_database , Mapping <EOL> from . . utils import date as date_utils , terminal <EOL> from . . exceptions import CancelException <EOL> from . . projects import Project <EOL> class BaseUi ( object ) : <EOL> DURATION_FORMAT = '<STR_LIT>' <EOL> def msg ( self , message , color = None ) : <EOL> click . echo ( message ) <EOL> def err ( self , message ) : <EOL> self . msg ( click . style ( <EOL> click . wrap_text ( "<STR_LIT>" % message , preserve_paragraphs = True ) , <EOL> fg = '<STR_LIT>' ) <EOL> ) <EOL> def warn ( self , message ) : <EOL> self . msg ( click . style ( <EOL> click . wrap_text ( message , preserve_paragraphs = False ) , <EOL> fg = '<STR_LIT>' ) <EOL> ) <EOL> def projects_list ( self , projects , numbered = False ) : <EOL> for ( key , project ) in enumerate ( projects ) : <EOL> if numbered : <EOL> self . msg ( "<STR_LIT>" % ( key , project . id , project . name ) ) <EOL> else : <EOL> self . msg ( "<STR_LIT>" % ( key , project . id , project . name ) ) <EOL> def project_with_activities ( self , project , numbered_activities = False ) : <EOL> self . msg ( six . text_type ( project ) ) <EOL> self . msg ( "<STR_LIT>" ) <EOL> mappings = aliases_database . get_reversed_aliases ( ) <EOL> for ( key , activity ) in enumerate ( project . activities ) : <EOL> mapping = Mapping ( mapping = ( project . id , activity . id ) , <EOL> backend = project . backend ) <EOL> if numbered_activities : <EOL> activity_number = '<STR_LIT>' % ( key ) <EOL> else : <EOL> activity_number = '<STR_LIT>' <EOL> if mapping in mappings : <EOL> self . msg ( "<STR_LIT>" % ( activity_number , <EOL> activity . id , activity . name , <EOL> mappings [ mapping ] ) ) <EOL> else : <EOL> self . msg ( '<STR_LIT>' % ( activity_number , activity . id , <EOL> activity . name ) ) <EOL> def select_project ( self , projects ) : <EOL> if len ( projects ) > <NUM_LIT:1> : <EOL> try : <EOL> return terminal . select_number ( <EOL> len ( projects ) , <EOL> "<STR_LIT>" % <EOL> ( len ( projects ) - <NUM_LIT:1> ) <EOL> ) <EOL> except KeyboardInterrupt : <EOL> raise CancelException ( ) <EOL> else : <EOL> self . msg ( '<STR_LIT>' ) <EOL> return <NUM_LIT:0> <EOL> def select_activity ( self , activities ) : <EOL> if len ( activities ) > <NUM_LIT:1> : <EOL> try : <EOL> return terminal . select_number ( <EOL> len ( activities ) , <EOL> "<STR_LIT>" % <EOL> ( len ( activities ) - <NUM_LIT:1> ) <EOL> ) <EOL> except KeyboardInterrupt : <EOL> raise CancelException ( ) <EOL> else : <EOL> self . msg ( '<STR_LIT>' ) <EOL> return <NUM_LIT:0> <EOL> def select_alias ( self ) : <EOL> try : <EOL> return terminal . select_string ( <EOL> "<STR_LIT>" <EOL> "<STR_LIT>" , r'<STR_LIT>' ) <EOL> except KeyboardInterrupt : <EOL> raise CancelException ( ) <EOL> def overwrite_alias ( self , alias , mapping , retry = True ) : <EOL> if retry : <EOL> choices = '<STR_LIT>' <EOL> default_choice = '<STR_LIT:r>' <EOL> choice_regexp = r'<STR_LIT>' <EOL> else : <EOL> choices = '<STR_LIT>' <EOL> default_choice = '<STR_LIT:n>' <EOL> choice_regexp = r'<STR_LIT>' <EOL> if mapping . mapping : <EOL> mapping_name = Project . tuple_to_str ( mapping . mapping ) <EOL> s = ( "<STR_LIT>" <EOL> "<STR_LIT>" % ( alias , mapping_name , choices ) ) <EOL> else : <EOL> s = ( "<STR_LIT>" <EOL> "<STR_LIT>" % ( alias , choices ) ) <EOL> overwrite = terminal . select_string ( <EOL> s , choice_regexp , re . I , default_choice <EOL> ) <EOL> if overwrite == '<STR_LIT:n>' : <EOL> return False <EOL> elif overwrite == '<STR_LIT:y>' : <EOL> return True <EOL> return None <EOL> def alias_added ( self , alias , mapping ) : <EOL> if mapping : <EOL> mapping_name = Project . tuple_to_str ( mapping ) <EOL> self . msg ( "<STR_LIT>" <EOL> "<STR_LIT>" % ( alias , mapping_name ) ) <EOL> else : <EOL> self . msg ( "<STR_LIT>" <EOL> "<STR_LIT>" % alias ) <EOL> def _show_mapping ( self , mapping , project , alias_first = True ) : <EOL> ( alias , mapping ) = mapping <EOL> if not mapping . is_mapped ( ) : <EOL> self . msg ( "<STR_LIT>" % ( mapping . backend , alias ) ) <EOL> return <EOL> mapping_name = '<STR_LIT>' % mapping . mapping <EOL> if not project : <EOL> project_name = '<STR_LIT>' <EOL> else : <EOL> if mapping . mapping [ <NUM_LIT:1> ] is None : <EOL> project_name = project . name <EOL> mapping_name = mapping . mapping [ <NUM_LIT:0> ] <EOL> else : <EOL> activity = project . get_activity ( mapping . mapping [ <NUM_LIT:1> ] ) <EOL> if activity is None : <EOL> project_name = '<STR_LIT>' % ( project . name ) <EOL> else : <EOL> project_name = '<STR_LIT>' % ( project . name , activity . name ) <EOL> if alias_first : <EOL> args = [ mapping . backend , alias , mapping_name ] <EOL> else : <EOL> args = [ mapping . backend , mapping_name , alias ] <EOL> args . append ( '<STR_LIT>' % project_name if project_name else '<STR_LIT>' ) <EOL> self . msg ( "<STR_LIT>" % tuple ( args ) ) <EOL> def mapping_detail ( self , mapping , project ) : <EOL> self . _show_mapping ( mapping , project , False ) <EOL> def alias_detail ( self , mapping , project ) : <EOL> self . _show_mapping ( mapping , project , True ) <EOL> def clean_inactive_aliases ( self , aliases ) : <EOL> self . msg ( "<STR_LIT>" ) <EOL> for ( mapping , project ) in aliases : <EOL> self . alias_detail ( mapping , project ) <EOL> return click . confirm ( "<STR_LIT>" ) <EOL> def confirm_commit_entries ( self , entries_dict ) : <EOL> self . msg ( "<STR_LIT>" ) <EOL> sorted_entries = sorted ( entries_dict . items ( ) , key = lambda e : e [ <NUM_LIT:0> ] ) <EOL> for date , entries in sorted_entries : <EOL> self . msg ( date_utils . unicode_strftime ( date , '<STR_LIT>' ) ) <EOL> for entry in entries : <EOL> self . msg ( six . text_type ( entry ) ) <EOL> return click . confirm ( "<STR_LIT>" ) <EOL> def ignored_entries_list ( self , entries ) : <EOL> total = <NUM_LIT:0> <EOL> for entry in entries : <EOL> self . msg ( self . get_entry_status ( entry ) ) <EOL> total += entry . hours <EOL> self . msg ( click . style ( '<STR_LIT:\n>' + self . columnize ( [ <EOL> "<STR_LIT>" , self . DURATION_FORMAT . format ( total ) ] <EOL> ) , bold = True ) ) <EOL> def failed_entries_list ( self , entries ) : <EOL> total = <NUM_LIT:0> <EOL> for entry in entries : <EOL> self . msg ( click . style ( <EOL> self . get_entry_status ( entry ) + "<STR_LIT>" + entry . push_error , <EOL> fg = '<STR_LIT>' <EOL> ) ) <EOL> total += entry . hours <EOL> self . msg ( click . style ( '<STR_LIT:\n>' + self . columnize ( [ <EOL> "<STR_LIT>" , self . DURATION_FORMAT . format ( total ) ] <EOL> ) , bold = True , fg = '<STR_LIT>' ) ) <EOL> def get_entry_status ( self , entry ) : <EOL> if entry . is_ignored ( ) : <EOL> status = '<STR_LIT>' <EOL> elif entry . alias not in aliases_database : <EOL> status = '<STR_LIT>' <EOL> else : <EOL> if not aliases_database [ entry . alias ] . is_mapped ( ) : <EOL> status = '<STR_LIT>' <EOL> else : <EOL> status = '<STR_LIT>' % aliases_database [ entry . alias ] . mapping <EOL> try : <EOL> status_format = '<STR_LIT>' if status else '<STR_LIT>' <EOL> status = status_format . format ( <EOL> status = status , <EOL> backend = aliases_database [ entry . alias ] . backend <EOL> ) <EOL> except ( KeyError , AttributeError ) : <EOL> pass <EOL> if status : <EOL> project_name = '<STR_LIT>' % ( entry . alias , status ) <EOL> else : <EOL> project_name = entry . alias <EOL> duration_format = self . DURATION_FORMAT <EOL> if ( entry . alias in aliases_database and <EOL> not aliases_database [ entry . alias ] . is_mapped ( ) ) : <EOL> duration_format = '<STR_LIT:(>' + duration_format + '<STR_LIT:)>' <EOL> return self . columnize ( [ <EOL> project_name , duration_format . format ( entry . hours ) , <EOL> entry . description <EOL> ] ) <EOL> def columnize ( self , text ) : <EOL> for _ in range ( len ( text ) , <NUM_LIT:3> ) : <EOL> text . append ( '<STR_LIT>' ) <EOL> return '<STR_LIT>' . format ( * text ) <EOL> def show_status ( self , entries_dict ) : <EOL> if not list ( filter ( None , entries_dict . values ( ) ) ) : <EOL> self . msg ( "<STR_LIT>" ) <EOL> return <EOL> self . msg ( '<STR_LIT>' ) <EOL> entries_list = entries_dict . items ( ) <EOL> entries_list = sorted ( entries_list ) <EOL> total_hours = <NUM_LIT:0> <EOL> for ( date , entries ) in entries_list : <EOL> if len ( entries ) == <NUM_LIT:0> : <EOL> continue <EOL> subtotal_hours = <NUM_LIT:0> <EOL> current_date = date_utils . unicode_strftime ( date , '<STR_LIT>' ) . capitalize ( ) <EOL> self . msg ( click . style ( <EOL> '<STR_LIT>' % ( current_date ) , <EOL> bold = True <EOL> ) ) <EOL> for entry in entries : <EOL> if ( not entry . is_ignored ( ) and entry . alias not in <EOL> aliases_database ) : <EOL> self . msg ( click . style ( <EOL> self . get_entry_status ( entry ) , fg = '<STR_LIT>' <EOL> ) ) <EOL> close_matches = aliases_database . get_close_matches ( <EOL> entry . alias <EOL> ) <EOL> if close_matches : <EOL> self . msg ( click . style ( <EOL> '<STR_LIT>' % <EOL> '<STR_LIT:U+002CU+0020>' . join ( close_matches ) , fg = '<STR_LIT>' <EOL> ) ) <EOL> else : <EOL> self . msg ( self . get_entry_status ( entry ) ) <EOL> if ( entry . alias not in aliases_database or <EOL> aliases_database [ entry . alias ] . mapping is not None ) : <EOL> subtotal_hours += entry . hours or <NUM_LIT:0> <EOL> self . msg ( self . columnize ( [ <EOL> '<STR_LIT>' , self . DURATION_FORMAT . format ( subtotal_hours ) <EOL> ] ) ) <EOL> total_hours += subtotal_hours <EOL> self . msg ( "<STR_LIT:\n>" + click . style ( self . columnize ( [ <EOL> "<STR_LIT>" , self . DURATION_FORMAT . format ( total_hours ) <EOL> ] ) , bold = True ) ) <EOL> self . msg ( '<STR_LIT>' ) <EOL> def pushed_entry ( self , entry ) : <EOL> if entry . push_error is not None : <EOL> self . msg ( click . style ( "<STR_LIT>" % ( <EOL> self . get_entry_status ( entry ) , <EOL> entry . push_error <EOL> ) , fg = '<STR_LIT>' , bold = True ) ) <EOL> else : <EOL> self . msg ( self . get_entry_status ( entry ) ) <EOL> def pushed_entries_summary ( self , entries , ignored_entries ) : <EOL> backends_total = defaultdict ( int ) <EOL> for entry in entries : <EOL> if entry . push_error is None : <EOL> backends_total [ aliases_database [ entry . alias ] . backend ] += entry . hours <EOL> failed_entries = list ( <EOL> filter ( lambda e : e . push_error is not None , entries ) <EOL> ) <EOL> self . msg ( '<STR_LIT>' ) <EOL> for backend_name , total in backends_total . items ( ) : <EOL> self . msg ( click . style ( self . columnize ( [ <EOL> "<STR_LIT>" + backend_name , <EOL> self . DURATION_FORMAT . format ( total ) <EOL> ] ) , bold = True ) ) <EOL> if ignored_entries : <EOL> self . msg ( click . style ( "<STR_LIT>" , <EOL> fg = '<STR_LIT>' , bold = True ) ) <EOL> self . ignored_entries_list ( ignored_entries ) <EOL> if failed_entries : <EOL> self . msg ( click . style ( "<STR_LIT>" , <EOL> fg = '<STR_LIT>' , bold = True ) ) <EOL> self . failed_entries_list ( failed_entries ) <EOL> def pushing_entries ( self ) : <EOL> self . msg ( "<STR_LIT>" ) <EOL> def search_results ( self , projects ) : <EOL> for project in projects : <EOL> self . msg ( '<STR_LIT>' % ( <EOL> project . get_short_status ( ) , project . backend , project . id , <EOL> project . name <EOL> ) ) <EOL> def suggest_aliases ( self , not_found_alias , aliases ) : <EOL> self . err ( "<STR_LIT>" % <EOL> not_found_alias ) <EOL> if len ( aliases ) > <NUM_LIT:0> : <EOL> self . msg ( "<STR_LIT>" % <EOL> "<STR_LIT>" . join ( aliases ) ) <EOL> def command_usage ( self , command ) : <EOL> self . msg ( inspect . getdoc ( command ) ) <EOL> def updating_projects_database ( self ) : <EOL> self . msg ( "<STR_LIT>" ) <EOL> def projects_database_update_success ( self , aliases_after_update , <EOL> projects_db ) : <EOL> """<STR_LIT>""" <EOL> def show_aliases ( aliases ) : <EOL> """<STR_LIT>""" <EOL> for alias in aliases : <EOL> mapping = aliases_after_update [ alias ] <EOL> ( project , activity ) = projects_db . mapping_to_project ( mapping ) <EOL> self . msg ( "<STR_LIT>" % ( <EOL> alias , project . name if project else "<STR_LIT:?>" , <EOL> activity . name if activity else "<STR_LIT:?>" <EOL> ) ) <EOL> self . msg ( "<STR_LIT>" ) <EOL> deleted_aliases = ( set ( aliases_database . aliases . keys ( ) ) - <EOL> set ( aliases_after_update . keys ( ) ) ) <EOL> added_aliases = ( set ( aliases_after_update . keys ( ) ) - <EOL> set ( aliases_database . aliases . keys ( ) ) ) <EOL> modified_aliases = set ( ) <EOL> for alias , mapping in six . iteritems ( aliases_after_update ) : <EOL> if ( alias in aliases_database <EOL> and aliases_database [ alias ] != mapping ) : <EOL> modified_aliases . add ( alias ) <EOL> if added_aliases : <EOL> self . msg ( "<STR_LIT>" ) <EOL> show_aliases ( added_aliases ) <EOL> if deleted_aliases : <EOL> self . msg ( "<STR_LIT>" ) <EOL> for alias in deleted_aliases : <EOL> self . msg ( alias ) <EOL> if modified_aliases : <EOL> self . msg ( "<STR_LIT>" ) <EOL> show_aliases ( modified_aliases ) <EOL> def show_command_results ( self , search , matches , projects_db ) : <EOL> def mapping_to_activity_name ( mapping ) : <EOL> activity = projects_db . mapping_to_project ( mapping ) <EOL> if not activity [ <NUM_LIT:0> ] or not activity [ <NUM_LIT:1> ] : <EOL> activity_str = "<STR_LIT>" <EOL> else : <EOL> activity_str = '<STR_LIT>' . format ( <EOL> activity [ <NUM_LIT:0> ] . name , activity [ <NUM_LIT:1> ] . name <EOL> ) <EOL> return activity_str <EOL> matches_str = [ ] <EOL> for alias in matches [ '<STR_LIT>' ] : <EOL> if not alias . is_mapped ( ) : <EOL> matches_str . append ( "<STR_LIT>" ) <EOL> else : <EOL> activity_str = mapping_to_activity_name ( alias ) <EOL> matches_str . append ( <EOL> "<STR_LIT>" <EOL> "<STR_LIT>" . format ( <EOL> activity = click . style ( activity_str , bold = True ) , <EOL> mapping = '<STR_LIT>' % alias . mapping , <EOL> backend = click . style ( alias . backend , bold = True ) <EOL> ) <EOL> ) <EOL> for project , activity in matches [ '<STR_LIT>' ] : <EOL> if activity : <EOL> matches_str . append ( <EOL> "<STR_LIT>" . format ( <EOL> project = click . style ( project . name , bold = True ) , <EOL> activity = click . style ( activity . name , bold = True ) <EOL> ) <EOL> ) <EOL> else : <EOL> matches_str . append ( "<STR_LIT>" . format ( <EOL> click . style ( project . name , bold = True ) <EOL> ) ) <EOL> for mapping , alias in matches [ '<STR_LIT>' ] : <EOL> activity_str = mapping_to_activity_name ( mapping ) <EOL> matches_str . append ( <EOL> "<STR_LIT>" . format ( <EOL> alias = click . style ( alias , bold = True ) , <EOL> backend = click . style ( mapping . backend , bold = True ) <EOL> ) <EOL> ) <EOL> self . msg ( "<STR_LIT>" % ( <EOL> click . style ( search , bold = True ) , <EOL> '<STR_LIT:U+002CU+0020>' . join ( matches_str ) if matches_str else "<STR_LIT>" <EOL> ) ) </s>
