def test_bind(handy_callback): widget = teek.Window() assert not widget.bindings.keys() @handy_callback def tcl_call_bound_callback(): pass @handy_callback def teek_bound_callback(): pass command = teek.create_command(tcl_call_bound_callback) teek.tcl_call(None, 'bind', widget, '<<Asd>>', command) assert widget.bindings.keys() == {'<<Asd>>'} widget.bind('<<Asd>>', teek_bound_callback) teek.update() teek.tcl_call(None, 'event', 'generate', widget, '<<Asd>>') teek.delete_command(command) assert tcl_call_bound_callback.ran_once() # tests binding with + assert teek_bound_callback.ran_once() # some binding strings are equivalent assert widget.bindings['<Button-3>'] is widget.bindings['<Button-3>'] assert widget.bindings['<3>'] is widget.bindings['<Button-3>'] assert repr(widget.bindings) == '<a bindings object, behaves like a dict>'
def test_delete_command(): result = [] command = teek.create_command(result.append, [int]) teek.tcl_call(None, command, '123') assert result == [123] teek.delete_command(command) with pytest.raises(teek.TclError): teek.tcl_call(None, command, '123')
def cancel(self): """Prevent this timeout from running as scheduled. :exc:`RuntimeError` is raised if the timeout has already ran or it has been cancelled. There is example code in :source:`examples/timeout.py`. """ if self._state != 'pending': raise RuntimeError("cannot cancel a %s timeout" % self._state) teek.tcl_call(None, 'after', 'cancel', self._id) self._state = 'cancelled' teek.delete_command(self._tcl_command)
def destroy(self): """Delete this widget and all child widgets. Manual page: :man:`destroy(3tk)` .. note:: Don't override this in a subclass. In some cases, the widget is destroyed without a call to this method. >>> class BrokenFunnyLabel(teek.Label): ... def destroy(self): ... print("destroying") ... super().destroy() ... >>> BrokenFunnyLabel(teek.Window()).pack() >>> teek.quit() >>> # nothing was printed! Use the ``<Destroy>`` event instead: >>> class WorkingFunnyLabel(teek.Label): ... def __init__(self, *args, **kwargs): ... super().__init__(*args, **kwargs) ... self.bind('<Destroy>', self._destroy_callback) ... def _destroy_callback(self): ... print("destroying") ... >>> WorkingFunnyLabel(teek.Window()).pack() >>> teek.quit() destroying """ for name in self._call([str], 'winfo', 'children', self): # allow overriding the destroy() method if the widget was # created by teek if name in _widgets: _widgets[name]._destroy_recurser() else: self._call(None, 'destroy', name) # this must be BEFORE deleting command_list commands because <Destroy> # bindings may need command_list stuff self._call(None, 'destroy', self) # this is here because now the widget is basically useless del _widgets[self.to_tcl()] for command in self.command_list: teek.delete_command(command) self.command_list.clear() # why not
def test_create_command(capsys): def working_func(): # no type checking is done, this turns into a dict below return CustomSequence() command = teek.create_command(working_func) assert teek.tcl_call({'a b c': int}, command) == {'a b c': 123} assert capsys.readouterr() == ('', '') teek.tcl_call(None, command, 'asda') output, errors = capsys.readouterr() assert not output assert errors.endswith( "TypeError: expected 0 arguments, got 1 arguments\n") teek.delete_command(command) def broken_func(arg1): if arg1 == 'lol': print('it works') else: print('it doesnt works :(', arg1) raise RuntimeError("oh noes") command = teek.create_command(broken_func, [str]) assert teek.tcl_call(str, command, 'lol') == '' teek.delete_command(command) output, errors = capsys.readouterr() assert output == 'it works\n' assert 'raise RuntimeError("oh noes")' in errors def create_the_command(): return teek.create_command(broken_func, [str]) command = create_the_command() assert teek.tcl_call(str, command, 'lol') == '' teek.delete_command(command) output, errors = capsys.readouterr() assert output == 'it works\n' assert 'raise RuntimeError("oh noes")' in errors assert 'command = create_the_command()' in errors assert 'return teek.create_command(broken_func, [str])' in errors # test return values def lel(): return (True, 3, ['a', 'b', 'c']) command = teek.create_command(lel) assert (teek.tcl_call((bool, int, [str]), command) == (True, 3, ['a', 'b', 'c'])) teek.delete_command(command) assert capsys.readouterr() == ('', '')
def faker(name, return_value=None): called = [] def command_func(*args): called.append(list(args)) return return_value fake = teek.create_command(command_func, [], extra_args_type=str) teek.tcl_call(None, 'rename', name, name + '_real') try: teek.tcl_call(None, 'rename', fake, name) yield called finally: try: teek.delete_command(name) except teek.TclError: pass teek.tcl_call(None, 'rename', name + '_real', name)
def _run(self): needs_cleanup = True # this is important, thread tests freeze without this special # case for some reason def quit_callback(): nonlocal needs_cleanup needs_cleanup = False teek.before_quit.connect(quit_callback) try: self._callback(*self._args, **self._kwargs) self._state = 'successfully completed' except Exception as e: self._state = 'failed' raise e finally: teek.before_quit.disconnect(quit_callback) if needs_cleanup: teek.delete_command(self._tcl_command)
def test_screen_distances(): assert teek.ScreenDistance(123).pixels == 123 assert teek.ScreenDistance('123').pixels == 123 assert round(teek.ScreenDistance(123).fpixels, 3) == 123.0 assert round(teek.ScreenDistance('123').fpixels, 3) == 123.0 assert teek.ScreenDistance(123) == teek.ScreenDistance('123') assert hash(teek.ScreenDistance(123)) == hash(teek.ScreenDistance('123')) inch = teek.ScreenDistance('1i') centimeter = teek.ScreenDistance('1c') pixel = teek.ScreenDistance(1) assert round(inch.fpixels / centimeter.fpixels, 2) == 2.54 assert repr(inch) == "ScreenDistance('1i')" assert repr(centimeter) == "ScreenDistance('1c')" assert repr(pixel) == "ScreenDistance('1')" assert inch.to_tcl() == '1i' assert centimeter.to_tcl() == '1c' assert pixel.to_tcl() == '1' assert inch != centimeter assert inch > centimeter assert inch != 'asd' assert inch != '1i' with pytest.raises(TypeError): inch < '1i' teek.tcl_eval(None, 'proc returnArg {arg} {return $arg}') try: assert teek.tcl_eval(teek.ScreenDistance, 'returnArg 1i') == inch assert teek.tcl_eval(teek.ScreenDistance, 'returnArg 1c') == centimeter assert teek.tcl_eval(teek.ScreenDistance, 'returnArg 1') == pixel finally: teek.delete_command('returnArg') with pytest.raises(teek.TclError): teek.ScreenDistance('asdf asdf')
def handy_commands(): teek.tcl_eval(None, 'proc returnArg {arg} { return $arg }') teek.tcl_eval(None, 'proc returnEmptyString {} {}') yield teek.delete_command('returnArg') teek.delete_command('returnEmptyString')