diff --git a/noblocking_turtle_shell.py b/noblocking_turtle_shell.py index 011050a..012c927 100644 --- a/noblocking_turtle_shell.py +++ b/noblocking_turtle_shell.py @@ -1,60 +1,76 @@ import cmd -from threading import Thread, Event -from turtle import bye -from queue import Queue, Empty - +import threading +from queue import Queue +from turtle import forward from equipment.turtle_device import TurtleDevice -class TurtleDeviceThread(Thread): +class TurtleDeviceThread(threading.Thread): def __init__(self): super().__init__() self.device = TurtleDevice() - self.queue = Queue() - + + self.queue = Queue[tuple]() + + self.device.open() + self.device.execute("speed", 1) + def run(self): while True: - try: - item = self.queue.get() - except self.queue.Empty: - continue - else: - if (item == 'exit'): - break - self.device.execute(*item) + action, args, kwargs = self.queue.get() + if action == "exit": self.queue.task_done() - + break + self.device.execute(action, *args, **kwargs) + self.queue.task_done() + + def add_task(self, action, *args, **kwargs): + self.queue.put((action, args, kwargs)) + class NoBlockingTurtleShell(cmd.Cmd): - intro = 'Welcome to the turtle shell. Type help or ? to list commands.\n' - prompt = '(turtle) ' + intro = "Welcome to the turtle shell. Type help or ? to list commands.\n" + prompt = "(turtle) " file = None def __init__(self, turtle_thread: TurtleDeviceThread): - super(NoBlockingTurtleShell, self).__init__() + super().__init__() self.turtle_thread = turtle_thread - + + @property + def turtle_device(self): + return self.turtle_thread.device def do_execute(self, arg): - self.turtle_thread.queue.put(parse(arg)) + command_and_args = arg.split() + if len(command_and_args) == 1: + self.turtle_thread.add_task(command) + return + command = command_and_args[0] + args = tuple(int(c) if c.isdecimal() else c for c in command_and_args[1:]) + self.turtle_thread.add_task(command, *args) - def do_exit(self, arg): - self.close() - self.turtle_thread.queue.put("exit") + + def do_forward(self, arg): + 'Move the turtle forward by the specified distance: FORWARD 10' + self.do_execute("forward 100") + def do_right(self, arg): + 'Turn turtle right by given number of degrees: RIGHT 20' + self.do_execute("right 100") + def do_left(self, arg): + 'Turn turtle left by given number of degrees: LEFT 90' + self.do_execute("left 100") + def do_bye(self, arg): + 'Stop recording, close the turtle window, and exit: BYE' print('Thank you for using Turtle') + self.turtle_thread.add_task("exit") return True - - - def close(self): - if self.file: - self.file.close() - self.file = None -def parse(arg): - 'Convert a series of zero or more numbers to an argument tuple' - return tuple(arg.split()) -if __name__ == '__main__': +if __name__ == "__main__": turtle_thread = TurtleDeviceThread() - turtle_thread.start() - NoBlockingTurtleShell(turtle_thread).cmdloop() \ No newline at end of file + turtle_thread.daemon = True + thread_shell = threading.Thread(target=NoBlockingTurtleShell(turtle_thread).cmdloop) + thread_shell.start() + turtle_thread.run() + thread_shell.join() diff --git a/tests/controls/test_device.py b/tests/for_controls/test_device.py similarity index 100% rename from tests/controls/test_device.py rename to tests/for_controls/test_device.py diff --git a/tests/equipment/test_turtle_device.py b/tests/for_equipment/test_turtle_device.py similarity index 100% rename from tests/equipment/test_turtle_device.py rename to tests/for_equipment/test_turtle_device.py diff --git a/turtle_shell.py b/turtle_shell.py index 20464cf..ac22aab 100644 --- a/turtle_shell.py +++ b/turtle_shell.py @@ -10,7 +10,6 @@ class TurtleShell(cmd.Cmd): # ----- basic turtle commands ----- def do_forward(self, arg): 'Move the turtle forward by the specified distance: FORWARD 10' - forward(*parse(arg)) def do_right(self, arg): 'Turn turtle right by given number of degrees: RIGHT 20'