def test_subinterp3(self): """exercise loading tohil into a child and grandchild interpreter and delete the child, implicitly deleting the grandchild, and make sure no child interpreters are left over""" make_a_bunch(2, 1) self.assertEqual(tohil.call('interp', 'delete', 'x0'), '') self.assertEqual(tohil.call('interp', 'slaves'), '')
def test_subinterp2(self): """exercise loading tohil into a child and grandchild interpreter and delete the grandchild first then the child""" make_a_bunch(2, 1) self.assertEqual(tohil.call('interp', 'delete', 'x0 x0'), '') self.assertEqual(tohil.call('interp', 'delete', 'x0'), '') self.assertEqual(tohil.call('interp', 'slaves'), '')
def test_subinterp1(self): """exercise loading tohil into a child interpreter, and make sure no child interpreters are left over""" interp = tohil.eval("interp create") tohil.call(interp, 'eval', 'package require tohil') self.assertEqual(tohil.call('interp', 'delete', interp), '') self.assertEqual(tohil.call('interp', 'slaves'), '')
def test_subst1(self): """exercise tohil.subst""" tohil.call("set", "name", "karl") self.assertEqual(tohil.subst("hello, $name"), "hello, karl") self.assertEqual(tohil.subst("hello, [return $name]"), "hello, karl") self.assertEqual( repr(tohil.subst("hello, [return $name]", to=tohil.tclobj)), "<tohil.tclobj: 'hello, karl'>", )
def test_call2(self): """make sure tohil.call doesn't expand its arguments""" self.assertEqual(tohil.call("return", "[info globals]"), "[info globals]") self.assertEqual(tohil.call("return", "$secretVariable"), "$secretVariable") with self.assertRaises(tohil.TclError): tohil.call("better_not_be_this_asdfjhk")
def test_call3(self): """test with some arguments; compare to eval's output""" self.assertEqual( tohil.call("clock", "format", 1, "-gmt", 1, "-locale", "fr_FR"), "jeu. janv. 01 00:00:01 GMT 1970", ) self.assertEqual( tohil.call("clock", "format", 1, "-gmt", 1, "-locale", "fr_FR"), tohil.eval("clock format 1 -gmt 1 -locale fr_FR"), )
def test_kw_args(self): # tohil.call ignores kwargs and so they'll never make it back to the # callback def callback(*args, **kwargs): return args, kwargs tohil.register_callback("pycallback", callback) self.assertEqual(tohil.call("pycallback", 1, akwarg=2), ((1,), {}))
def iseven(num): num = int(num) if num == 1: return False elif num == 0: return True else: return not tohil.call("isodd", num - 2, to=bool)
def test_subinterpreter_explicit_delete(self): subinterp = tohil.call("interp", "create", to=str) # This can often cause spooky behavior since it creates a python # subinterpreter which is then deleted when we delete the Tcl # subinterpreter tohil.call(subinterp, "eval", "package require tohil") self.assertEqual(len(tohil.call("interp", "slaves", to=list)), 1) tohil.call("interp", "delete", subinterp) self.assertEqual(tohil.call("interp", "slaves", to=list), [])
def test_subinterpreter_gc_delete_loop(self): class TohilInterp: deleted = False def __init__(self): self.interp = tohil.call("interp", "create") def __del__(self): type(self).deleted = True tohil.call("interp", "delete", self.interp) def call(self, command, *args): return tohil.call(self.interp, "eval", [command, *args]) for i in range(5): TohilInterp.deleted = False subinterp = TohilInterp() subinterp.call("package", "require", "tohil") self.assertEqual(len(tohil.call("interp", "slaves", to=list)), 1) del subinterp self.assertEqual(tohil.call("interp", "slaves", to=list), []) self.assertTrue(TohilInterp.deleted)
def test_subinterpreter_gc_delete(self): class TohilInterp: deleted = False def __init__(self): self.interp = tohil.call("interp", "create") def __del__(self): type(self).deleted = True tohil.call("interp", "delete", self.interp) def call(self, command, *args): return tohil.call(self.interp, "eval", [command, *args]) subinterp = TohilInterp() # This can often cause spooky behavior since it creates a python # subinterpreter which is then deleted when we delete the Tcl # subinterpreter subinterp.call("package", "require", "tohil") self.assertEqual(len(tohil.call("interp", "slaves", to=list)), 1) del subinterp self.assertEqual(tohil.call("interp", "slaves", to=list), []) self.assertTrue(TohilInterp.deleted)
def test_after_func(self): flag = False def setflag(): nonlocal flag flag = True tohil.register_callback("setflag", setflag) tohil.call("after", 100, "setflag") while not flag: tohil.call("update") tohil.call("update", "idletasks") time.sleep(.05) assert flag
def make_a_bunch(depth: int, width: int): for interp in d4(depth, width): #print(f"creating {interp}") tohil.call('interp', 'create', interp) tohil.call('interp', 'eval', interp, 'package require tohil')
def test_call5(self): """test """ self.assertEqual(no_arg_kw(foo="bar"), "{'foo': 'bar'}") with self.assertRaises(tohil.TclError): tohil.call("")
def test_call4(self): """test what happens when we cause an error on the tcl side""" with self.assertRaises(tohil.TclError): tohil.call("cant", "run", "this")
def test_subinterp4(self): """the goodie, make 39 nested tcl interpreters, each loading tohil, then delete various ones while expecting to get all their children too and end up with no child interpreters extant """ make_a_bunch(3, 3) #print(f'''"{tohil.eval('interp slaves')}"''') #print("deleting x2 x0 x1") tohil.call('interp', 'delete', ['x2', 'x0', 'x1']) #print("deleting x2 x1") tohil.call('interp', 'delete', ['x2', 'x1']) #print("deleting x2") tohil.call('interp', 'delete', ['x2']) #print("deleting x2 x1") tohil.call('interp', 'delete', ['x1', 'x1']) #print("deleting x1") tohil.call('interp', 'delete', ['x1']) #print("deleting x0") tohil.call('interp', 'delete', ['x0']) #print('done') self.assertEqual(tohil.call('interp', 'slaves'), '')
def test_call1(self): """exercise tohil.call""" self.assertEqual(tohil.call("expr", "5 + 5", to=int), 10) self.assertEqual( tohil.call("expr", "[clock seconds] > 1000000000", to=bool), True)
def test_simple(self): def callback(arg): return arg tohil.register_callback("pycallback", callback) self.assertEqual(tohil.call("pycallback", 1), tohil.tclobj(1))
def test_too_many_args(self): def callback(required): return required tohil.register_callback("pycallback", callback) with self.assertRaises(tohil.TclError): tohil.call("pycallback 1 2")
def test_missing_req_arg(self): def callback(required): return required tohil.register_callback("pycallback", callback) with self.assertRaises(tohil.TclError): tohil.call("pycallback")
def call(self, command, *args): return tohil.call(self.interp, "eval", [command, *args])
def test_var_args(self): def callback(*args): return args tohil.register_callback("pycallback", callback) self.assertEqual(tohil.call("pycallback", 1, 2, 3), ("1", "2", "3"))
def __del__(self): type(self).deleted = True tohil.call("interp", "delete", self.interp)
def __init__(self): self.interp = tohil.call("interp", "create")