Kaynağa Gözat

- Use rich comparison methods rather than __cmp__ to sort process
configs and process group configs to better straddle Python
versions. (thanks to Jonathan Riboux for identifying the problem
and supplying an initial patch).

- Fixed test_supervisorctl.test_maintail_dashf test for Python 2.7.
(thanks to Jonathan Riboux for identifying the problem and
supplying an initial patch).

- Fixed the way that supervisor.datatypes.url computes a "good" URL
for compatibility with Python 2.7 and Python >= 2.6.5. URLs with
bogus "schemes://" will now be accepted as a version-straddling
compromise (before they were rejected before supervisor would
start). (thanks to Jonathan Riboux for identifying the problem
and supplying an initial patch).

Chris McDonough 15 yıl önce
ebeveyn
işleme
0c5547b03c

+ 16 - 0
CHANGES.txt

@@ -1,5 +1,21 @@
 Next release
 
+  - Use rich comparison methods rather than __cmp__ to sort process
+    configs and process group configs to better straddle Python
+    versions.  (thanks to Jonathan Riboux for identifying the problem
+    and supplying an initial patch).
+
+  - Fixed test_supervisorctl.test_maintail_dashf test for Python 2.7.
+    (thanks to Jonathan Riboux for identifying the problem and
+    supplying an initial patch).
+
+  - Fixed the way that supervisor.datatypes.url computes a "good" URL
+    for compatibility with Python 2.7 and Python >= 2.6.5.  URLs with
+    bogus "schemes://" will now be accepted as a version-straddling
+    compromise (before they were rejected before supervisor would
+    start).  (thanks to Jonathan Riboux for identifying the problem
+    and supplying an initial patch).
+
   - Add a ``-v`` / ``--version`` option to supervisord: Print the
     supervisord version number out to stdout and exit.  (Roger Hoover)
 

+ 2 - 0
setup.cfg

@@ -2,6 +2,8 @@
 zip_ok = false
 
 [nosetests]
+exclude=medusa
+where=src/supervisor
 nocapture=1
 cover-package=supervisor
 with-coverage=1

+ 5 - 4
src/supervisor/datatypes.py

