Rev 13: setup.py's that import modules are now supported by plugin-info, though in http://people.canonical.com/~robertc/baz2.0/plugins/plugin_info/trunk

Robert Collins robertc at robertcollins.net
Mon Mar 1 04:37:58 GMT 2010


At http://people.canonical.com/~robertc/baz2.0/plugins/plugin_info/trunk

------------------------------------------------------------
revno: 13
revision-id: robertc at robertcollins.net-20100301043749-jtpu8aenalcmxs5q
parent: robertc at robertcollins.net-20100301021719-d1udrsm29naaaqgf
committer: Robert Collins <robertc at robertcollins.net>
branch nick: trunk
timestamp: Mon 2010-03-01 15:37:49 +1100
message:
  setup.py's that import modules are now supported by plugin-info, though 
  those modules should be as shallow as possible to avoid interactions.
=== modified file 'NEWS'
--- a/NEWS	2010-03-01 01:32:52 +0000
+++ b/NEWS	2010-03-01 04:37:49 +0000
@@ -24,6 +24,10 @@
 
   BUGFIXES:
 
+    * setup.py's that import modules are now supported by plugin-info, though 
+      those modules should be as shallow as possible to avoid interactions.
+      (Robert Collins)
+
   API BREAKS:
 
   TESTING:

=== modified file 'extract.py'
--- a/extract.py	2010-03-01 01:32:52 +0000
+++ b/extract.py	2010-03-01 04:37:49 +0000
@@ -28,6 +28,8 @@
     'PluginInfo',
     ]
 
+import sys
+
 from bzrlib import branch, directory_service, osutils
 
 
@@ -54,14 +56,29 @@
     :param path: The path the plugin can be found at.
     :return: A PluginInfo for the plugin at path.
     """
-    source_file = open(path + '/setup.py', 'rb')
+    # setup a fake 'package' that this setup can import siblings from
+    package = MyPackage(path)
+    source_path = path  + '/setup.py'
+    source_file = open(source_path, 'rb')
     try:
         source = source_file.read()
     finally:
         source_file.close()
     code = compile(source, 'setup.py', 'exec')
-    eval_globals = {}
-    module = eval(code, eval_globals)
+    eval_globals = {'__file__':source_path,
+        '__name__':'setup',
+        '__package__':package.__name__}
+    sys.modules[package.__name__] = package
+    try:
+        module = eval(code, eval_globals)
+    finally:
+        del sys.modules[package.__name__]
+        to_unload = []
+        for module in sys.modules.keys():
+            if module.startswith(package.__name__ + '.'):
+                to_unload.append(module)
+        for module in to_unload:
+            del sys.modules[module]
     result = PluginInfo()
     result.name = eval_globals.get('bzr_plugin_name', None)
     result.commands = eval_globals.get('bzr_commands', [])
@@ -141,3 +158,13 @@
         result.append('plugin.repository_formats = %s\n' % (self.repository_formats,))
         result.append('plugin.transports = %s\n' % (self.transports,))
         return ''.join(result)
+
+
+class MyPackage(object):
+    """A package to isolate (a little) imports."""
+
+    def __init__(self, dir):
+        setattr(self, '__file__', dir + '/__init__.py')
+        setattr(self, '__name__', 'setup_plugin_info')
+        setattr(self, '__package__', 'setup_plugin_info')
+        setattr(self, '__path__', [dir])

=== modified file 'tests/test_extract.py'
--- a/tests/test_extract.py	2010-03-01 01:32:52 +0000
+++ b/tests/test_extract.py	2010-03-01 04:37:49 +0000
@@ -18,6 +18,7 @@
 """Tests for extracting data from a plugin."""
 
 from copy import copy
+import sys
 
 from bzrlib import directory_service
 from bzrlib.plugins.plugin_info.extract import *
@@ -191,6 +192,17 @@
         expected_plugin.location = 'foo--bar'
         self.assertEqual(expected_plugin, plugin)
 
+    def test_extract_imports_sibling(self):
+        self.build_tree(['foo--bar/'])
+        self.build_tree_contents([('foo--bar/info.py', self.sample_setup()),
+            ('foo--bar/setup.py', 'from info import *\n')])
+        imported = list(sys.modules.keys())
+        plugin = extract_info_local('foo--bar')
+        expected_plugin = self.expected_plugin()
+        expected_plugin.location = 'foo--bar'
+        self.assertEqual(expected_plugin, plugin)
+        self.assertEqual(imported, sys.modules.keys())
+
     def test_extract_info_branch(self):
         tree = self.setup_plugin()
         expected_plugin = self.expected_plugin()




More information about the bazaar-commits mailing list