Example #1
0
def test_from_to_tcl():
    image1 = teek.Image(file=SMILEY_PATH)
    teek.tcl_eval(None, 'proc returnArg {arg} {return $arg}')
    image2 = teek.tcl_call(teek.Image, 'returnArg', image1)
    assert image1.to_tcl() == image2.to_tcl()  # no implicit copying
    assert image1 is not image2  # no implicit cache
    assert slow_content_eq_check(image1, image2)
Example #2
0
def test_before_after_quit():
    teek.tcl_eval(None, '')   # make sure that a Tcl interpreter is running

    asd = []
    teek.before_quit.connect(asd.append, args=['one'])
    teek.Menu().bind('<Destroy>', (lambda: asd.append('two')))
    teek.after_quit.connect(asd.append, args=['three'])
    teek.quit()
    assert asd == ['one', 'two', 'three']
Example #3
0
def test_font_magic_new_method():
    font = teek.Font('a_font_with_this_name_does_not_exist')
    assert isinstance(font, teek.Font)
    assert not isinstance(font, teek.NamedFont)

    teek.tcl_eval(None, 'font create test_font_name')
    named_font = teek.Font('test_font_name')
    assert isinstance(named_font, teek.NamedFont)
    named_font.delete()
Example #4
0
def test_from_and_to_tcl():
    description = ["Helvetica", 42, "bold"]
    descriptiony_font = teek.Font(description)
    assert descriptiony_font.to_tcl() is description
    assert teek.Font.from_tcl(description) == descriptiony_font

    teek.tcl_eval(None, 'font create test_font_name')
    named_font = teek.NamedFont.from_tcl('test_font_name')
    assert isinstance(named_font, teek.NamedFont)
    assert named_font.to_tcl() == 'test_font_name'
    named_font.delete()
Example #5
0
def test_from_and_to_tcl():
    description = [get_test_family(), 42, 'bold']
    descriptiony_font = teek.Font(description)
    assert descriptiony_font.to_tcl() == to_tcl(description)
    assert teek.Font.from_tcl(description) == descriptiony_font

    teek.tcl_eval(None, 'font create test_font_name')
    named_font = teek.NamedFont.from_tcl('test_font_name')
    assert isinstance(named_font, teek.NamedFont)
    assert named_font.to_tcl() == 'test_font_name'
    named_font.delete()
Example #6
0
def test_spinbox():
    asd = []
    spinbox = teek.Spinbox(teek.Window(),
                           from_=0,
                           to=10,
                           command=(lambda: asd.append('boo')))
    assert asd == []
    teek.tcl_eval(
        None, '''
    set command [%s cget -command]
    $command
    $command
    ''' % spinbox.to_tcl())
    assert asd == ['boo', 'boo']
Example #7
0
def test_run_called_from_wrong_thread(handy_callback):
    # this starts the Tcl interpreter, we get different errors without this
    teek.tcl_eval(None, '')

    @handy_callback
    def thread_target():
        with pytest.raises(RuntimeError) as error:
            teek.run()
        assert str(error.value) == "run() must be called from main thread"

    thread = threading.Thread(target=thread_target)
    thread.start()
    thread.join()
    assert thread_target.ran_once()
Example #8
0
    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
Example #9
0
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()
Example #10
0
def test_empty_tuple_bug():
    # after half a second, press escape in the widget of the dialog that
    # happens to be focused
    teek.after(500, lambda: teek.tcl_eval(
        None, "event generate [focus] <Escape>"))

    # do the dialog, tkinter should return an empty tuple which should be
    # converted to an empty string
    result = teek.tcl_call(str, 'tk_getSaveFile')     # this threw an error
    assert result == ''
Example #11
0
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')
Example #12
0
def test_scrollbar(fake_command, handy_callback):
    scrollbar = teek.Scrollbar(teek.Window())
    assert scrollbar.get() == (0.0, 1.0)

    # testing the set method isn't as easy as you might think because get()
    # doesn't return the newly set arguments after calling set()
    with fake_command(scrollbar.to_tcl()) as called:
        scrollbar.set(1.2, 3.4)
        assert called == [['set', '1.2', '3.4']]

    # this tests the code that runs when the user scrolls the scrollbar
    log = []
    scrollbar.config['command'].connect(lambda *args: log.append(args))

    teek.tcl_eval(
        None, '''
    set command [%s cget -command]
    $command moveto 1.2
    $command scroll 1 units
    $command scroll 2 pages
    ''' % scrollbar.to_tcl())
    assert log == [('moveto', 1.2), ('scroll', 1, 'units'),
                   ('scroll', 2, 'pages')]
