Package trac :: Package tests :: Module loader

Source Code for Module trac.tests.loader

  1  # -*- coding: utf-8 -*- 
  2  # 
  3  # Copyright (C) 2017-2023 Edgewall Software 
  4  # All rights reserved. 
  5  # 
  6  # This software is licensed as described in the file COPYING, which 
  7  # you should have received as part of this distribution. The terms 
  8  # are also available at https://trac.edgewall.org/wiki/TracLicense. 
  9  # 
 10  # This software consists of voluntary contributions made by many 
 11  # individuals. For the exact contribution history, see the revision 
 12  # history and logs, available at https://trac.edgewall.org/log/. 
 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   
91 -class LoadComponentsTestCase(unittest.TestCase):
92
93 - def setUp(self):
94 self.env = EnvironmentStub(path=mkdtemp()) 95 os.makedirs(os.path.join(self.env.path, 'plugins')) 96 self.components = []
97
98 - def tearDown(self):
99 self._cleanup_working_set() 100 self.env.reset_db_and_disk() 101 for c in self.components: 102 ComponentMeta.deregister(c)
103
104 - def _cleanup_working_set(self):
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
114 - def _build_egg_file(self, module_name):
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
132 - def test_entry_point_with_extras(self):
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
176 -def test_suite():
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