def test_text_effects(self): """ Check effects can be played. """ # Skip for non-Windows if the terminal definition is incomplete. # This typically means we're running inside a non-standard termina;. # For example, thi happens when embedded in PyCharm. if sys.platform != "win32": curses.initscr() if curses.tigetstr("ri") is None: self.skipTest("No valid terminal definition") # A lot of effects are just about the visual output working when played # so check that playing a load of text effects doesn't crash. # # It's really not a great test, but it's important to show Effects are # dynamically compatible with Screen.play(). def internal_checks(screen): screen.play([ Scene([ MockEffect(count=5), Print(screen, FigletText("hello"), 2), Cycle(screen, FigletText("world"), 6), BannerText(screen, FigletText("world"), 10, 3), Mirage(screen, FigletText("huh?"), 14, 2)], 0)]) Screen.wrapper(internal_checks, height=25)
def test_palette(self): """ Check that we have a valid colour palette. """ def internal_checks(screen): # Check basic length self.assertGreater(screen.colours, 0) self.assertEqual(len(screen.palette), 256 * 3) # Should always have fundamental console colours for i, c in enumerate((0, 0, 0)): self.assertEqual(screen.palette[i], c) for i, c in enumerate((128, 0, 0)): self.assertEqual(screen.palette[i+3], c) for i, c in enumerate((0, 128, 0)): self.assertEqual(screen.palette[i+6], c) for i, c in enumerate((128, 128, 0)): self.assertEqual(screen.palette[i+9], c) for i, c in enumerate((0, 0, 128)): self.assertEqual(screen.palette[i+12], c) for i, c in enumerate((128, 0, 128)): self.assertEqual(screen.palette[i+15], c) for i, c in enumerate((0, 128, 128)): self.assertEqual(screen.palette[i+18], c) for i, c in enumerate((192, 192, 192)): self.assertEqual(screen.palette[i+21], c) Screen.wrapper(internal_checks, height=15)
def test_key_input(self): """ Check that keyboard input works. """ def internal_checks(screen): # Inject a letter and check it is picked up self._inject_key(screen, ord("a")) ch = screen.get_event() self.assertEqual(ch.key_code, ord("a")) self.assertIsNone(screen.get_event()) # Inject a letter and check it is picked up self._inject_key(screen, Screen.KEY_BACK_TAB) ch = screen.get_event() self.assertEqual(ch.key_code, Screen.KEY_BACK_TAB) self.assertIsNone(screen.get_event()) # Check that get_key also works. self._inject_key(screen, ord("b")) ch = screen.get_key() self.assertEqual(ch, ord("b")) self.assertIsNone(screen.get_key()) # Check that unicode input also works self._inject_key(screen, ord(u"├")) ch = screen.get_event() self.assertEqual(ch.key_code, ord(u"├")) self.assertIsNone(screen.get_event()) Screen.wrapper(internal_checks, height=15, unicode_aware=True)
def test_limits(self): """ Check that get_from and print_at limit checking works. """ def internal_checks(screen): # Check we have some canvas dimensions self.assertEqual(screen.dimensions[1], screen.width) self.assertEqual(screen.dimensions[0], screen.height) # Basic limit checking self.assertIsNone(screen.get_from(-1, -1)) self.assertIsNone(screen.get_from(screen.width, screen.height)) # Printing off-screen should not fail, but do nothing. screen.print_at("hello", 0, -1) screen.print_at("hello", 0, screen.height) # Printing across screen edge should crop. screen.print_at("12345", -1, 0) char, fg, _, bg = screen.get_from(0, 0) self.assertEqual(char, ord("2")) self.assertEqual(fg, Screen.COLOUR_WHITE) self.assertEqual(bg, Screen.COLOUR_BLACK) Screen.wrapper( check_screen_and_canvas, height=15, arguments=[internal_checks])
def test_last_pos(self): """ Check that screen drawing is efficient and unaffected by draw. """ def internal_checks(screen): # Should start with no known location. screen.reset() self.assertEqual(screen._cur_x, None) self.assertEqual(screen._cur_y, None) # Drawing should not affect latest update. This was previously # bugged - hence this test case! screen.move(0, 0) screen.draw(10, 10) self.assertEqual(screen._cur_x, None) self.assertEqual(screen._cur_y, None) # Printing should not affect latest update. screen.print_at("Hi", 12, 12) self.assertEqual(screen._cur_x, None) self.assertEqual(screen._cur_y, None) # Refresh should update the last drawn character. screen.refresh() self.assertEqual(screen._cur_x, 14) self.assertEqual(screen._cur_y, 12) Screen.wrapper( internal_checks, height=15, unicode_aware=False)
def test_play(self): """ Check that we can play a basic Effect in a Scene. """ def internal_checks(screen): # Since the Screen draws things, there's not too much we can do # to genuinely verify this without verifying all Scene and Effect # function too. Just play a dummy Effect for now. test_effect = MockEffect() screen.play([Scene([test_effect], 0)]) self.assertTrue(test_effect.stop_called) self.assertTrue(test_effect.reset_called) # Now check that the desired duration is used. test_effect = MockEffect(count=6) screen.play([Scene([test_effect], 15)]) self.assertFalse(test_effect.stop_called) self.assertTrue(test_effect.reset_called) # Now check that delete_count works. test_effect = MockEffect(count=6) test_effect2 = MockEffect(delete_count=3) scene = Scene([test_effect, test_effect2], 15) self.assertEqual(len(scene.effects), 2) screen.play([scene]) self.assertEqual(len(scene.effects), 1) self.assertEqual(scene.effects[0], test_effect) Screen.wrapper(internal_checks, height=15)
def test_polygons(self): """ Check that filled polygons work as expected. """ def internal_checks(screen): screen.fill_polygon([[(0, 0), (10, 0), (0, 10), (10, 10)]]) screen.fill_polygon([[(20, 0), (30, 0), (30, 10), (25, 5), (20, 10)]]) screen.fill_polygon([[(40, 0), (45, 5), (50, 0), (50, 10), (40, 10)]]) screen.fill_polygon([[(60, 0), (70, 0), (70, 10), (60, 10)], [(63, 2), (67, 2), (67, 8), (63, 8)]]) self.maxDiff = None self.assert_canvas_equals( screen, "Y########7 ########## . . ########## \n" + " Y######7 ########## #. .# ########## \n" + " Y####7 ########## ##. .## ### ### \n" + " Y##7 ########## ###. .### ### ### \n" + " Y7 ########## ####..#### ### ### \n" + " .. ####7Y#### ########## ### ### \n" + " .##. ###7 Y### ########## ### ### \n" + " .####. ##7 Y## ########## ### ### \n" + " .######. #7 Y# ########## ########## \n" + ".########. 7 Y ########## ########## \n") Screen.wrapper( check_screen_and_canvas, height=10, unicode_aware=False, arguments=[internal_checks])
def test_origin(self): """ Check that Canvas origin is correct. """ def internal_checks(screen): canvas = Canvas(screen, 5, 5, 1, 2) self.assertEqual(canvas.origin, (1, 2)) Screen.wrapper(internal_checks, height=15)
def test_title(self): """ Check that we can change the screen title. """ def internal_checks(screen): # It's not possible to read values back, so just check code doesn't # crash. screen.set_title("Asciimatics test") Screen.wrapper(internal_checks, height=15)
def test_centre(self): """ Check that centre works as expected. """ def internal_checks(screen): screen.centre("1234", 0) char, fg, _, bg = screen.get_from((screen.width - 4) // 2, 0) self.assertEqual(char, ord("1")) self.assertEqual(fg, Screen.COLOUR_WHITE) self.assertEqual(bg, Screen.COLOUR_BLACK) Screen.wrapper(internal_checks, height=15)
def test_draw(self): """ Check that line drawing works as expected. """ def internal_checks(screen): # Draw thick and thin lines for line_type in (True, False): # Draw in opposite directions for start in range(0, 11, 10): screen.print_at(str(start), 11, 2) # Horizontal line screen.move(start, 0) screen.draw(10 - start, 0, thin=line_type) res = screen.get_from(1, 0) self.assertEqual(res[0], ord("^" if line_type else "#")) # Check clearing works too screen.draw(start, 0, char=" ", thin=line_type) res = screen.get_from(1, 0) self.assertEqual(res[0], ord(" ")) # Vertical line screen.move(0, start) screen.draw(0, 10 - start, thin=line_type) res = screen.get_from(0, 1) self.assertEqual(res[0], ord("|" if line_type else "#")) # Check clearing works too screen.draw(0, start, char=" ", thin=line_type) res = screen.get_from(0, 1) self.assertEqual(res[0], ord(" ")) # Diagonal line screen.move(0, start) screen.draw(10, 10 - start, thin=line_type) res = screen.get_from(1, 9 if start else 1) if line_type: self.assertEqual(res[0], ord("'" if start else "\\")) else: self.assertEqual(res[0], ord("7" if start else "Y")) # Check clearing works too screen.move(0, start) screen.draw(10, 10 - start, char=" ", thin=line_type) res = screen.get_from(1, 9 if start else 1) self.assertEqual(res[0], ord(" ")) Screen.wrapper( check_screen_and_canvas, height=15, unicode_aware=False, arguments=[internal_checks])
def test_next_scene(self): """ Check that we can play multiple Scenes. """ def internal_checks(screen): # First check that we can move between screens. test_effect1 = MockEffect(stop=False) test_effect2 = MockEffect(count=5) screen.play([ Scene([test_effect1], 5), Scene([test_effect2], 0)]) self.assertTrue(test_effect1.update_called) self.assertTrue(test_effect2.update_called) # Now check that we can start at the second scene. test_effect1 = MockEffect(stop=False) scene1 = Scene([test_effect1], 5, name="1") test_effect2 = MockEffect(count=3) scene2 = Scene([test_effect2], 0, name="2") screen.play([scene1, scene2], start_scene=scene2) self.assertFalse(test_effect1.update_called) self.assertTrue(test_effect2.update_called) # Now check that we can move to named scenes. test_effect1 = MockEffect(stop=False, next_scene="B") test_effect2 = MockEffect(count=5) screen.play([ Scene([test_effect1], 15, name="A"), Scene([test_effect2], 0, name="B")]) self.assertTrue(test_effect1.update_called) self.assertTrue(test_effect2.update_called) # Now check that bad names cause an exception. with self.assertRaises(RuntimeError): test_effect1 = MockEffect(stop=False, next_scene="C") test_effect2 = MockEffect(count=5) screen.play([ Scene([test_effect1], 15, name="A"), Scene([test_effect2], 0, name="B")]) self.assertTrue(test_effect1.update_called) self.assertFalse(test_effect2.update_called) # Now check that play stops at the end when repeat=False test_effect1 = MockEffect(stop=False) scene1 = Scene([test_effect1], 5, name="1") screen.play([scene1], repeat=False) self.assertTrue(test_effect1.update_called) Screen.wrapper(internal_checks, height=15)
def test_refresh(self): """ Check that refresh works. """ def internal_checks(screen): # Not much we can do here as refresh will draw to a screen we can't # query. Check that we don't hit an Exception on refresh(). screen.print_at("Hello world!", 0, 0, colour=Screen.COLOUR_CYAN, attr=Screen.A_BOLD, bg=Screen.COLOUR_BLUE) screen.refresh() Screen.wrapper( check_screen_and_canvas, height=15, arguments=[internal_checks])
def display(self): while True: try: # save the console so if the program encounters # a problem/exception we may be able to restore the console self._save_window() Screen.wrapper(self._start_app, catch_interrupt=False, arguments=[self.last_scene]) break except ResizeScreenError as e: self.last_scene = e.scene except Exception as e: print('Unhandled exception: ' + str(e)) self._restore_window() raise e
def process_event(self, event): # Do the key handling for this Frame. if isinstance(event, KeyboardEvent): if event.key_code in [ord('q'), ord('Q'), Screen.ctrl("c")]: raise StopApplication("User quit") # Now pass on to lower levels for normal handling of the event. return super(DemoFrame, self).process_event(event)
def test_visible(self): """ Check that is_visible works as expected. """ def internal_checks(screen): # Check some points that must always be visible self.assertTrue(screen.is_visible(0, 0)) self.assertTrue(screen.is_visible( screen.width - 1, screen.height - 1)) # Check some points that cannot be visible self.assertFalse(screen.is_visible(-1, -1)) self.assertFalse(screen.is_visible( screen.width, screen.height)) Screen.wrapper( check_screen_and_canvas, height=15, arguments=[internal_checks])
def test_scroll(self): """ Check that scrolling works as expected. """ def internal_checks(screen): # New screen is not scrolled. self.assertEqual(screen.start_line, 0) # Scroll and check it has moved screen.scroll() self.assertEqual(screen.start_line, 1) # Scroll to specific location and check it has moved screen.scroll_to(0) self.assertEqual(screen.start_line, 0) Screen.wrapper(internal_checks, height=15)
def test_wrapper_return(self): """ Check that you get the result back from the wrapped function. """ def internal_checks(_): return True self.assertTrue(Screen.wrapper(internal_checks))
def test_unhandled_events(self): """ Check that default handling of events works as documented. """ def internal_checks(screen): # Check for exit for char in ("X", "x", "Q", "q"): with self.assertRaises(StopApplication): event = KeyboardEvent(ord(char)) screen._unhandled_event_default(event) for char in (" ", "\n"): with self.assertRaises(NextScene): event = KeyboardEvent(ord(char)) screen._unhandled_event_default(event) Screen.wrapper(internal_checks, height=15)
def test_signal(self): """ Check that signals are restored after using _CursesScreen """ if sys.platform == "win32": self.skipTest("Windows does not have signals.") def dummy_signal_handler(): """Dummy previous signal handler.""" pass outer_state = _SignalState() self.assertNotEqual(signal.getsignal(signal.SIGWINCH), dummy_signal_handler) outer_state.set(signal.SIGWINCH, dummy_signal_handler) self.assertEqual(signal.getsignal(signal.SIGWINCH), dummy_signal_handler) Screen.wrapper(self.signal_check) self.assertEqual(signal.getsignal(signal.SIGWINCH), dummy_signal_handler) outer_state.restore() self.assertNotEqual(signal.getsignal(signal.SIGWINCH), dummy_signal_handler)
def test_ctrl(self): """ Check that ctrl returns the right values. """ # Check standard alphabetical range for i, char in enumerate(range(ord('@'), ord('Z'))): self.assertEqual(Screen.ctrl(char), i) self.assertEqual(Screen.ctrl(chr(char)), i) self.assertEqual(Screen.ctrl(chr(char).lower()), i) # Check last few options - which mostly aren't actually returned in # Linux and so probably only of limited value, but what the heck! for i, char in enumerate(["[", "\\", "]", "^", "_"]): self.assertEqual(Screen.ctrl(char), i + 27) # Check other things return None - pick boundaries for checks. for char in ["?", "`", "\x7f"]: self.assertIsNone(Screen.ctrl(char))
def test_uni_image_files(self): """ Check that the unicode ColourImageFile rendering works. """ # Skip for non-Windows if the terminal definition is incomplete. # This typically means we're running inside a non-standard terminal. # For example, this happens when embedded in PyCharm. if sys.platform != "win32": curses.initscr() if curses.tigetstr("ri") is None: self.skipTest("No valid terminal definition") def internal_checks(screen): # Check the original FG only rendering renderer = ColourImageFile( screen, os.path.join(os.path.dirname(__file__), "globe.gif"), height=10, uni=True, dither=True) # Check renderer got all images from the file. count = 0 for image in renderer.images: count += 1 self.assertIsNotNone(image) self.assertIsNotNone(len(image) <= renderer.max_height) self.assertEqual(count, 11) # Check an image looks plausible image = next(renderer.images) self.assertEqual( image, ['.', '.....▄▄▄▄▄▄▄▄▄▄......', '...▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄...', '.▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄..', '.▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄.', '▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄.', '▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄.', '.▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄.', '.▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄..', '...▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄...', '.....▄▄▄▄▄▄▄▄▄▄▄.....']) Screen.wrapper(internal_checks, height=15)
def test_putch_and_getch(self): """ Check deprecated features still work. """ def internal_checks(screen): for x in range(screen.width): for y in range(15): char = randint(0, 255) fg = randint(0, Screen.COLOUR_WHITE) bg = randint(0, Screen.COLOUR_WHITE) attr = randint(0, Screen.A_UNDERLINE) screen.putch(chr(char), x, y, fg, attr, bg) char2, fg2, attr2, bg2 = screen.getch(x, y) self.assertEqual(char, char2) self.assertEqual(fg, fg2) self.assertEqual(attr, attr2) self.assertEqual(bg, bg2) Screen.wrapper(internal_checks, height=15)
def test_highlight(self): """ Check that highlight works as expected. """ def internal_checks(screen): for x in range(screen.width): for y in range(15): char = randint(0, 255) fg = randint(Screen.COLOUR_RED, Screen.COLOUR_WHITE) bg = randint(Screen.COLOUR_RED, Screen.COLOUR_WHITE) attr = randint(0, Screen.A_UNDERLINE) screen.print_at(chr(char), x, y, fg, attr, bg) # Check BG highlight first. screen.highlight(-1, -1, screen.width + 2, screen.height + 2, bg=0) for x in range(screen.width): for y in range(15): _, fg2, _, bg2 = screen.get_from(x, y) self.assertEqual(bg2, 0) self.assertNotEqual(fg2, 0) # Now check FG highlighting. screen.highlight(-1, -1, screen.width + 2, screen.height + 2, fg=0) for x in range(screen.width): for y in range(15): _, fg2, _, bg2 = screen.get_from(x, y) self.assertEqual(bg2, 0) self.assertEqual(fg2, 0) # Now check blending. screen.print_at("*" * screen.width, 0, 0, Screen.COLOUR_CYAN, Screen.A_NORMAL, Screen.COLOUR_YELLOW) screen.highlight(0, 0, screen.width, 1, fg=0, bg=0, blend=50) for x in range(screen.width): _, fg2, _, bg2 = screen.get_from(x, 0) self.assertEqual(bg2, 0) self.assertEqual(fg2, 0) Screen.wrapper( check_screen_and_canvas, height=15, arguments=[internal_checks])
def test_print_and_get(self): """ Check that basic print_at and get_from work as expected. """ def internal_checks(screen): for x in range(screen.width): for y in range(15): char = randint(0, 255) fg = randint(0, Screen.COLOUR_WHITE) bg = randint(0, Screen.COLOUR_WHITE) attr = randint(0, Screen.A_UNDERLINE) screen.print_at(chr(char), x, y, fg, attr, bg) char2, fg2, attr2, bg2 = screen.get_from(x, y) self.assertEqual(char, char2) self.assertEqual(fg, fg2) self.assertEqual(attr, attr2) self.assertEqual(bg, bg2) Screen.wrapper( check_screen_and_canvas, height=15, arguments=[internal_checks])
def test_windows_input(self): """ Check that extended keyboard input works on Windows. """ def internal_checks(screen): if sys.platform != "win32": self.skipTest("Only valid for Windows platforms") # Test no mapping by default self._inject_key(screen, Screen.KEY_NUMPAD0) self.assertIsNone(screen.get_event()) # Test switching on mapping picks up keys screen.map_all_keys(True) self._inject_key(screen, Screen.KEY_NUMPAD0) ch = screen.get_key() self.assertEqual(ch, Screen.KEY_NUMPAD0) self.assertIsNone(screen.get_key()) Screen.wrapper(internal_checks, height=15)
def test_paint(self): """ Check that paint with colour map works. """ def internal_checks(screen): # Put a simple colour map to screen. screen.paint( "Text", 0, 0, colour_map=((1, 0, 4), (2, 0, 3), (3, 0, 2), (4, 0, 1))) # Check it is rendered as expected. char, fg, _, bg = screen.get_from(0, 0) self.assertEqual(fg, 1) self.assertEqual(bg, 4) char, fg, _, bg = screen.get_from(3, 0) self.assertEqual(fg, 4) self.assertEqual(bg, 1) Screen.wrapper( check_screen_and_canvas, height=15, arguments=[internal_checks])
def test_scroll_redraw(self): """ Check that scrolling works with screen locations. """ def internal_checks(screen): # New screen is not scrolled. self.assertEqual(screen.start_line, 0) # Scroll and check it has not moved screen.print_at("Hello", 0, 1) for i, c in enumerate("Hello"): self.assertEqual(screen.get_from(i, 1)[0], ord(c)) screen.scroll() for i, c in enumerate("Hello"): self.assertEqual(screen.get_from(i, 1)[0], ord(c)) screen.refresh() for i, c in enumerate("Hello"): self.assertEqual(screen.get_from(i, 1)[0], ord(c)) Screen.wrapper(internal_checks)
def test_wrapper(self): """ Check that you can create a blank Screen. """ def internal_checks(screen): # Check screen basically exists self.assertIsNotNone(screen) self.assertGreater(screen.width, 0) self.assertGreater(screen.height, 0) self.assertGreater(screen.colours, 0) # Check that the Screen is cleared ready for use. for x in range(screen.width): for y in range(screen.height): char, fg, attr, bg = screen.get_from(x, y) self.assertEqual(char, ord(" ")) self.assertEqual(fg, Screen.COLOUR_WHITE) self.assertEqual(attr, 0) self.assertEqual(bg, Screen.COLOUR_BLACK) Screen.wrapper(internal_checks)
def demo(screen: Screen, scene: Scene, app_context: AppContext): bbsmenu_view = BbsmenuView(screen, BbsmenuVM(app_context)) board_view = BoardView(screen, BoardVM(app_context)) thread_view = ThreadView(screen, ThreadVM(app_context)) image_view = ImageView(screen, ImageVM(app_context)) ng_view = NGView(screen, NGVM(app_context)) favorites_view = FavoritesView(screen, FavoritesVM(app_context)) keylog = KeyLogger(screen) # noqa: F841 app_context.set_bbsmenu() scenes = [ # Scene([keylog], -1, name="Keylog"), Scene([bbsmenu_view], -1, name="Bbsmenu"), Scene([board_view], -1, name="Board"), Scene([thread_view], -1, name="Thread"), Scene([image_view], -1, name="Image"), Scene([ng_view], -1, name="NG"), Scene([favorites_view], -1, name="Favorites") ] screen.play(scenes, stop_on_resize=True, start_scene=scene, unhandled_input=global_shortcuts, allow_int=True)
def on_show_audio(cmd: pcmd.Command, args: List[str], scale: float, char: str) -> None: """Callback for `show audio` - shows the detected input""" if not ch.is_alive(): utils.printerr('The audio channel isn\'t running at the moment ... ') return w, h = shutil.get_terminal_size() bw, bh = w//4*3, h def disp_audio(screen: Screen) -> None: while True: screen.clear() b = ch.buff sw = len(b)//bw b = np.asarray([np.average(b[i:i+sw]) for i in range(0, len(b), sw)]) for i, v in enumerate(b): screen.move((w-bw)//2+i, int(h//2-bh*v*scale)) screen.draw((w-bw)//2+i, h//2, char=char, colour=1 if np.max(b) > .2 else 7) e = screen.get_key() if e in (ord('Q'), ord('q')): break screen.refresh() time.sleep(.01) Screen.wrapper(disp_audio)
def process_event(self, event): if isinstance(event, KeyboardEvent): if self.__scene_keybinds: for keybind, scene in self.__scene_keybinds.items(): if event.key_code in [ ord(keybind.lower()), ord(keybind.upper()) ]: raise NextScene(scene) if event.key_code in [ord('q'), ord('Q'), Screen.ctrl("c")]: raise StopApplication("User quit") return super(PriceFrame, self).process_event(event)
def main(filename): global loop try: if os.stat(filename).st_size == 0: raise EOFError except FileNotFoundError: print("{}: no such file or directory".format(filename)) exit(errno.ENOENT) except EOFError: print("{}: file is empty".format(filename)) exit(errno.ENODATA) with open(filename, 'r+b') as f: def main_loop(screen): UI(screen, f) loop = main_loop try: Screen.wrapper(loop) except KeyboardInterrupt: exit(0)
def test_catch_exceptions(self): """ Check that we can catch exceptions (e.g. for ctrl-c). """ def internal_checks(screen): # Not much we can do here as refresh will draw to a screen we can't # query. Check that we don't hit an Exception on refresh(). if sys.platform == "win32": # Strictly speaking, this doesn't test catching ctrl-c as # it isn't possible to trigger the control handler (even if # we don't catch interrupts). Still a good basic check for # input, though. event = win32console.PyINPUT_RECORDType(win32console.KEY_EVENT) event.Char = u"\03" event.KeyDown = 1 event.RepeatCount = 1 event.ControlKeyState = win32con.LEFT_CTRL_PRESSED event.VirtualKeyCode = 67 event.VirtualScanCode = 46 screen._stdin.WriteConsoleInput([event]) event.KeyDown = 0 screen._stdin.WriteConsoleInput([event]) ch = screen.get_event() self.assertEqual(ch.key_code, 3) self.assertIsNone(screen.get_event()) else: # Check Ctrl-c (and no other input) os.kill(os.getpid(), signal.SIGINT) ch = screen.get_event() self.assertEqual(ch.key_code, 3) self.assertIsNone(screen.get_event()) # Check Ctrl-z (and no other input) os.kill(os.getpid(), signal.SIGTSTP) ch = screen.get_event() self.assertEqual(ch.key_code, 26) self.assertIsNone(screen.get_event()) Screen.wrapper(internal_checks, height=15, catch_interrupt=True)
def process_event(self, event): """User input for the main map view.""" if isinstance(event, KeyboardEvent): if event.key_code in [Screen.ctrl("m"), Screen.ctrl("j")]: self._scene.add_effect( EnterLocation( self._screen, self._longitude, self._latitude, self._on_new_location)) elif event.key_code in [ord('q'), ord('Q'), Screen.ctrl("c")]: raise StopApplication("User quit") elif event.key_code in [ord('t'), ord('T')]: self._satellite = not self._satellite if self._satellite: self._size = _START_SIZE elif event.key_code == ord("?"): self._scene.add_effect(PopUpDialog(self._screen, _HELP, ["OK"])) elif event.key_code == ord("+") and self._zoom <= 20: if self._desired_zoom < 20: self._desired_zoom += 1 elif event.key_code == ord("-") and self._zoom >= 0: if self._desired_zoom > 0: self._desired_zoom -= 1 elif event.key_code == ord("0"): self._desired_zoom = 0 elif event.key_code == ord("9"): self._desired_zoom = 20 elif event.key_code == Screen.KEY_LEFT: self._desired_longitude -= 360 / 2 ** self._zoom / self._size * 10 elif event.key_code == Screen.KEY_RIGHT: self._desired_longitude += 360 / 2 ** self._zoom / self._size * 10 elif event.key_code == Screen.KEY_UP: self._desired_latitude = self._inc_lat(self._desired_latitude, -self._size / 10) elif event.key_code == Screen.KEY_DOWN: self._desired_latitude = self._inc_lat(self._desired_latitude, self._size / 10) else: return # Trigger a reload of the tiles and redraw map self._updated.set() self._screen.force_update()
def main(): parser = ArgumentParser() parser.add_argument("root_dir", default=Path.cwd(), nargs="?", type=Path, help="The directory to analyze") args = parser.parse_args() dirstat = None def tdirstat(screen: Screen, old_scene): nonlocal dirstat on_stats_change = lambda *args, **kwargs: screen.force_update() if dirstat is None: dirstat = DirectoryStat( path=str(args.root_dir.absolute()), on_stats_change=on_stats_change, mounts_to_ignore=get_mounts()) # Make sure this gets set each time the screen resizes dirstat._on_stats_change = on_stats_change screen.play( [Scene([TDirStatView(screen, dirstat)], duration=-1)], stop_on_resize=True, start_scene=old_scene) last_scene = None while True: try: Screen.wrapper( func=tdirstat, catch_interrupt=True, arguments=[last_scene]) sys.exit(0) except ResizeScreenError as e: last_scene = e.scene except ValueError as e: # Screen will be blank when it's too small. It's better than the # application crashing, I suppose pass
def test_mouse_input(self): """ Check that mouse input works. """ def internal_checks(screen): # Inject a mouse move and check it is picked up self._inject_mouse(screen, 1, 2, 0) ev = screen.get_event() self.assertEqual(ev.x, 1) self.assertEqual(ev.y, 2) self.assertEqual(ev.buttons, 0) self.assertIsNone(screen.get_event()) # Check left click self._inject_mouse(screen, 2, 3, MouseEvent.LEFT_CLICK) ev = screen.get_event() self.assertEqual(ev.x, 2) self.assertEqual(ev.y, 3) self.assertEqual(ev.buttons, MouseEvent.LEFT_CLICK) self.assertIsNone(screen.get_event()) # Check right click self._inject_mouse(screen, 0, 0, MouseEvent.RIGHT_CLICK) ev = screen.get_event() self.assertEqual(ev.x, 0) self.assertEqual(ev.y, 0) self.assertEqual(ev.buttons, MouseEvent.RIGHT_CLICK) self.assertIsNone(screen.get_event()) # Check double click self._inject_mouse(screen, 0, 0, MouseEvent.DOUBLE_CLICK) ev = screen.get_event() self.assertEqual(ev.x, 0) self.assertEqual(ev.y, 0) self.assertEqual(ev.buttons, MouseEvent.DOUBLE_CLICK) self.assertIsNone(screen.get_event()) Screen.wrapper(internal_checks, height=15)
def main(): data = DataModel() data.load_config() last_scene = None while True: try: Screen.wrapper(screen, arguments=[last_scene, data]) break except ResizeScreenError as e: last_scene = e.scene except StopApplication: break modules = [data.config['master_channel']] modules.extend(data.config['slave_channels']) if 'middlewares' in data.config: modules.extend(data.config['middlewares']) for i in modules: mid, cid = data.split_cid(i) if callable(data.modules[mid].wizard): print(_("Press ENTER/RETURN to start setting up {0}.").format(i)) input() data.modules[mid].wizard(data.profile, cid)
def process_event(self, event): # Do the key handling for this Frame. if isinstance(event, KeyboardEvent): if event.key_code in [ord('q'), ord('Q'), Screen.ctrl("c")]: raise StopApplication("User quit") if event.key_code in [ord('a'), ord('A')]: self._attach() if event.key_code in [ord('d'), ord('D')]: self._delete() if event.key_code in [ord('n'), ord('N')]: self._new() # Now pass on to lower levels for normal handling of the event. return super(ListView, self).process_event(event)
def __init__(self): self.screen = Screen.open() self.scenes = [] self.akt_sender_str = "Deutschlandradio" self.akt_sender_nr = 0 self.volume = 25 self.number_of_stations = 0 # Prepare frame for the presets self.preset_frame = Frame(self.screen, 7, 29, can_scroll=False, title="Tastenbelegung", x=0, y=10, reduce_cpu=True) self.pr_layout = Layout([10, 90], fill_frame=True) self.preset_frame.add_layout(self.pr_layout) # Prepare frame for the sender list self.sender_frame = Frame(self.screen, 17, 50, can_scroll=False, title="Senderliste", x=30, y=0, reduce_cpu=True) self.sender_layout0 = Layout([10, 80, 10], fill_frame=True) self.sender_frame.add_layout(self.sender_layout0) # Load the json config-file self.cfg = self.load_config() # Prepare the layouts, add spaces etc self.format_sl_layout(self.sender_layout0) # Nicht mehr nötig nach aktuellem Stand # format_pr_layout(pr_layout) # Create the sender-labels and fill them initially. Return them for # later changing self.sender_labels = self.gen_and_add_sender_labels( self.sender_layout0, self.parse_sender()) self.preset_labels = self.gen_and_add_preset_labels( self.pr_layout, self.parse_presets()) self.preset_frame.fix() self.sender_frame.fix()
def process_event(self, event): # Do the key handling for this Frame. if isinstance(event, KeyboardEvent): if event.key_code in [ord('q'), ord('Q'), Screen.ctrl('c')]: raise StopApplication("User quit") elif event.key_code in [ord('a'), ord('A')]: self._add() elif event.key_code in [ord('e'), ord('E')]: self._edit() elif event.key_code in [ord('d'), ord('D')]: self._delete() # Now pass on to lower levels for normal handling of the event. return super().process_event(event)
def test_paint(self): """ Check that paint with colour map works. """ def internal_checks(screen): # Put a simple colour map to screen. screen.paint("Text", 0, 0, colour_map=((1, 0, 4), (2, 0, 3), (3, 0, 2), (4, 0, 1))) # Check it is rendered as expected. char, fg, _, bg = screen.get_from(0, 0) self.assertEqual(fg, 1) self.assertEqual(bg, 4) char, fg, _, bg = screen.get_from(3, 0) self.assertEqual(fg, 4) self.assertEqual(bg, 1) Screen.wrapper(check_screen_and_canvas, height=15, arguments=[internal_checks])
def test_forced_update(self): """ Check that forcing an update works as expected. """ def internal_checks(screen): # First check that Effects are always drawn at Scene start test_effect = MockEffect(count=101, stop_frame=101, frame_rate=100) screen.set_scenes([Scene([test_effect], 0)]) screen.draw_next_frame() self.assertTrue(test_effect.update_called) # Now check that the Screen honours the long frame rate... test_effect.update_called = False for _ in range(90): screen.draw_next_frame() self.assertFalse(test_effect.update_called) # Now check that the forced update works as expected. screen.force_update() screen.draw_next_frame() self.assertTrue(test_effect.update_called) Screen.wrapper(internal_checks, height=15)
def test_scroll_redraw(self): """ Check that scrolling works with screen locations. """ def internal_checks(screen): # New screen is not scrolled. self.assertEqual(screen.start_line, 0) # Scroll and check it has not moved screen.print_at("Hello", 0, 1) screen.scroll() screen.refresh() for i, c in enumerate("Hello"): self.assertEqual(screen.get_from(i, 1)[0], ord(c)) # Scroll and check drawing off-screen works. screen.print_at("World", 0, 0) screen.scroll() screen.refresh() for i, c in enumerate("World"): self.assertEqual(screen.get_from(i, 0)[0], ord(c)) Screen.wrapper(internal_checks)
def screen_logic(self, screen: Screen): from datetime import datetime, timedelta t0 = datetime.now() try: for t in range(self.seconds + 1): # For best accuracy, calculate time till next "frame" based on actual time wait_for_it = t0 + timedelta(seconds=t) seconds_to_wait = (wait_for_it - datetime.now()).total_seconds() if seconds_to_wait > 0: time.sleep(seconds_to_wait) elif seconds_to_wait < -0.1: # Skip a frame if we're running late continue effects = [Print(screen, FigletText(str(self.seconds - t)), 0)] scene = Scene(effects, 40) screen.set_scenes([scene]) # Strange, it seems a few frames need to be skipped. for _ in range(10): screen.draw_next_frame(repeat=False) except StopApplication: return
def test_colour_image_file(self): """ Check that the ColourImageFile renderer works. """ # Skip for non-Windows if the terminal definition is incomplete. # This typically means we're running inside a non-standard termina;. # For example, thi happens when embedded in PyCharm. if sys.platform != "win32": curses.initscr() if curses.tigetstr("ri") is None: self.skipTest("No valid terminal definition") def internal_checks(screen): renderer = ColourImageFile(screen, os.path.join(os.path.dirname(__file__), "globe.gif"), height=10) # Check renderer got all images from the file. count = 0 for image in renderer.images: count += 1 self.assertIsNotNone(image) self.assertIsNotNone(len(image) <= renderer.max_height) self.assertEqual(count, 11) # Check an image looks plausible image = next(renderer.images) self.assertEqual(image, [ '', ' ##### ', ' ############# ', ' ################# ', ' ###################', '####################', '####################', ' ###################', ' ################## ', ' ############### ', ' ########### ' ]) Screen.wrapper(internal_checks, height=15)
def test_rainbow(self): """ Check that the Rainbow renderer works. """ # Skip for non-Windows if the terminal definition is incomplete. # This typically means we're running inside a non-standard terminal. # For example, this happens when embedded in PyCharm. if sys.platform != "win32" and curses.tigetstr("ri") is None: self.skipTest("No valid terminal definition") def internal_checks(screen): # Create a base renderer plain_text = (".-------.\n" + "| hello |\n" + "`-------`\n") renderer = SpeechBubble("hello") self.assertEqual(str(renderer), plain_text) # Pretend that we always have an 8 colour palette for the test. screen.colours = 8 # Check that the Rainbow renderer doesn't change this. rainbow = Rainbow(screen, renderer) self.assertEqual(str(rainbow), plain_text) # Check rainbow colour scheme. self.assertEqual( rainbow.rendered_text[1], [ [(1, 1, None), (1, 1, None), (3, 1, None), (3, 1, None), (2, 1, None), (2, 1, None), (6, 1, None), (6, 1, None), (4, 1, None)], [(1, 1, None), (3, 1, None), (3, 1, None), (2, 1, None), (2, 1, None), (6, 1, None), (6, 1, None), (4, 1, None), (4, 1, None)], [(3, 1, None), (3, 1, None), (2, 1, None), (2, 1, None), (6, 1, None), (6, 1, None), (4, 1, None), (4, 1, None), (5, 1, None)], []]) Screen.wrapper(internal_checks, height=15)
def test_key_input(self): """ Check that keyboard input works. """ def internal_checks(screen): # Inject a letter and check it is picked up self._inject_key(screen, ord("a")) ch = screen.get_event() self.assertEqual(ch.key_code, ord("a")) self.assertIsNone(screen.get_event()) # Inject a letter and check it is picked up self._inject_key(screen, Screen.KEY_BACK_TAB) ch = screen.get_event() self.assertEqual(ch.key_code, Screen.KEY_BACK_TAB) self.assertIsNone(screen.get_event()) # Check that get_key also works. self._inject_key(screen, ord("b")) ch = screen.get_key() self.assertEqual(ch, ord("b")) self.assertIsNone(screen.get_key()) # Check that unicode input also works self._inject_key(screen, ord(u"├")) ch = screen.get_event() self.assertEqual(ch.key_code, ord(u"├")) self.assertIsNone(screen.get_event()) # Check that unicode input colliding with curses KEY_MAP also works (code: 263) self._inject_key(screen, ord(u"ć")) ch = screen.get_event() self.assertEqual(ch.key_code, ord(u"ć")) self.assertIsNone(screen.get_event()) Screen.wrapper(internal_checks, height=15, unicode_aware=True)
def main(years): board = create_board() fill_up_board(board) without_candles = copy.deepcopy(board) candles = set_candles(years, board) input_queue = Queue() input_thread = threading.Thread(target=add_input, args=(input_queue, )) input_thread.daemon = True input_thread.start() def print_board_ascii(screen): while True: if not input_queue.empty(): char = input_queue.get() if char == "f": put_out_a_candle(candles, board, without_candles) move_candles(candles, board) board_str = get_board_str(board) for i in range(len(board_str)): screen.print_at(board_str[i], 0, i) screen.refresh() Screen.wrapper(print_board_ascii)
def process_event(self, event: Optional[Event]) -> Optional[Event]: """Process either a keyboard or a mouse event. If the user pressed enter/space or double clicked on the widget, a popup will be shown to allow the user to pick a date. Args: event: the event to be handled. Returns: The handled event, in case somebody else needs it. """ if event is not None: if isinstance(event, KeyboardEvent): if event.key_code in [Screen.ctrl("M"), Screen.ctrl("J"), ord(" ")]: event = None elif isinstance(event, MouseEvent): if event.buttons != 0: if self.is_mouse_over(event, include_label=False): event = None if event is None: self._child = CustomDatePickerPopup(self, year_range=self._year_range) self.frame.scene.add_effect(self._child) return event
def visualize(self): """ Wrapper for self._visualize. Sets up the screen environment from a asciimatics """ screen = Screen.open() restore = True try: try: self._visualize(screen) except ResizeScreenError: restore = False raise finally: screen.close(restore)
def process_event(self, event: Any) -> Any: result = super(TopView, self).process_event(event) if isinstance(event, KeyboardEvent): # quit if event.key_code in [ord("q"), Screen.ctrl("c")]: raise StopApplication("") # toggle sort for current widget if event.key_code in [ord("r")]: if self.focussed_widget.name in self.onefuzz_reversed: self.onefuzz_reversed[ self.focussed_widget.name] = not self.onefuzz_reversed[ self.focussed_widget.name] return result
def demo(wout, win): while True: screen = Screen.from_windows(wout, win) effects = [ Print(screen, Rainbow(screen, FigletText("256 colours")), y=screen.height//2 - 8), Print(screen, Rainbow(screen, FigletText("for xterm users")), y=screen.height//2 + 3), Clock(screen, screen.width//2, screen.height//2, screen.height//2), ] try: screen.play([Scene(effects, -1)], stop_on_resize=True) return except ResizeScreenError: pass
def test_key_input(self): """ Check that keyboard input works. """ def internal_checks(screen): # Inject a letter and check it is picked up self._inject_key(screen, ord("a")) ch = screen.get_event() self.assertEqual(ch.key_code, ord("a")) self.assertIsNone(screen.get_event()) # Inject a letter and check it is picked up self._inject_key(screen, Screen.KEY_BACK_TAB) ch = screen.get_event() self.assertEqual(ch.key_code, Screen.KEY_BACK_TAB) self.assertIsNone(screen.get_event()) # Check that get_key also works. self._inject_key(screen, ord("b")) ch = screen.get_key() self.assertEqual(ch, ord("b")) self.assertIsNone(screen.get_key()) Screen.wrapper(internal_checks, height=15)
def _new_screen(self, start_scene): screen = Screen.open() screen.clear() self._msgs_view = MsgsView(screen, self._msgs_model, self._ident_model, self._stngs_model, self._status_model) self._ident_view = IdentView(screen, self._ident_model) self._stngs_view = RadioStngsView(screen, self._stngs_model) self._status_view = StatusView(screen, self._stngs_model) scenes = [ Scene([self._msgs_view], -1, name="Messages"), Scene([self._ident_view], -1, name="Identity"), Scene([self._stngs_view], -1, name="Settings"), Scene([self._status_view], -1, name="Status"), ] screen.set_scenes(scenes, start_scene=start_scene) self._screen = screen
def preinit(): screen = Screen.open() test1.intro(screen) junk = Frame(screen, screen.height * 2 // 3, screen.width * 2 // 3, hover_focus=True, has_border=True, title="Game Settings", reduce_cpu=False) oldpalette = copy.deepcopy(junk.palette) Scenes = [] debug = [True] game = [] data = MainMenu(game,screen,debug,oldpalette)
def main_loop(controller): screen = None while True: if screen is None or screen.has_resized(): if screen is not None: screen.close(False) screen = Screen.open() controller.build_ui(screen, None) # effects = create_effect(screen) # screen.set_scenes([Scene(effects, 500)]) try: screen.draw_next_frame() except StopApplication: screen.close(True) break gevent.sleep(0.05)
def process_event(self, event): # Do the key handling for this Frame. if isinstance(event, KeyboardEvent): if event.key_code in [ord('q'), ord('Q'), Screen.ctrl("c")]: raise StopApplication("User quit") elif event.key_code in [ord("r"), ord("R")]: self._reverse = not self._reverse elif event.key_code == ord("<"): self._sort = max(0, self._sort - 1) elif event.key_code == ord(">"): self._sort = min(7, self._sort + 1) # Force a refresh for improved responsiveness self._last_frame = 0 # Now pass on to lower levels for normal handling of the event. return super(DemoFrame, self).process_event(event)