1 __author__ = "jadmanski (at] google.com (John Admanski)" 2 3 import os, sys 4 5 # This must run on Python versions less than 2.4. 6 dirname = os.path.dirname(sys.modules[__name__].__file__) 7 common_dir = os.path.abspath(os.path.join(dirname, "common_lib")) 8 sys.path.insert(0, common_dir) 9 import check_version 10 sys.path.pop(0) 11 check_version.check_python_version() 12 13 import new, glob, traceback 14 15 16 def _create_module(name): 17 """Create a single top-level module""" 18 module = new.module(name) 19 sys.modules[name] = module 20 return module 21 22 23 def _create_module_and_parents(name): 24 """Create a module, and all the necessary parents""" 25 parts = name.split(".") 26 # first create the top-level module 27 parent = _create_module(parts[0]) 28 created_parts = [parts[0]] 29 parts.pop(0) 30 # now, create any remaining child modules 31 while parts: 32 child_name = parts.pop(0) 33 module = new.module(child_name) 34 setattr(parent, child_name, module) 35 created_parts.append(child_name) 36 sys.modules[".".join(created_parts)] = module 37 parent = module 38 39 40 def _import_children_into_module(parent_module_name, path): 41 """Import all the packages on a path into a parent module""" 42 # find all the packages at 'path' 43 names = [] 44 for filename in os.listdir(path): 45 full_name = os.path.join(path, filename) 46 if not os.path.isdir(full_name): 47 continue # skip files 48 if "." in filename: 49 continue # if "." is in the name it's not a valid package name 50 if not os.access(full_name, os.R_OK | os.X_OK): 51 continue # need read + exec access to make a dir importable 52 if "__init__.py" in os.listdir(full_name): 53 names.append(filename) 54 # import all the packages and insert them into 'parent_module' 55 sys.path.insert(0, path) 56 for name in names: 57 module = __import__(name) 58 # add the package to the parent 59 parent_module = sys.modules[parent_module_name] 60 setattr(parent_module, name, module) 61 full_name = parent_module_name + "." + name 62 sys.modules[full_name] = module 63 # restore the system path 64 sys.path.pop(0) 65 66 67 def import_module(module, from_where): 68 """Equivalent to 'from from_where import module' 69 Returns the corresponding module""" 70 from_module = __import__(from_where, globals(), locals(), [module]) 71 return getattr(from_module, module) 72 73 74 def _autotest_logging_handle_error(self, record): 75 """Method to monkey patch into logging.Handler to replace handleError.""" 76 # The same as the default logging.Handler.handleError but also prints 77 # out the original record causing the error so there is -some- idea 78 # about which call caused the logging error. 79 import logging 80 if logging.raiseExceptions: 81 # Avoid recursion as the below output can end up back in here when 82 # something has *seriously* gone wrong in autotest. 83 logging.raiseExceptions = 0 84 sys.stderr.write('Exception occurred formatting message: ' 85 '%r using args %r\n' % (record.msg, record.args)) 86 traceback.print_stack() 87 sys.stderr.write('-' * 50 + '\n') 88 traceback.print_exc() 89 sys.stderr.write('Future logging formatting exceptions disabled.\n') 90 91 92 def _monkeypatch_logging_handle_error(): 93 # Hack out logging.py* 94 logging_py = os.path.join(os.path.dirname(__file__), "common_lib", 95 "logging.py*") 96 if glob.glob(logging_py): 97 os.system("rm -f %s" % logging_py) 98 99 # Monkey patch our own handleError into the logging module's StreamHandler. 100 # A nicer way of doing this -might- be to have our own logging module define 101 # an autotest Logger instance that added our own Handler subclass with this 102 # handleError method in it. But that would mean modifying tons of code. 103 import logging 104 assert callable(logging.Handler.handleError) 105 logging.Handler.handleError = _autotest_logging_handle_error 106 107 108 def setup(base_path, root_module_name=""): 109 """ 110 Perform all the necessary setup so that all the packages at 111 'base_path' can be imported via "import root_module_name.package". 112 If root_module_name is empty, then all the packages at base_path 113 are inserted as top-level packages. 114 115 Also, setup all the common.* aliases for modules in the common 116 library. 117 118 The setup must be different if you are running on an Autotest server 119 or on a test machine that just has the client directories installed. 120 """ 121 # Hack... Any better ideas? 122 if (root_module_name == 'autotest_lib.client' and 123 os.path.exists(os.path.join(os.path.dirname(__file__), 124 '..', 'server'))): 125 root_module_name = 'autotest_lib' 126 base_path = os.path.abspath(os.path.join(base_path, '..')) 127 128 _create_module_and_parents(root_module_name) 129 _import_children_into_module(root_module_name, base_path) 130 131 if root_module_name == 'autotest_lib': 132 # Allow locally installed third party packages to be found 133 # before any that are installed on the system itself when not. 134 # running as a client. 135 # This is primarily for the benefit of frontend and tko so that they 136 # may use libraries other than those available as system packages. 137 sys.path.insert(0, os.path.join(base_path, "site-packages")) 138 139 _monkeypatch_logging_handle_error() 140