Coverage for test_plugins.py : 81%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1# -*- coding: utf-8 -*-
2#@+leo-ver=5-thin
3#@+node:ekr.20210907081548.1: * @file ../unittests/test_plugins.py
4#@@first
5"""General tests of plugins."""
7import glob
8import re
9from leo.core import leoGlobals as g
10from leo.core.leoTest2 import LeoUnitTest
11from leo.core.leoPlugins import LeoPluginsController
12assert g
14#@+others
15#@+node:ekr.20210907082556.1: ** class TestPlugins(LeoUnitTest)
16class TestPlugins(LeoUnitTest):
17 """General tests of plugoins."""
18 #@+others
19 #@+node:ekr.20210909165100.1: *3* TestPlugin.check_syntax
20 def check_syntax(self, filename): # pylint: disable=inconsistent-return-statements
21 with open(filename, 'r') as f:
22 s = f.read()
23 try:
24 s = s.replace('\r', '')
25 tree = compile(s + '\n', filename, 'exec')
26 del tree # #1454: Suppress -Wd ResourceWarning.
27 return True
28 except SyntaxError:
29 raise
30 except Exception:
31 self.fail(f"unexpected error in: {filename}")
33 #@+node:ekr.20210907082746.1: *3* TestPlugins.get_plugins
34 def get_plugins(self):
35 """Return a list of all plugins *without* importing them."""
36 excludes = (
37 # These are not real plugins...
38 'babel_api.py',
39 'babel_kill.py',
40 'babel_lib.py',
41 'baseNativeTree.py',
42 'leocursor.py',
43 'leo_cloud_server.py',
44 'leo_mypy_plugin.py',
45 'nested_splitter.py',
46 'qtGui.py',
47 'qt_gui.py',
48 'qt_big_text.py',
49 'qt_commands.py',
50 'qt_events.py',
51 'qt_frame.py',
52 'qt_idle_time.py',
53 'qt_main.py',
54 'qt_quickheadlines.py',
55 'qt_quicksearch_sub.py',
56 'qt_text.py',
57 'qt_tree.py',
58 'qt_quicksearch.py',
59 'swing_gui.py',
60 # Experimental.
61 'leo_pdf.py',
62 )
63 plugins = g.os_path_join(g.app.loadDir, '..', 'plugins', '*.py')
64 plugins = g.os_path_abspath(plugins)
65 files = glob.glob(plugins)
66 files = [z for z in files if not z.endswith('__init__.py')]
67 files = [z for z in files if g.shortFileName(z) not in excludes]
68 files = [g.os_path_abspath(z) for z in files]
69 return sorted(files)
70 #@+node:ekr.20210907081455.2: *3* TestPlugins.test_all_plugins_have_top_level_init_method
71 def test_all_plugins_have_top_level_init_method(self):
72 # Ensure all plugins have top-level init method *without* importing them.
73 files = self.get_plugins()
74 for fn in files:
75 with open(fn, 'r') as f:
76 s = f.read()
77 self.assertTrue('def init():' in s or 'def init ():' in s, msg=fn)
78 #@+node:ekr.20210907081455.3: *3* TestPlugins.test_all_qt_plugins_call_g_assertUi_qt_
79 def test_all_qt_plugins_call_g_assertUi_qt_(self):
80 files = self.get_plugins()
81 excludes = (
82 # Special cases, handling Qt imports in unusual ways.
83 'backlink.py', # Qt code is optional, disabled with module-level guard.
84 'leoscreen.py', # Qt imports are optional.
85 'nodetags.py', # #2031: Qt imports are optional.
86 'picture_viewer.py', # Special case.
87 'pyplot_backend.py',
88 'remove_duplicate_pictures.py' # Special case.
89 )
90 pattern = re.compile(r'\b(QtCore|QtGui|QtWidgets)\b') # Don't search for Qt.
91 for fn in files:
92 if g.shortFileName(fn) in excludes:
93 continue
94 with open(fn, 'r') as f:
95 s = f.read()
96 if not re.search(pattern, s):
97 continue
98 self.assertTrue(re.search(r"g\.assertUi\(['\"]qt['\"]\)", s), msg=fn)
99 #@+node:ekr.20210909161328.2: *3* TestPlugins.test_c_vnode2position
100 def test_c_vnode2position(self):
101 c = self.c
102 for p in c.all_positions():
103 p2 = c.vnode2position(p.v)
104 # We can *not* assert that p == p2!
105 assert p2
106 self.assertEqual(p2.v, p.v)
107 assert c.positionExists(p2), 'does not exist: %s' % p2
108 #@+node:ekr.20210909194336.57: *3* TestPlugins.test_regularizeName
109 def test_regularizeName(self):
110 pc = LeoPluginsController()
111 table = (
112 ('x', 'x'),
113 ('foo.bar', 'foo.bar'),
114 ('x.py', 'leo.plugins.x'),
115 ('leo.plugins.x', 'leo.plugins.x')
116 )
117 for fn, expected in table:
118 result = pc.regularizeName(fn)
119 self.assertEqual(result, expected, msg=fn)
120 # Make sure that calling regularizeName twice is benign.
121 result2 = pc.regularizeName(result)
122 assert result2 == result
123 #@+node:ekr.20210909161328.4: *3* TestPlugins.test_syntax_of_all_plugins
124 def test_syntax_of_all_plugins(self):
125 files = self.get_plugins()
126 for filename in files:
127 self.check_syntax(filename)
128 #@+node:ekr.20210909165720.1: *3* TestPlugins.xx_test_import_all_plugins
129 def xx_test_import_of_all_plugins(self):
130 # This works, but is slow.
131 files = self.get_plugins()
132 for filename in files:
133 plugin_module = g.shortFileName(filename)[:-3]
134 try:
135 exec(f"import leo.plugins.{plugin_module}")
136 except g.UiTypeException:
137 pass
138 except AttributeError:
139 pass
140 except ImportError:
141 pass
142 #@-others
143#@-others
144#@-leo