@@ -401,10 +401,11 @@ byte_size = SuffixMultiplier({'kb': 1024,
 
 def url(value):
     import urlparse
-    scheme, netloc, path, params, query, fragment = urlparse.urlparse(value)
-    if scheme and netloc:
-        return value     
-    if scheme == 'unix' and path.startswith('//') and len(path) > 2:
+    # earlier Python 2.6 urlparse (2.6.4 and under) can't parse unix:// URLs,
+    # later ones can but we need to straddle
+    uri = value.replace('unix://', 'http://', 1).strip()
+    scheme, netloc, path, params, query, fragment = urlparse.urlparse(uri)
+    if scheme and (netloc or path):
         return value
     raise ValueError("value %s is not a URL" % value)
 

+ 37 - 8
src/supervisor/options.py

@@ -694,7 +694,6 @@ class ServerOptions(Options):
                 FastCGIGroupConfig(self, program_name, priority, processes,
                                    socket_config)
                 )
-        
 
         groups.sort()
         return groups
@@ -1508,14 +1507,38 @@ class UnhosedConfigParser(ConfigParser.RawConfigParser):
             else:
                 return default
 
-class Config:
-    def __cmp__(self, other):
-        return cmp(self.priority, other.priority)
+class Config(object):
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __lt__(self, other):
+        if self.priority == other.priority:
+            return self.name < other.name
+            
+        return self.priority < other.priority
+
+    def __le__(self, other):
+        if self.priority == other.priority:
+            return self.name <= other.name
+            
+        return self.priority <= other.priority
+
+    def __gt__(self, other):
+        if self.priority == other.priority:
+            return self.name > other.name
+            
+        return self.priority > other.priority
+
+    def __ge__(self, other):
+        if self.priority == other.priority:
+            return self.name >= other.name
+            
+        return self.priority >= other.priority
 
     def __repr__(self):
         return '<%s instance at %s named %s>' % (self.__class__, id(self),
                                                  self.name)
-    
+
 class ProcessConfig(Config):
     req_param_names = [
         'name', 'uid', 'command', 'directory', 'umask', 'priority',
@@ -1642,9 +1665,6 @@ class ProcessGroupConfig(Config):
 
         return True
 
-    def __ne__(self, other):
-        return not self.__eq__(other)
-
     def after_setuid(self):
         for config in self.process_configs:
             config.create_autochildlogs()
@@ -1664,6 +1684,15 @@ class EventListenerPoolConfig(Config):
         self.pool_events = pool_events
         self.result_handler = result_handler
 
+    def __eq__(self, other):
+        if not isinstance(other, EventListenerPoolConfig):
+            return False
+        
+        if (self.name == other.name) and (self.priority == other.priority):
+            return True
+
+        return False
+            
     def after_setuid(self):
         for config in self.process_configs:
             config.create_autochildlogs()

+ 0 - 4
src/supervisor/tests/test_datatypes.py

@@ -198,10 +198,6 @@ class DatatypesTest(unittest.TestCase):
         bad_url = "unix://"
         self.assertRaises(ValueError, datatypes.url, bad_url)   
     
-    def test_url_rejects_urlparse_unrecognized_scheme_with_path(self):
-        bad_url = "bad://path"
-        self.assertRaises(ValueError, datatypes.url, bad_url)
-
 class InetStreamSocketConfigTests(unittest.TestCase):
     def _getTargetClass(self):
         return datatypes.InetStreamSocketConfig

+ 35 - 15
src/supervisor/tests/test_options.py

@@ -403,8 +403,13 @@ class ServerOptionsTests(unittest.TestCase):
         instance.realize(args=[])
 
         section = instance.configroot.supervisord
+
         self.assertEqual(len(section.process_group_configs), 2)
+
         cat = section.process_group_configs[0]
+        self.assertEqual(len(cat.process_configs), 1)
+
+        cat = section.process_group_configs[1]
         self.assertEqual(len(cat.process_configs), 2)
         self.assertTrue(section.process_group_configs is
                         instance.process_group_configs)
@@ -426,14 +431,10 @@ class ServerOptionsTests(unittest.TestCase):
         instance.process_config_file()
 
         section = instance.configroot.supervisord
+
         self.assertEqual(len(section.process_group_configs), 2)
-        cat = section.process_group_configs[0]
-        self.assertEqual(len(cat.process_configs), 1)
-        proc = cat.process_configs[0]
-        self.assertEqual(proc.name, 'three')
-        self.assertEqual(proc.command, '/bin/pig')
 
-        cat = section.process_group_configs[1]
+        cat = section.process_group_configs[0]
         self.assertEqual(len(cat.process_configs), 1)
         proc = cat.process_configs[0]
         self.assertEqual(proc.name, 'one')
@@ -441,6 +442,12 @@ class ServerOptionsTests(unittest.TestCase):
         self.assertTrue(section.process_group_configs is
                         instance.process_group_configs)
 
+        cat = section.process_group_configs[1]
+        self.assertEqual(len(cat.process_configs), 1)
+        proc = cat.process_configs[0]
+        self.assertEqual(proc.name, 'three')
+        self.assertEqual(proc.command, '/bin/pig')
+
     def test_readFile_failed(self):
         from supervisor.options import readFile
         try:
@@ -725,6 +732,12 @@ class ServerOptionsTests(unittest.TestCase):
         process_name = %(program_name)s_%(process_num)s
         command = /bin/cat
         numprocs = 3
+
+        [eventlistener:biz]
+        events=PROCESS_COMMUNICATION
+        process_name = %(program_name)s_%(process_num)s
+        command = /bin/biz
+        numprocs = 2
         """)
         from supervisor.options import UnhosedConfigParser
         from supervisor.dispatchers import default_handler
@@ -732,15 +745,20 @@ class ServerOptionsTests(unittest.TestCase):
         config.read_string(text)
         instance = self._makeOne()
         gconfigs = instance.process_groups_from_parser(config)
-        self.assertEqual(len(gconfigs), 2)
+        self.assertEqual(len(gconfigs), 3)
 
         gconfig1 = gconfigs[0]
+        self.assertEqual(gconfig1.name, 'biz')
+        self.assertEqual(gconfig1.result_handler, default_handler)
+        self.assertEqual(len(gconfig1.process_configs), 2)
+
+        gconfig1 = gconfigs[1]
         self.assertEqual(gconfig1.name, 'cat')
         self.assertEqual(gconfig1.priority, -1)
         self.assertEqual(gconfig1.result_handler, default_handler)
         self.assertEqual(len(gconfig1.process_configs), 3)
 
-        gconfig1 = gconfigs[1]
+        gconfig1 = gconfigs[2]
         self.assertEqual(gconfig1.name, 'dog')
         self.assertEqual(gconfig1.priority, 1)
         self.assertEqual(gconfig1.result_handler, default_handler)
@@ -840,6 +858,7 @@ class ServerOptionsTests(unittest.TestCase):
             return instance.process_groups_from_parser(config)
 
         gconfigs = get_process_groups(instance, config)
+        
         exp_owner = (sentinel.uid, sentinel.gid)
 
         self.assertEqual(len(gconfigs), 4)
@@ -856,7 +875,7 @@ class ServerOptionsTests(unittest.TestCase):
         pconfig_foo = gconf_foo.process_configs[0]
         self.assertEqual(pconfig_foo.__class__, FastCGIProcessConfig)
         
-        gconf_bar = gconfigs[2]
+        gconf_bar = gconfigs[1]
         self.assertEqual(gconf_bar.name, 'bar')
         self.assertEqual(gconf_bar.priority, 999)
         self.assertEqual(gconf_bar.socket_config.url,
@@ -865,7 +884,13 @@ class ServerOptionsTests(unittest.TestCase):
         self.assertEqual(0700, gconf_bar.socket_config.get_mode())
         self.assertEqual(len(gconf_bar.process_configs), 3)
         
-        gconf_flub = gconfigs[1]
+        gconf_cub = gconfigs[2]
+        self.assertEqual(gconf_cub.name, 'cub')
+        self.assertEqual(gconf_cub.socket_config.url,
+                         'tcp://localhost:6000')
+        self.assertEqual(len(gconf_cub.process_configs), 1)
+
+        gconf_flub = gconfigs[3]
         self.assertEqual(gconf_flub.name, 'flub')
         self.assertEqual(gconf_flub.socket_config.url,
                          'unix:///tmp/flub.sock')
@@ -873,11 +898,6 @@ class ServerOptionsTests(unittest.TestCase):
         self.assertEqual(0700, gconf_flub.socket_config.get_mode())
         self.assertEqual(len(gconf_flub.process_configs), 1)
         
-        gconf_cub = gconfigs[3]
-        self.assertEqual(gconf_cub.name, 'cub')
-        self.assertEqual(gconf_cub.socket_config.url,
-                         'tcp://localhost:6000')
-        self.assertEqual(len(gconf_cub.process_configs), 1)
         
 
     def test_fcgi_program_no_socket(self):

+ 3 - 3
src/supervisor/tests/test_supervisorctl.py

@@ -867,9 +867,9 @@ class TestDefaultControllerPlugin(unittest.TestCase):
         self.assertEqual(len(errors), 1)
         error = errors[0]
         self.assertEqual(plugin.listener.closed,
-                         'http://localhost:92491/mainlogtail')
+                         'http://localhost:65532/mainlogtail')
         self.assertEqual(error[0],
-                         'http://localhost:92491/mainlogtail')
+                         'http://localhost:65532/mainlogtail')
         for msg in ('Cannot connect', 'socket.error'):
             self.assertTrue(msg in error[1])
 
@@ -951,7 +951,7 @@ class DummyPluginFactory:
 class DummyClientOptions:
     def __init__(self):
         self.prompt = 'supervisor'
-        self.serverurl = 'http://localhost:92491' # should be uncontactable
+        self.serverurl = 'http://localhost:65532'
         self.username = 'chrism'
         self.password = '123'
         self.history_file = None