Example #13
0
def test_eval_and_call(handy_commands, capfd):
    assert teek.tcl_eval(None, 'if {1 == 2} {puts omg}') is None
    assert teek.tcl_eval(str, 'list a b c') == 'a b c'
    assert teek.tcl_eval(int, 'expr 22 / 7') == 3
    assert teek.tcl_eval(int, 'returnEmptyString') is None
    assert round(teek.tcl_eval(float, 'expr 22 / 7.0'), 2) == 3.14
    assert teek.tcl_eval([int], 'list 1 2 3') == [1, 2, 3]
    assert teek.tcl_eval([str], 'list { a} {b } { c }') == [' a', 'b ', ' c ']
    assert (teek.tcl_eval((str, int, str, int), 'list a 1 b 2') ==
            ('a', 1, 'b', 2))
    assert teek.tcl_eval([int], 'list 0b11111111 0o377 0xff') == [255] * 3
    assert teek.tcl_eval(
        {'a': int, 'c': bool}, 'dict create a 1 b 2') == {'a': 1, 'b': '2'}

    with pytest.raises(ValueError):
        teek.tcl_eval(int, 'returnArg lel')
    with pytest.raises(ValueError):
        teek.tcl_eval((str, str), 'list a b c')
    with pytest.raises(ValueError):
        teek.tcl_eval([int], 'list 1 2 3 yay')

    bools = ['true false', 'tru fal', 'yes no', 'y n', 'on off', '1 0']
    for yes, no in map(str.split, bools):
        assert teek.tcl_call(bool, 'returnArg', yes.upper()) is True
        assert teek.tcl_call(bool, 'returnArg', no.upper()) is False
        assert teek.tcl_call(bool, 'returnArg', yes.lower()) is True
        assert teek.tcl_call(bool, 'returnArg', no.lower()) is False
    assert teek.tcl_eval(bool, 'returnEmptyString') is None

    with pytest.raises(ValueError):
        teek.tcl_eval(bool, 'returnArg lolwut')

    with pytest.raises(TypeError):
        teek.tcl_call(None, 'puts', object())

    assert capfd.readouterr() == ('', '')
    with pytest.raises(TypeError):
        teek.tcl_eval(object(), 'puts hello')

    # tcl seems to use sometimes lf and sometimes crlf, lol
    output, errors = capfd.readouterr()
    assert output.replace('\r\n', '\n') == 'hello\n'
    assert not errors

    # forced to string converting relies on this
    test_data = [
        ('ab', 'ab'),
        ('a b', 'a b'),
        (['a', 'b'], 'a b'),
        ([' a', 'b '], '{ a} {b }'),
        (['a ', ' b'], '{a } { b}'),
        (['a', 'b c'], 'a {b c}'),
        (('a', 'b c'), 'a {b c}'),
        (CustomSequence(), '{a b c} 123'),
    ]
    for before, after in test_data:
        assert teek.tcl_call(str, 'format', '%s', before) == after

    # test conversion to strings when teek.tcl_calling
    assert teek.tcl_call(
        str, 'list', True, 5, 3.14, [1, 2], {3: 4}, ('lol', 'wut'),
    ) == '1 5 3.14 {1 2} {3 4} {lol wut}'

    # special case: Tcl empty string is None in python
    teek.tcl_eval(None, 'proc returnEmpty {} { return {} }')

    class BrokenFromTcl:

        oh_no = False

        @classmethod
        def from_tcl(cls, tcl_string):
            cls.oh_no = True
            raise RuntimeError("NO!! THIS WASNT SUPPSOED TO RUN!!!")

    assert teek.tcl_call(BrokenFromTcl, 'returnEmpty') is None
    assert not BrokenFromTcl.oh_no

    assert capfd.readouterr() == ('', '')
Example #14
0
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')
Example #15
0
 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"