freeipa/ignore_import_errors.py
Jan Cholasta 9b53423815 makeapi, makeaci: do not fail on missing imports
Add import hook to makeapi and makeaci which makes them ignore import
errors in modules in our source tree and instead print a warning.

This makes it possible to build IPA without having to have most of our
runtime dependencies installed.

https://fedorahosted.org/freeipa/ticket/6418

Reviewed-By: Petr Spacek <pspacek@redhat.com>
Reviewed-By: Martin Basti <mbasti@redhat.com>
2016-10-24 14:11:08 +02:00

88 lines
2.5 KiB
Python

#
# Copyright (C) 2016 FreeIPA Contributors see COPYING for license
#
"""
ImportError ignoring import hook.
"""
from __future__ import print_function
import imp
import inspect
import os.path
import sys
DIRNAME = os.path.dirname(os.path.abspath(__file__))
class FailedImport(object):
def __init__(self, loader, name):
self.__file__ = __file__
self.__name__ = name
self.__path__ = []
self.__loader__ = loader
self.__package__ = name
def __repr__(self):
return '<failed import {!r}>'.format(self.__name__)
class IgnoringImporter(object):
def find_module(self, fullname, path=None):
parentname, dot, name = fullname.rpartition('.')
assert (not dot and path is None) or (dot and path is not None)
# check if the module can be found
try:
file, _filename, _description = imp.find_module(name, path)
except ImportError:
pass
else:
if file is not None:
file.close()
# it can be found, do normal import
return None
# check if the parent module import failed
if dot and isinstance(sys.modules[parentname], FailedImport):
# it did fail, so this import will fail as well
return self
# find out from where are we importing
if path is None:
path = sys.path
for pathname in path:
pathname = os.path.abspath(pathname)
if not pathname.startswith(DIRNAME):
break
else:
# importing from our source tree, do normal import
return None
# find out into what .py file are we importing
frame = inspect.currentframe().f_back
filename = frame.f_code.co_filename
if filename.startswith('<'):
# not a file, do normal import
return None
filename = os.path.abspath(filename)
if not filename.startswith(DIRNAME):
# not a file in our source tree, do normal import
return None
return self
def load_module(self, fullname):
frame = inspect.currentframe().f_back
print("{}: {}:{}: ignoring ImportError: No module named {}".format(
sys.argv[0],
os.path.relpath(frame.f_code.co_filename),
frame.f_lineno,
fullname))
return sys.modules.setdefault(fullname, FailedImport(self, fullname))
sys.meta_path.insert(0, IgnoringImporter())