140 lines
5.3 KiB
Python
140 lines
5.3 KiB
Python
|
__author__ = "jadmanski@google.com (John Admanski)"
|
||
|
|
||
|
import os, sys
|
||
|
|
||
|
# This must run on Python versions less than 2.4.
|
||
|
dirname = os.path.dirname(sys.modules[__name__].__file__)
|
||
|
common_dir = os.path.abspath(os.path.join(dirname, "common_lib"))
|
||
|
sys.path.insert(0, common_dir)
|
||
|
import check_version
|
||
|
sys.path.pop(0)
|
||
|
check_version.check_python_version()
|
||
|
|
||
|
import glob, traceback, types
|
||
|
|
||
|
|
||
|
def _create_module(name):
|
||
|
"""Create a single top-level module"""
|
||
|
module = types.ModuleType(name)
|
||
|
sys.modules[name] = module
|
||
|
return module
|
||
|
|
||
|
|
||
|
def _create_module_and_parents(name):
|
||
|
"""Create a module, and all the necessary parents"""
|
||
|
parts = name.split(".")
|
||
|
# first create the top-level module
|
||
|
parent = _create_module(parts[0])
|
||
|
created_parts = [parts[0]]
|
||
|
parts.pop(0)
|
||
|
# now, create any remaining child modules
|
||
|
while parts:
|
||
|
child_name = parts.pop(0)
|
||
|
module = types.ModuleType(child_name)
|
||
|
setattr(parent, child_name, module)
|
||
|
created_parts.append(child_name)
|
||
|
sys.modules[".".join(created_parts)] = module
|
||
|
parent = module
|
||
|
|
||
|
|
||
|
def _import_children_into_module(parent_module_name, path):
|
||
|
"""Import all the packages on a path into a parent module"""
|
||
|
# find all the packages at 'path'
|
||
|
names = []
|
||
|
for filename in os.listdir(path):
|
||
|
full_name = os.path.join(path, filename)
|
||
|
if not os.path.isdir(full_name):
|
||
|
continue # skip files
|
||
|
if "." in filename:
|
||
|
continue # if "." is in the name it's not a valid package name
|
||
|
if not os.access(full_name, os.R_OK | os.X_OK):
|
||
|
continue # need read + exec access to make a dir importable
|
||
|
if "__init__.py" in os.listdir(full_name):
|
||
|
names.append(filename)
|
||
|
# import all the packages and insert them into 'parent_module'
|
||
|
sys.path.insert(0, path)
|
||
|
for name in names:
|
||
|
module = __import__(name)
|
||
|
# add the package to the parent
|
||
|
parent_module = sys.modules[parent_module_name]
|
||
|
setattr(parent_module, name, module)
|
||
|
full_name = parent_module_name + "." + name
|
||
|
sys.modules[full_name] = module
|
||
|
# restore the system path
|
||
|
sys.path.pop(0)
|
||
|
|
||
|
|
||
|
def import_module(module, from_where):
|
||
|
"""Equivalent to 'from from_where import module'
|
||
|
Returns the corresponding module"""
|
||
|
from_module = __import__(from_where, globals(), locals(), [module])
|
||
|
return getattr(from_module, module)
|
||
|
|
||
|
|
||
|
def _autotest_logging_handle_error(self, record):
|
||
|
"""Method to monkey patch into logging.Handler to replace handleError."""
|
||
|
# The same as the default logging.Handler.handleError but also prints
|
||
|
# out the original record causing the error so there is -some- idea
|
||
|
# about which call caused the logging error.
|
||
|
import logging
|
||
|
if logging.raiseExceptions:
|
||
|
# Avoid recursion as the below output can end up back in here when
|
||
|
# something has *seriously* gone wrong in autotest.
|
||
|
logging.raiseExceptions = 0
|
||
|
sys.stderr.write('Exception occurred formatting message: '
|
||
|
'%r using args %r\n' % (record.msg, record.args))
|
||
|
traceback.print_stack()
|
||
|
sys.stderr.write('-' * 50 + '\n')
|
||
|
traceback.print_exc()
|
||
|
sys.stderr.write('Future logging formatting exceptions disabled.\n')
|
||
|
|
||
|
|
||
|
def _monkeypatch_logging_handle_error():
|
||
|
# Hack out logging.py*
|
||
|
logging_py = os.path.join(os.path.dirname(__file__), "common_lib",
|
||
|
"logging.py*")
|
||
|
if glob.glob(logging_py):
|
||
|
os.system("rm -f %s" % logging_py)
|
||
|
|
||
|
# Monkey patch our own handleError into the logging module's StreamHandler.
|
||
|
# A nicer way of doing this -might- be to have our own logging module define
|
||
|
# an autotest Logger instance that added our own Handler subclass with this
|
||
|
# handleError method in it. But that would mean modifying tons of code.
|
||
|
import logging
|
||
|
assert callable(logging.Handler.handleError)
|
||
|
logging.Handler.handleError = _autotest_logging_handle_error
|
||
|
|
||
|
|
||
|
def setup(base_path, root_module_name=""):
|
||
|
"""
|
||
|
Perform all the necessary setup so that all the packages at
|
||
|
'base_path' can be imported via "import root_module_name.package".
|
||
|
If root_module_name is empty, then all the packages at base_path
|
||
|
are inserted as top-level packages.
|
||
|
|
||
|
Also, setup all the common.* aliases for modules in the common
|
||
|
library.
|
||
|
|
||
|
The setup must be different if you are running on an Autotest server
|
||
|
or on a test machine that just has the client directories installed.
|
||
|
"""
|
||
|
# Hack... Any better ideas?
|
||
|
if (root_module_name == 'autotest_lib.client' and
|
||
|
os.path.exists(os.path.join(os.path.dirname(__file__),
|
||
|
'..', 'server'))):
|
||
|
root_module_name = 'autotest_lib'
|
||
|
base_path = os.path.abspath(os.path.join(base_path, '..'))
|
||
|
|
||
|
_create_module_and_parents(root_module_name)
|
||
|
_import_children_into_module(root_module_name, base_path)
|
||
|
|
||
|
if root_module_name == 'autotest_lib':
|
||
|
# Allow locally installed third party packages to be found
|
||
|
# before any that are installed on the system itself when not.
|
||
|
# running as a client.
|
||
|
# This is primarily for the benefit of frontend and tko so that they
|
||
|
# may use libraries other than those available as system packages.
|
||
|
sys.path.insert(0, os.path.join(base_path, "site-packages"))
|
||
|
|
||
|
_monkeypatch_logging_handle_error()
|