1
2
3
4
5
6
7
8
9
10
11
12
13
14 import glob
15 import os
16 import pkg_resources
17 import shutil
18 import subprocess
19 import sys
20 import unittest
21
22 from trac import loader
23 from trac.core import ComponentMeta
24 from trac.test import EnvironmentStub, mkdtemp
25 from trac.util import create_file
26 from trac.util.compat import close_fds
27
28
29 _setup_py = """\
30 from setuptools import setup, find_packages
31
32 setup(
33 name = '%(name)s',
34 version = '1.0',
35 description = '',
36 license = '',
37 install_requires = ['Trac'],
38 packages = find_packages(exclude=['*.tests*']),
39 extras_require = {'dependency': 'Dependency'},
40 entry_points = {'trac.plugins': [
41 'ComponentA = %(name)s:ComponentA',
42 'ComponentB = %(name)s:ComponentB[dependency]'
43 ]
44 })
45 """
46
47
48 _plugin_py = """\
49 import os.path
50 from trac.core import Component, implements
51 from trac.env import IEnvironmentSetupParticipant
52 from trac.util import create_file
53
54 class ComponentA(Component):
55
56 implements(IEnvironmentSetupParticipant)
57
58 def __init__(self):
59 self._created_file = os.path.join(self.env.path, 'log', 'created_a')
60 self._upgraded_file = os.path.join(self.env.path, 'log', 'upgraded_a')
61
62 def environment_created(self):
63 self.upgrade_environment()
64
65 def environment_needs_upgrade(self):
66 return not os.path.exists(self._upgraded_file)
67
68 def upgrade_environment(self):
69 create_file(self._upgraded_file)
70
71
72 class ComponentB(Component):
73
74 implements(IEnvironmentSetupParticipant)
75
76 def __init__(self):
77 self._created_file = os.path.join(self.env.path, 'log', 'created_b')
78 self._upgraded_file = os.path.join(self.env.path, 'log', 'upgraded_b')
79
80 def environment_created(self):
81 self.upgrade_environment()
82
83 def environment_needs_upgrade(self):
84 return not os.path.exists(self._upgraded_file)
85
86 def upgrade_environment(self):
87 create_file(self._upgraded_file)
88 """
89
90
92
97
103
105 for plugin_name in os.listdir(self.env.plugins_dir):
106 plugin_path = os.path.join(self.env.plugins_dir, plugin_name)
107 try:
108 pkg_resources.working_set.entries.remove(plugin_path)
109 except ValueError:
110 pass
111 else:
112 del pkg_resources.working_set.entry_keys[plugin_path]
113
115 plugin_src = os.path.join(self.env.path, 'plugin_src')
116 os.mkdir(plugin_src)
117 os.mkdir(os.path.join(plugin_src, module_name))
118 create_file(os.path.join(plugin_src, 'setup.py'),
119 _setup_py % {'name': module_name})
120 create_file(os.path.join(plugin_src, module_name, '__init__.py'),
121 _plugin_py)
122 proc = subprocess.Popen((sys.executable, 'setup.py', 'bdist_egg'),
123 cwd=plugin_src, stdin=subprocess.PIPE,
124 stdout=subprocess.PIPE, stderr=subprocess.PIPE,
125 close_fds=close_fds)
126 proc.communicate(input='')
127 for f in (proc.stdin, proc.stdout, proc.stderr):
128 f.close()
129 for filename in glob.glob(os.path.join(plugin_src, 'dist', '*-*.egg')):
130 return filename
131
133 """Load entry points with extras
134
135 Entry points with absent dependencies should not be found in
136 the component registry.
137 """
138 egg_file_src = self._build_egg_file('plugin1')
139 egg_file_dst = os.path.join(self.env.plugins_dir,
140 os.path.basename(egg_file_src))
141 shutil.copyfile(egg_file_src, egg_file_dst)
142
143 loader.load_components(self.env)
144 from plugin1 import ComponentA, ComponentB
145 self.components.append(ComponentA)
146 self.components.append(ComponentB)
147
148 from trac.env import IEnvironmentSetupParticipant
149 registry = ComponentMeta._registry
150 self.assertIn(ComponentA, ComponentMeta._components)
151 self.assertIn(ComponentA, registry.get(IEnvironmentSetupParticipant))
152 self.assertNotIn(ComponentB, ComponentMeta._components)
153 self.assertNotIn(ComponentB, registry.get(IEnvironmentSetupParticipant))
154
156 create_file(os.path.join(self.env.plugins_dir,
157 'RegressionTestRev6017.py'), """\
158 from trac.wiki.macros import WikiMacroBase
159
160 class RegressionTestRev6017Macro(WikiMacroBase):
161 def expand_macro(self, formatter, name, content, args):
162 return "Hello World"
163
164 """)
165
166 loader.load_components(self.env)
167 loader.load_components(self.env)
168
169 loaded_components = [c for c in ComponentMeta._components
170 if 'RegressionTestRev6017' in c.__name__]
171
172 self.assertEqual(1, len(loaded_components),
173 "Plugin loaded more than once.")
174
175
177 suite = unittest.TestSuite()
178 suite.addTest(unittest.makeSuite(LoadComponentsTestCase))
179 return suite
180
181
182 if __name__ == '__main__':
183 unittest.main(defaultTest='test_suite')
184