1 """ 2 Use this module to get and run all tk tests. 3 4 Tkinter tests should live in a package inside the directory where this file 5 lives, like test_tkinter. 6 Extensions also should live in packages following the same rule as above. 7 """ 8 9 import os 10 import sys 11 import unittest 12 import importlib 13 import test.test_support 14 15 this_dir_path = os.path.abspath(os.path.dirname(__file__)) 16 17 _tk_unavailable = None 18 19 def check_tk_availability(): 20 """Check that Tk is installed and available.""" 21 global _tk_unavailable 22 23 if _tk_unavailable is None: 24 _tk_unavailable = False 25 if sys.platform == 'darwin': 26 # The Aqua Tk implementations on OS X can abort the process if 27 # being called in an environment where a window server connection 28 # cannot be made, for instance when invoked by a buildbot or ssh 29 # process not running under the same user id as the current console 30 # user. To avoid that, raise an exception if the window manager 31 # connection is not available. 32 from ctypes import cdll, c_int, pointer, Structure 33 from ctypes.util import find_library 34 35 app_services = cdll.LoadLibrary(find_library("ApplicationServices")) 36 37 if app_services.CGMainDisplayID() == 0: 38 _tk_unavailable = "cannot run without OS X window manager" 39 else: 40 class ProcessSerialNumber(Structure): 41 _fields_ = [("highLongOfPSN", c_int), 42 ("lowLongOfPSN", c_int)] 43 psn = ProcessSerialNumber() 44 psn_p = pointer(psn) 45 if ( (app_services.GetCurrentProcess(psn_p) < 0) or 46 (app_services.SetFrontProcess(psn_p) < 0) ): 47 _tk_unavailable = "cannot run without OS X gui process" 48 else: # not OS X 49 import Tkinter 50 try: 51 Tkinter.Button() 52 except Tkinter.TclError as msg: 53 # assuming tk is not available 54 _tk_unavailable = "tk not available: %s" % msg 55 56 if _tk_unavailable: 57 raise unittest.SkipTest(_tk_unavailable) 58 return 59 60 def is_package(path): 61 for name in os.listdir(path): 62 if name in ('__init__.py', '__init__.pyc', '__init.pyo'): 63 return True 64 return False 65 66 def get_tests_modules(basepath=this_dir_path, gui=True, packages=None): 67 """This will import and yield modules whose names start with test_ 68 and are inside packages found in the path starting at basepath. 69 70 If packages is specified it should contain package names that want 71 their tests colleted. 72 """ 73 py_ext = '.py' 74 75 for dirpath, dirnames, filenames in os.walk(basepath): 76 for dirname in list(dirnames): 77 if dirname[0] == '.': 78 dirnames.remove(dirname) 79 80 if is_package(dirpath) and filenames: 81 pkg_name = dirpath[len(basepath) + len(os.sep):].replace('/', '.') 82 if packages and pkg_name not in packages: 83 continue 84 85 filenames = filter( 86 lambda x: x.startswith('test_') and x.endswith(py_ext), 87 filenames) 88 89 for name in filenames: 90 try: 91 yield importlib.import_module( 92 ".%s" % name[:-len(py_ext)], pkg_name) 93 except test.test_support.ResourceDenied: 94 if gui: 95 raise 96 97 def get_tests(text=True, gui=True, packages=None): 98 """Yield all the tests in the modules found by get_tests_modules. 99 100 If nogui is True, only tests that do not require a GUI will be 101 returned.""" 102 attrs = [] 103 if text: 104 attrs.append('tests_nogui') 105 if gui: 106 attrs.append('tests_gui') 107 for module in get_tests_modules(gui=gui, packages=packages): 108 for attr in attrs: 109 for test in getattr(module, attr, ()): 110 yield test 111 112 if __name__ == "__main__": 113 test.test_support.use_resources = ['gui'] 114 test.test_support.run_unittest(*get_tests()) 115