def main(): """ Main app loop, handles parsing args and starting the app """ if not os.isatty(0): # If we are getting piped to, use that input stream only raise ValueError('Piping is not supported!') else: # Args if we are passed -h parser = argparse.ArgumentParser( description= 'A powerful CLI tool that puts log analytics at your fingertips.') parser.add_argument( '-e', action='append', type=str, help= 'Command to pass through that will stream into this program, ex: logria -e \'tail -f log.txt\'' ) args = parser.parse_args() if args.e: args = args.e[0].split(' ') stream = CommandInputStream(args) stream.start() else: stream = None # Start the app app = Logria( stream) # If the stream is None, the app will ask the user to init app.start()
def test_launch_no_stream(self): """ Test that we can launch the app This should crash only due to a curses error """ with self.assertRaises(error): os.environ['TERM'] = 'dumb' app = Logria(None, False) app.start()
def test_launch_with_file_stream(self): """ Test that we can launch the app This should crash only due to a curses error """ with self.assertRaises(error): os.environ['TERM'] = 'dumb' stream = FileInputStream(['readme.md']) app = Logria(stream, False) app.start()
def test_launch_with_command_stream(self): """ Test that we can launch the app This should crash only due to a curses error """ with self.assertRaises(error): os.environ['TERM'] = 'dumb' stream = CommandInputStream(['ls', '-l']) app = Logria(stream, False) app.start()
def main(): """ Main app loop, handles parsing args and starting the app """ # Setup CLI args parser = argparse.ArgumentParser(description=constants.APP_DESCRIPTION, ) parser.add_argument('-v', '--version', action='version', version=f'{APP_NAME} {VERSION}') parser.add_argument('-e', action='append', type=str, help=constants.EXEC_HELP) parser.add_argument('-c', '--no-cache', dest='no_cache', default=True, action='store_false', help=constants.HISTORY_HELP) parser.add_argument('-n', '--no-smart-speed', dest='no_smart_speed', default=True, action='store_false', help=constants.SMART_SPEED_HELP) args = parser.parse_args() # pylint: disable=no-else-raise if not os.isatty(0): # If we are getting piped to, use that input stream only print(constants.PIPE_INPUT_ERROR) sys.exit(-1) else: if args.e: command = args.e[0].split(' ') stream = CommandInputStream(command) stream.start() else: # If the stream is None, the app will ask the user to init stream = None app = Logria(stream, history_tape_cache=args.no_cache, smart_poll_rate=args.no_smart_speed) app.start()
def test_process_matches(self): """ Test that we correctly process matches """ os.environ['TERM'] = 'dumb' app = Logria(None, False, False) # Fake window size: 10 x 100 app.height = 10 app.width = 100 # Set fake previous render app.last_row = app.height - 3 # simulate the last row we can render to app.current_end = 80 # Simulate the last message rendered # Set fake messages app.messages = [str(x) for x in range(20)] # Set regex function, process app.func_handle = regex_generator.regex_test_generator(r'\d') process_matches(app) self.assertEqual(app.messages, [str(x) for x in range(20)])
def test_render_first_items(self): """ Test we render properly when stuck to the top """ os.environ['TERM'] = 'dumb' app = Logria(None, False, False) # Fake window size: 10 x 100 app.height = 10 app.width = 100 # Set fake previous render app.last_row = app.height - 3 # simulate the last row we can render to app.current_end = 80 # Simulate the last message rendered # Set fake messages app.messages = [str(x) for x in range(100)] # Set positional booleans app.manually_controlled_line = False app.stick_to_top = True app.stick_to_bottom = False start, end = determine_position(app, app.messages) self.assertEqual(start, -1) self.assertEqual(end, 6) app.stop()
def test_render_scroll_pgup_keystroke(self): """ Test we render properly when stuck to the bottom """ os.environ['TERM'] = 'dumb' app = Logria(None, False, False) # Fake window size: 10 x 100 app.height = 10 app.width = 100 # Set fake previous render app.last_row = app.height - 3 # simulate the last row we can render to app.current_end = 40 # Simulate the last message rendered # Set fake messages app.messages = [str(x) for x in range(100)] # Set positional booleans app.manually_controlled_line = False app.stick_to_top = True app.stick_to_bottom = True # Scroll action resolve_keypress(app, 'KEY_PPAGE') start, end = determine_position(app, app.messages) self.assertEqual(start, 25) self.assertEqual(end, 33) app.stop()
def test_can_render_matches(self): """ Test we render properly when using matches """ os.environ['TERM'] = 'dumb' app = Logria(None, False, False) # Fake window size: 10 x 100 app.height = 10 app.width = 100 # Set fake previous render app.last_row = app.height - 3 # simulate the last row we can render to app.current_end = 80 # Simulate the last message rendered # Set fake messages app.messages = [f'{x}|{x}' for x in range(20)] # Set fake filter app.func_handle = regex_generator.regex_test_generator(r'\d\|\d') process_matches(app) # Set positional booleans app.manually_controlled_line = False app.stick_to_top = True app.stick_to_bottom = False start, end = determine_position(app, app.matched_rows) self.assertEqual(start, -1) self.assertEqual(end, 6) app.stop()
def test_process_parser_invalid_index(self): """ Test that we correctly process parser with invalid index """ os.environ['TERM'] = 'dumb' app = Logria(None, False, False) # Fake window size: 10 x 100 app.height = 10 app.width = 100 # Set fake previous render app.last_row = app.height - 3 # simulate the last row we can render to app.current_end = 80 # Simulate the last message rendered # Set fake messages app.messages = [f'{x}+{x}+{x}' for x in range(10)] app.parser_index = 3 app.last_index_processed = 0 # Set parser, activate app.parser = Parser() app.parser.set_pattern( pattern='\+', type_='split', name='Test', example='a-a', analytics_methods={ 'Item 1': 'count', 'Item 2': 'count' } ) # Store previous message pointer app.previous_messages = app.messages # Process parser process_parser(app) self.assertEqual(app.messages, [])
def test_process_parser_analytics_average_no_numbers(self): """ Test that we correctly process a parser with average metric but no source numbers """ os.environ['TERM'] = 'dumb' app = Logria(None, False, False) # Fake window size: 10 x 100 app.height = 10 app.width = 100 # Set fake previous render app.last_row = app.height - 3 # simulate the last row we can render to app.current_end = 80 # Simulate the last message rendered # Set fake messages app.messages = [chr(x) for x in range(64, 80)] app.parser_index = 0 app.last_index_processed = 0 app.analytics_enabled = True # Set parser, activate app.parser = Parser() app.parser.set_pattern( pattern=r'(\d)', type_='regex', name='Test', example='4', analytics_methods={ 'Item': 'average' } ) # Set analytics method manually app.parser._analytics_map = dict( zip(range(len(app.parser._analytics_methods.keys())), app.parser._analytics_methods.keys())) # Since we manually construct alaytics, create the the key app.parser.analytics[0] = None self.assertIsNone(app.parser.apply_analytics(0, 'A'))
def test_process_parser_split_no_pattern(self): """ Test that we correctly process parser with split no pattern """ os.environ['TERM'] = 'dumb' app = Logria(None, False, False) # Fake window size: 10 x 100 app.height = 10 app.width = 100 # Set fake previous render app.last_row = app.height - 3 # simulate the last row we can render to app.current_end = 80 # Simulate the last message rendered # Set fake messages app.messages = [str(x) for x in range(10)] app.parser_index = 0 app.last_index_processed = 0 # Set parser, activate app.parser = Parser() app.parser.set_pattern( pattern=None, type_='split', name='Test', example='4', analytics_methods={ 'Item': 'average' } ) # Store previous message pointer app.previous_messages = app.messages # Process parser with self.assertRaises(ValueError): process_parser(app)
def test_process_parser_analytics_too_many_matches(self): """ Test that we correctly process parser with too many matches """ os.environ['TERM'] = 'dumb' app = Logria(None, False, False) # Fake window size: 10 x 100 app.height = 10 app.width = 100 # Set fake previous render app.last_row = app.height - 3 # simulate the last row we can render to app.current_end = 80 # Simulate the last message rendered # Set fake messages app.messages = [str(x) for x in range(10, 20)] app.parser_index = 0 app.last_index_processed = 0 app.analytics_enabled = True # Set parser, activate app.parser = Parser() app.parser.set_pattern( pattern=r'(\d)(\d)', type_='regex', name='Test', example='4', analytics_methods={ 'Item': 'invalid' } ) # Set analytics method manually app.parser._analytics_map = dict( zip(range(len(app.parser._analytics_methods.keys())), app.parser._analytics_methods.keys())) # Store previous message pointer app.previous_messages = app.messages # Process parser process_parser(app) self.assertEqual(app.messages, [])