|
1 | | -import inspect |
| 1 | +import os |
| 2 | +import sys |
| 3 | +import unittest |
2 | 4 |
|
3 | 5 | import testlib |
4 | 6 | import mitogen.master |
5 | 7 |
|
6 | 8 |
|
| 9 | +def testmod_compile(path): |
| 10 | + path = os.path.join(testlib.MODS_DIR, path) |
| 11 | + f = open(path, 'rb') |
| 12 | + co = compile(f.read(), path, 'exec') |
| 13 | + f.close() |
| 14 | + return co |
| 15 | + |
| 16 | + |
7 | 17 | class ScanCodeImportsTest(testlib.TestCase): |
8 | 18 | func = staticmethod(mitogen.master.scan_code_imports) |
9 | 19 |
|
10 | | - if mitogen.core.PY3: |
11 | | - level = 0 |
12 | | - else: |
13 | | - level = -1 |
14 | | - |
15 | | - SIMPLE_EXPECT = [ |
16 | | - (level, 'inspect', ()), |
17 | | - (level, 'testlib', ()), |
18 | | - (level, 'mitogen.master', ()), |
19 | | - ] |
20 | | - |
21 | | - def test_simple(self): |
22 | | - source_path = inspect.getsourcefile(ScanCodeImportsTest) |
23 | | - with open(source_path) as f: |
24 | | - co = compile(f.read(), source_path, 'exec') |
25 | | - self.assertEqual(list(self.func(co)), self.SIMPLE_EXPECT) |
| 20 | + @unittest.skipIf(sys.version_info < (3, 0), "Py is 2.x, would be relative") |
| 21 | + def test_default_absolute(self): |
| 22 | + co = testmod_compile('scanning/defaults.py') |
| 23 | + expected = [ |
| 24 | + (0, 'a', ()), (0, 'a.b', ()), (0, 'c', ()), |
| 25 | + (0, 'e', ()), (0, 'e.f', ()), (0, 'h', ()), |
| 26 | + (0, 'i', ()), |
| 27 | + (0, 'j', ('k', 'l', 'm')), |
| 28 | + (0, 'o', ('*',)), |
| 29 | + ] |
| 30 | + self.assertEqual(list(self.func(co)), expected) |
| 31 | + |
| 32 | + @unittest.skipIf(sys.version_info >= (3, 0), "Py is 3.x, would be absolute") |
| 33 | + def test_default_relative(self): |
| 34 | + co = testmod_compile('scanning/defaults.py') |
| 35 | + expected = [ |
| 36 | + (-1, 'a', ()), (-1, 'a.b', ()), (-1, 'c', ()), |
| 37 | + (-1, 'e', ()), (-1, 'e.f', ()), (-1, 'h', ()), |
| 38 | + (-1, 'i', ()), |
| 39 | + (-1, 'j', ('k', 'l', 'm')), |
| 40 | + (-1, 'o', ('*',)), |
| 41 | + ] |
| 42 | + self.assertEqual(list(self.func(co)), expected) |
| 43 | + |
| 44 | + @unittest.skipIf(sys.version_info < (2, 5), "Py is 2.4, no absolute_import") |
| 45 | + def test_explicit_absolute(self): |
| 46 | + co = testmod_compile('scanning/has_absolute_import.py') |
| 47 | + expected = [ |
| 48 | + (0, '__future__', ('absolute_import',)), |
| 49 | + |
| 50 | + (0, 'a', ()), (0, 'a.b', ()), (0, 'c', ()), |
| 51 | + (0, 'e', ()), (0, 'e.f', ()), (0, 'h', ()), |
| 52 | + (0, 'i', ()), |
| 53 | + (0, 'j', ('k', 'l', 'm')), |
| 54 | + (0, 'o', ('*',)), |
| 55 | + ] |
| 56 | + self.assertEqual(list(self.func(co)), expected) |
| 57 | + |
| 58 | + @unittest.skipIf(sys.version_info < (2, 5), "Py is 2.4, no `from . import x`") |
| 59 | + def test_explicit_relative(self): |
| 60 | + co = testmod_compile('scanning/explicit_relative.py') |
| 61 | + expected = [ |
| 62 | + (1, '', ('a',)), |
| 63 | + (1, 'b', ('c', 'd')), |
| 64 | + (3, '', ('f', 'j')), |
| 65 | + ] |
| 66 | + self.assertEqual(list(self.func(co)), expected) |
| 67 | + |
| 68 | + def test_scoped_class(self): |
| 69 | + # Imports in `class` or `def` are ignored, a bad heuristc to detect |
| 70 | + # lazy imports and skip sending the pre-emptively. |
| 71 | + # See |
| 72 | + # - https://github.com/mitogen-hq/mitogen/issues/682 |
| 73 | + # - https://github.com/mitogen-hq/mitogen/issues/1325#issuecomment-3170482014 |
| 74 | + co = testmod_compile('scanning/scoped_class.py') |
| 75 | + self.assertEqual(list(self.func(co)), []) |
| 76 | + |
| 77 | + pass |
| 78 | + |
| 79 | + def test_scoped_function(self): |
| 80 | + co = testmod_compile('scanning/scoped_function.py') |
| 81 | + self.assertEqual(list(self.func(co)), []) |
| 82 | + |
| 83 | + @unittest.skipIf(sys.version_info >= (3, 0), "Python is 3.x, which prunes") |
| 84 | + def test_scoped_if_else_unpruned(self): |
| 85 | + co = testmod_compile('scanning/scoped_if_else.py') |
| 86 | + level = (-1, 0)[int(sys.version_info >= (3, 0))] |
| 87 | + expected = [ |
| 88 | + (level, 'sys', ()), |
| 89 | + (level, 'in_if_always_true', ()), |
| 90 | + (level, 'in_if_always_true', ('x', 'z')), |
| 91 | + # Python 2.x does no pruning |
| 92 | + (level, 'in_else_never_true', ()), |
| 93 | + (level, 'in_else_never_true', ('x', 'z')), |
| 94 | + (level, 'in_if_py3', ()), |
| 95 | + (level, 'in_if_py3', ('x', 'z')), |
| 96 | + (level, 'in_else_py2', ()), |
| 97 | + (level, 'in_else_py2', ('x', 'z')), |
| 98 | + ] |
| 99 | + self.assertEqual(list(self.func(co)), expected) |
| 100 | + |
| 101 | + @unittest.skipIf(sys.version_info < (3, 0), "Python is 2.x, which doesn't prune") |
| 102 | + def test_scoped_if_else_pruned(self): |
| 103 | + co = testmod_compile('scanning/scoped_if_else.py') |
| 104 | + level = (-1, 0)[int(sys.version_info >= (3, 0))] |
| 105 | + expected = [ |
| 106 | + (level, 'sys', ()), |
| 107 | + (level, 'in_if_always_true', ()), |
| 108 | + (level, 'in_if_always_true', ('x', 'z')), |
| 109 | + # Python 3.x prunes some impossible branches ... |
| 110 | + (level, 'in_if_py3', ()), |
| 111 | + (level, 'in_if_py3', ('x', 'z')), |
| 112 | + # ... but not sys.version_info ones |
| 113 | + (level, 'in_else_py2', ()), |
| 114 | + (level, 'in_else_py2', ('x', 'z')), |
| 115 | + ] |
| 116 | + self.assertEqual(list(self.func(co)), expected) |
| 117 | + |
| 118 | + def test_scoped_try_except(self): |
| 119 | + co = testmod_compile('scanning/scoped_try_except.py') |
| 120 | + level = (-1, 0)[int(sys.version_info >= (3, 0))] |
| 121 | + expected = [ |
| 122 | + (level, 'in_try', ()), |
| 123 | + (level, 'in_try', ('x', 'z')), |
| 124 | + (level, 'in_except_importerror', ()), |
| 125 | + (level, 'in_except_importerror', ('x', 'z')), |
| 126 | + (level, 'in_except_exception', ()), |
| 127 | + (level, 'in_except_exception', ('x', 'z')), |
| 128 | + ] |
| 129 | + self.assertEqual(list(self.func(co)), expected) |
0 commit comments