2018-06-20 13:09:51 +03:00
""" Interactive python shell with port_stats
What ' s in the box:
2018-08-14 13:11:50 +03:00
- load ( ) - - ( re ) loads the task and packages information
- use ( repo ) - - switch to using < repo >
- load ( repo ) - - load stuff and start using the given repo instead of default
2018-06-20 13:09:51 +03:00
- pt ( name ) - - prints information about the package tasks
2018-06-22 13:40:38 +03:00
- spt ( name ) - - prints information about the package tasks , short version
- spi ( name ) - - prints the short package information
2019-01-22 12:05:05 +03:00
- gspi ( pattern ) , g - - prints the short package information for
2018-08-14 13:11:50 +03:00
all the packages with name matching pattern ( ' g ' for ' grep ' )
- list_spi ( pkgs_list ) - - same as gspi , but for python lists
2018-07-04 14:53:40 +03:00
of strings instead of patterns
2018-06-20 13:09:51 +03:00
- ti ( num ) - - prints information about the task #num
2018-06-22 13:40:38 +03:00
- fti ( num ) - - prints information about the task #num, full version (a dict)
2019-01-22 12:05:05 +03:00
- logs ( num , [ idx ] ) , l - - print logs ( logs / events . X . Y . log ) for task #num
2018-07-19 16:46:03 +03:00
- next_tasks ( ) - - display all non - done tasks that would update packages
2018-08-14 13:11:50 +03:00
- stats ( ) - - prints packages statistics
2018-06-20 13:09:51 +03:00
You can also enjoy autocompletion with < TAB > .
"""
2018-08-10 17:39:27 +03:00
2018-06-20 13:09:51 +03:00
from __future__ import print_function
import atexit
2018-08-10 17:39:27 +03:00
import json
2018-06-20 13:09:51 +03:00
import logging
import os
2018-06-22 13:40:38 +03:00
import re
2018-06-20 13:09:51 +03:00
import readline
2019-01-23 12:46:03 +03:00
import rlcompleter # noqa
2018-06-20 13:09:51 +03:00
import sys
from pydoc import pager
2018-06-22 13:40:38 +03:00
from port_stats import colorize
2018-06-20 13:09:51 +03:00
from port_stats import lists
2019-01-17 12:25:22 +03:00
from port_stats import logs as m_logs
2018-06-22 13:40:38 +03:00
from port_stats import reports
2019-01-17 12:25:22 +03:00
from port_stats import task_predicates as tp
from port_stats import tasks
2018-06-20 13:09:51 +03:00
from port_stats import utils
LOG = logging . getLogger ( ' port_stats.interactive ' )
2019-01-13 20:52:30 +03:00
def get_task ( taskid , task_dict ) :
try :
return task_dict [ int ( taskid ) ]
except Exception :
raise ValueError ( ' Task not found: %s ' % taskid )
2018-06-20 13:09:51 +03:00
2018-08-10 17:39:27 +03:00
2018-06-20 13:09:51 +03:00
def package_tasks ( pkg , data ) :
ts = sorted ( data [ pkg ] , key = lambda t : int ( t [ ' taskid ' ] ) )
return ' \n ' . join ( tasks . format_task ( t ) for t in ts )
2019-01-17 12:25:22 +03:00
# {{{ to= targets
2018-08-10 17:39:27 +03:00
def dump ( string ) :
print ( string )
def append_to ( filename ) :
def _write ( string ) :
2019-01-17 12:25:22 +03:00
if os . path . exists ( filename ) :
LOG . info ( ' File %s already exists, appending ' , filename )
2018-08-10 17:39:27 +03:00
with open ( filename , ' a ' ) as f :
f . write ( string )
f . write ( ' \n ' )
return _write
2019-01-17 12:25:22 +03:00
# }}}
# The Interactive Part
2018-06-20 13:09:51 +03:00
2018-08-10 17:39:27 +03:00
CONFIG = None
CURRENT = None
REPOS = { }
2019-01-13 20:52:30 +03:00
TASKS = { }
2018-06-20 13:09:51 +03:00
PACKAGE_TASKS = { }
2018-06-22 13:40:38 +03:00
BY_NAME = { }
BY_COLOR = { }
2018-06-20 13:09:51 +03:00
2019-01-13 20:52:30 +03:00
def repo_tasks ( task_dict = None ) :
for _ , t in sorted ( TASKS . iteritems ( ) ) :
if t [ ' repo ' ] == CURRENT [ ' new ' ] :
yield t
2018-08-10 17:39:27 +03:00
def use ( repo = None ) :
global PACKAGE_TASKS , BY_NAME , BY_COLOR , CURRENT
if repo is not None :
try :
2019-01-17 12:25:22 +03:00
CURRENT = ( c for c in CONFIG [ ' colorize ' ]
if c [ ' name ' ] == repo ) . next ( )
2018-08-10 17:39:27 +03:00
except StopIteration :
raise ValueError ( ' Unknown repo: ' + repo )
elif CURRENT is None :
CURRENT = CONFIG [ ' colorize ' ] [ 0 ]
LOG . info ( " Updating data structures for %s ... " , CURRENT [ ' name ' ] )
sys . ps1 = CURRENT [ ' name ' ] + ' >>> '
2019-01-13 20:52:30 +03:00
PACKAGE_TASKS = tasks . tasks_by_package ( repo_tasks ( ) )
2018-08-10 17:39:27 +03:00
BY_NAME , BY_COLOR = colorize . colorize ( REPOS [ CURRENT [ ' base ' ] ] ,
REPOS [ CURRENT [ ' new ' ] ] )
2018-06-20 13:09:51 +03:00
LOG . info ( " DONE " )
2018-08-10 17:39:27 +03:00
def load ( repo = None ) :
global TASKS , REPOS
2019-01-17 11:39:23 +03:00
TASKS = dict ( ( t [ ' taskid ' ] , t )
for t in tasks . load_tasks ( CONFIG [ ' tasks ' ] , cache = TASKS ) )
2018-08-10 17:39:27 +03:00
REPOS = lists . read_all_srclists ( CONFIG [ ' repos ' ] )
LOG . info ( " Got %s tasks, %s repositories " , len ( TASKS ) , len ( REPOS ) )
for name in sorted ( REPOS ) :
LOG . info ( " %s : %s srpms " , name , len ( REPOS [ name ] ) )
use ( repo )
2018-07-04 14:53:40 +03:00
2018-06-20 13:09:51 +03:00
def pt ( pkg , to = print ) :
to ( package_tasks ( pkg , PACKAGE_TASKS ) )
2018-06-22 13:40:38 +03:00
def spt ( pkg , to = print ) :
to ( tasks . format_tasks_short ( PACKAGE_TASKS . get ( pkg ) ) )
def spi ( pkg , to = print ) :
to ( reports . package_one_line ( pkg , BY_NAME , PACKAGE_TASKS ) )
2018-12-13 16:37:09 +03:00
def _spi_by_predicate ( pred , colors ) :
2018-06-22 13:40:38 +03:00
colors = colors or colorize . COLORS
2018-12-13 16:37:09 +03:00
return ' \n ' . join (
2018-06-22 13:40:38 +03:00
reports . package_one_line ( name , BY_NAME , PACKAGE_TASKS )
for name in sorted ( BY_NAME )
2018-07-04 14:53:40 +03:00
if pred ( name ) and BY_NAME [ name ] [ 0 ] in colors )
2018-06-22 13:40:38 +03:00
2018-08-14 13:11:50 +03:00
def gspi ( pattern , colors = None , to = print ) :
2018-07-04 14:53:40 +03:00
p = re . compile ( pattern )
2018-12-13 16:37:09 +03:00
to ( _spi_by_predicate ( p . search , colors ) )
2018-07-04 14:53:40 +03:00
2019-01-22 12:05:05 +03:00
g = gspi # noqa
2018-07-04 14:53:40 +03:00
def list_spi ( pkgs , colors = None , to = print ) :
pset = frozenset ( pkgs )
2018-12-13 16:37:09 +03:00
lines = _spi_by_predicate ( pset . __contains__ , colors )
unknown = pset - frozenset ( BY_NAME )
if unknown :
lines + = " \n Not in repos: \n \t " + " \n \t " . join ( sorted ( unknown ) )
to ( lines )
2018-07-04 14:53:40 +03:00
2018-06-20 13:09:51 +03:00
def ti ( num , to = print ) :
2018-12-13 15:51:50 +03:00
to ( reports . format_colored_task ( get_task ( num , TASKS ) , BY_NAME ) )
2018-07-19 16:46:03 +03:00
2018-12-13 15:51:50 +03:00
def display_tasks ( infos , include = None , exclude = None , to = pager ) :
tasks = ( reports . format_colored_task ( t , BY_NAME ) for t in infos )
2018-08-15 16:23:15 +03:00
if include :
p = re . compile ( include )
2018-12-13 15:51:50 +03:00
tasks = ( t for t in tasks if p . search ( t ) )
2018-08-15 16:23:15 +03:00
if exclude :
p = re . compile ( exclude )
2018-12-13 15:51:50 +03:00
tasks = ( t for t in tasks if not p . search ( t ) )
tasks = list ( tasks )
2018-08-14 13:13:21 +03:00
to ( " %s tasks \n \n %s " % ( len ( tasks ) , ' \n \n ' . join ( tasks ) ) )
2018-06-20 13:09:51 +03:00
2018-12-13 15:51:50 +03:00
def next_tasks ( include = None , exclude = None , to = pager ) :
filters = [ tp . not_ ( tp . has ( ' state ' , ' DONE ' ) ) ,
tp . has ( ' owner ' , ' recycler ' ) ,
tp . has_fresh_subtasks ( BY_NAME ) ]
2019-01-13 20:52:30 +03:00
display_tasks ( ( t for t in repo_tasks ( ) if all ( f ( t ) for f in filters ) ) ,
2018-12-13 15:51:50 +03:00
include , exclude , to )
2018-06-20 13:09:51 +03:00
def fti ( num , to = print ) :
to ( utils . format_dict ( get_task ( num , TASKS ) , indent = True ) )
def logs ( num , idx = - 1 , to = pager ) :
2018-09-11 12:57:21 +03:00
log_file = m_logs . task_event_logs ( get_task ( num , TASKS ) ) [ idx ]
2018-06-20 13:09:51 +03:00
with open ( log_file , ' r ' ) as f :
2019-01-22 12:03:49 +03:00
log = f . read ( ) . decode ( ' utf-8 ' , errors = ' replace ' )
2018-06-20 13:09:51 +03:00
to ( log_file + ' : \n \n ' + log )
2019-01-22 12:05:05 +03:00
l = logs # noqa
2018-09-11 15:49:57 +03:00
def stats ( names = None , to = dump ) :
total = len ( names ) if names else len ( REPOS [ CURRENT [ ' new ' ] ] )
to ( reports . color_totals ( BY_COLOR , names , total , summary = True ) )
2018-08-14 13:11:50 +03:00
2018-06-20 13:09:51 +03:00
def interactive_setup ( ) :
# Bind ‘ TAB’ to complete
readline . parse_and_bind ( ' tab:complete ' )
# Set history file – ~\.pythonhistory
histfile = os . path . join ( os . environ [ ' HOME ' ] , ' .pythonhistory ' )
# Attempt read of histfile
try :
readline . read_history_file ( histfile )
except IOError :
pass
# Write history file at shell exit
atexit . register ( readline . write_history_file , histfile )
# Configure logging
logging . basicConfig (
format = ' %(asctime)s %(levelname)-5s %(name)s - %(message)s ' ,
datefmt = ' % Y- % m- %d % H: % M: % S ' ,
stream = sys . stderr , level = logging . INFO )
2018-08-10 17:39:27 +03:00
config = sys . argv [ 1 ]
LOG . info ( " Loading configuraition file: %s " , config )
with open ( config , ' r ' ) as f :
global CONFIG
CONFIG = json . load ( f )
2019-01-17 12:25:22 +03:00
2018-06-20 13:09:51 +03:00
if __name__ == ' __main__ ' :
interactive_setup ( )
print ( __doc__ )