import_test.py 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. from __future__ import print_function
  2. import os
  3. import re
  4. import sys
  5. import time
  6. import signal
  7. import traceback
  8. import warnings
  9. import __res
  10. from __res import importer
  11. def setup_test_environment():
  12. try:
  13. from yatest_lib.ya import Ya
  14. import yatest.common as yc
  15. yc.runtime._set_ya_config(ya=Ya())
  16. except ImportError:
  17. pass
  18. def check_imports(no_check=(), extra=(), skip_func=None, py_main=None):
  19. """
  20. tests all bundled modules are importable
  21. just add
  22. "PEERDIR(library/python/import_test)" to your CMakeLists.txt and
  23. "from import_test import test_imports" to your python test source file.
  24. """
  25. if not isinstance(b'', str):
  26. def str_(s):
  27. return s.decode('UTF-8')
  28. else:
  29. def str_(s):
  30. return s
  31. exceptions = list(no_check)
  32. for key, _ in __res.iter_keys(b'py/no_check_imports/'):
  33. exceptions += str_(__res.find(key)).split()
  34. if exceptions:
  35. exceptions.sort()
  36. print('NO_CHECK_IMPORTS', ' '.join(exceptions))
  37. # all test modules get imported when tests are run
  38. exceptions.append('__tests__.*')
  39. patterns = [re.escape(s).replace(r'\*', r'.*') for s in exceptions]
  40. rx = re.compile('^({})$'.format('|'.join(patterns)))
  41. failed = []
  42. import_times = {}
  43. def norm(s):
  44. return (s[:-9] if s.endswith('.__init__') else s)
  45. modules = sys.extra_modules | set(extra)
  46. modules = sorted(modules, key=norm)
  47. if py_main:
  48. modules = [py_main] + modules
  49. for module in modules:
  50. if module not in extra and (rx.search(module) or skip_func and skip_func(module)):
  51. print('SKIP', module)
  52. continue
  53. name = module.rsplit('.', 1)[-1]
  54. if name == '__main__' and 'if __name__ ==' not in importer.get_source(module):
  55. print('SKIP', module, '''without "if __name__ == '__main__'" check''')
  56. continue
  57. def print_backtrace_marked(e):
  58. tb_exc = traceback.format_exception(*e)
  59. for item in tb_exc:
  60. for line in item.splitlines():
  61. print('FAIL:', line, file=sys.stderr)
  62. try:
  63. print('TRY', module)
  64. # XXX waiting for py3 to use print(..., flush=True)
  65. sys.stdout.flush()
  66. s = time.time()
  67. with warnings.catch_warnings():
  68. warnings.filterwarnings(action="ignore", category=DeprecationWarning)
  69. if module == '__main__':
  70. importer.load_module('__main__', '__main__py')
  71. elif module.endswith('.__init__'):
  72. __import__(module[:-len('.__init__')])
  73. else:
  74. __import__(module)
  75. delay = time.time() - s
  76. import_times[str(module)] = delay
  77. print('OK ', module, '{:.3f}s'.format(delay))
  78. except Exception as e:
  79. print('FAIL:', module, e, file=sys.stderr)
  80. print_backtrace_marked(sys.exc_info())
  81. failed.append('{}: {}'.format(module, e))
  82. except BaseException:
  83. e = sys.exc_info()
  84. print('FAIL:', module, e, file=sys.stderr)
  85. print_backtrace_marked(e)
  86. failed.append('{}: {}'.format(module, e))
  87. raise
  88. print("Slowest imports:")
  89. for m, t in sorted(import_times.items(), key=lambda x: x[1], reverse=True)[:30]:
  90. print(' ', '{:.3f}s'.format(t), m)
  91. if failed:
  92. raise ImportError('modules not imported:\n' + '\n'.join(failed))
  93. test_imports = check_imports
  94. def main():
  95. setup_test_environment()
  96. skip_names = sys.argv[1:]
  97. try:
  98. import faulthandler
  99. except ImportError:
  100. faulthandler = None
  101. if faulthandler:
  102. # Dump python backtrace in case of any errors
  103. faulthandler.enable()
  104. if hasattr(signal, "SIGUSR2"):
  105. # SIGUSR2 is used by test_tool to teardown tests
  106. faulthandler.register(signal.SIGUSR2, chain=True)
  107. os.environ['Y_PYTHON_IMPORT_TEST'] = ''
  108. # We should initialize Django before importing any applications
  109. if os.getenv('DJANGO_SETTINGS_MODULE'):
  110. try:
  111. import django
  112. except ImportError:
  113. pass
  114. else:
  115. django.setup()
  116. py_main = __res.find('PY_MAIN')
  117. if py_main:
  118. py_main_module = py_main.split(b':', 1)[0].decode('UTF-8')
  119. else:
  120. py_main_module = None
  121. try:
  122. check_imports(no_check=skip_names, py_main=py_main_module)
  123. except Exception:
  124. sys.exit(1)