def test_after_idle(): stuff = [] for i in range(5): teek.after_idle(stuff.append, [i]) # test positional args teek.after_idle(teek.quit) teek.run() assert stuff == list(range(5))
def test_error_in_thread_call(deinit_threads, handy_callback): teek.init_threads() @handy_callback def thread_target(): with pytest.raises(teek.TclError) as error: teek.tcl_eval(None, "expr {1/0}") exc = error.value assert isinstance(exc, teek.TclError) assert exc.__traceback__ is not None # error_message is the traceback that python would display if this # error wasn't caught error_message = ''.join( traceback.format_exception(type(exc), exc, exc.__traceback__)) assert error_message.startswith("Traceback (most recent call last):\n") regex = (r'\n' r' File ".*test_threads\.py", line \d+, in thread_target\n' r' teek\.tcl_eval\(None, "expr {1/0}"\)\n') assert re.search(regex, error_message) is not None thread = threading.Thread(target=thread_target) thread.start() teek.after(100, teek.quit) teek.run() thread.join() assert thread_target.ran_once()
def test_after(): start = time.time() timeout = teek.after(200, teek.quit) assert repr(timeout).startswith("<pending 'quit' timeout") teek.run() end = time.time() # the upper bound used to be 0.21, but it failed once # then i tried 0.22 and after a while that failed too assert 0.20 < (end - start) < 0.25 assert repr(timeout).startswith("<successfully completed 'quit' timeout")
def test_weird_error(capfd): # make sure that previous tests don't mess up teek.after_idle(teek.quit) teek.run() # ignore anything that ended up in the stderr because previous tests # TODO: why is stderr SOMETIMES non-empty?? capfd.readouterr() teek.create_command(print) # the command is intentionally not deleted teek.quit() teek.update() assert capfd.readouterr() == ('', '')
def deinit_threads(): """Make sure that init_threads() has not been called when test completes. If you have a test like this... def test_tootie(): teek.init_threads() ...the test will cause problems for any other tests that also call init_threads(), because it can't be called twice. Using this fixture in test_tootie() would fix that problem. """ yield teek.after_idle(teek.quit) teek.run()
def func(monkeypatch, handy_callback): @handy_callback def fake_run(): pass with monkeypatch.context() as monkey: monkey.setattr(teek, 'run', fake_run) exec(code, {'__file__': os.path.join(EXAMPLES_DIR, filename)}) assert fake_run.ran_once() # make sure that nothing breaks if the real .run() is called teek.update() teek.after_idle(teek.quit) teek.run()
def test_errors(capsys): def thingy(**kwargs): # test kwargs assert kwargs == {'lol': 'wut'} raise RuntimeError("\N{pile of poo}") timeout = teek.after_idle(thingy, kwargs={'lol': 'wut'}) assert repr(timeout).startswith("<pending 'thingy' timeout") teek.after_idle(teek.quit) teek.run() assert repr(timeout).startswith("<failed 'thingy' timeout") output, errors = capsys.readouterr() assert not output assert "timeout = teek.after_idle(thingy, kwargs={'lol': 'wut'})" in errors assert "\N{pile of poo}" in errors
def test_progressbar_bouncing(): progress_bar = teek.Progressbar(teek.Window(), mode='indeterminate') assert progress_bar.config['value'] == 0 progress_bar.start() def done_callback(): try: # sometimes the value gets set to 2.0 on this vm, so this works assert progress_bar.config['value'] > 1 progress_bar.stop() # prevents funny tk errors finally: # if this doesn't run, the test freezes teek.quit() teek.after(500, done_callback) teek.run()
def test_make_thread_safe(handy_callback, deinit_threads): @teek.make_thread_safe @handy_callback def thread_target(): assert threading.current_thread() is threading.main_thread() teek.init_threads() thread = threading.Thread(target=thread_target) thread.start() # make_thread_safe needs teek.run to work teek.after(500, teek.quit) teek.run() assert not thread.is_alive() assert thread_target.ran_once()
def test_init_threads_errors(deinit_threads, handy_callback): @handy_callback def thread1_target(): # the Tcl interpreter isn't started yet, so this runs an error that is # not covered by the code below with pytest.raises(RuntimeError) as error: teek.tcl_eval(None, '') assert str(error.value) == "init_threads() wasn't called" thread1 = threading.Thread(target=thread1_target) thread1.start() thread1.join() assert thread1_target.ran_once() # this starts the Tcl interpreter teek.tcl_eval(None, '') @handy_callback def thread2_target(): with pytest.raises(RuntimeError) as error: teek.init_threads() assert (str( error.value) == "init_threads() must be called from main thread") for cb in [ functools.partial(teek.tcl_call, None, 'puts', 'hello'), functools.partial(teek.tcl_eval, None, 'puts hello') ]: with pytest.raises(RuntimeError) as error: cb() assert str(error.value) == "init_threads() wasn't called" thread2 = threading.Thread(target=thread2_target) thread2.start() thread2.join() assert thread2_target.ran_once() teek.init_threads() with pytest.raises(RuntimeError) as error: teek.init_threads() assert str(error.value) == "init_threads() was called twice" teek.after_idle(teek.quit) teek.run()
def test_cancel(): timeout = teek.after(1000, print, args=["it didn't work"]) timeout.cancel() assert repr(timeout).startswith("<cancelled 'print' timeout") with pytest.raises(RuntimeError) as error: timeout.cancel() assert str(error.value) == "cannot cancel a cancelled timeout" def try_to_cancel_the_completed_timeout(): with pytest.raises(RuntimeError) as error: timeout.cancel() assert str(error.value) == ("cannot cancel a successfully " + "completed timeout") timeout = teek.after_idle(lambda: None) teek.after(50, try_to_cancel_the_completed_timeout) teek.after(100, teek.quit) teek.run()
def __init__(self): self._bus = EventBus() self._queue = DataQueue() self.preset = Preset("something here", self._bus, self._queue) self.controller_mouse = Mouse(self._bus, self._queue) self.controller_keyboard = Keyboard(self._bus, self._queue) # spin up threads for Teek teek.init_threads() click_listener = mouse.Listener( on_click=self.controller_mouse.on_click) window = teek.Window("Path of Exile Forge") window.geometry(1280, 720) POEForge(window, self._bus, self._queue) window.on_delete_window.connect(teek.quit) teek.run()
def test_basic_stuff(deinit_threads, handy_callback): teek.init_threads() text = teek.Text(teek.Window()) def thread_target(): for i in (1, 2, 3): text.insert(text.end, 'hello %d\n' % i) thread = threading.Thread(target=thread_target) thread.start() @handy_callback def done_callback(): assert text.get(text.start, text.end) == 'hello 1\nhello 2\nhello 3\n' teek.quit() # i experimented with different values: 500 was enough and 450 wasn't, so # this should be plenty teek.after(1000, done_callback) teek.run() thread.join() assert done_callback.ran_once()
startbutton = teek.Button(self, "Start", command=self.start) startbutton.pack() cancelbutton = teek.Button(self, "Cancel", command=self.cancel) cancelbutton.pack() def start(self): if self.timeout is None: self.timeout = teek.after(3000, self.callback) print("running callback after 3 seconds") else: print("already started") def cancel(self): if self.timeout is None: print("already cancelled") else: self.timeout.cancel() self.timeout = None print("callback won't be ran") def callback(self): print("*** running the callback ***") self.timeout = None window = teek.Window() TimeoutDemo(window).pack() window.on_delete_window.connect(teek.quit) teek.run()
def thread_target(): with pytest.raises(RuntimeError) as error: teek.run() assert str(error.value) == "run() must be called from main thread"