CleanCut / green

Green is a clean, colorful, fast python test runner.
MIT License
793 stars 75 forks source link

Compatibility issue with Python 2.7.3 and earlier #137

Closed gurnec closed 7 years ago

gurnec commented 7 years ago

With Python 2.7.3 and earlier, running green on this test ends in an exception from green, instead of the expected Error result:

import unittest

class Test(unittest.TestCase):
    def test(self):
        raise Exception()
Traceback (most recent call last):
  File "green\green.py", line 6, in <module>
    sys.exit(main())
  File "C:\Users\Chris\Documents\green\green\cmdline.py", line 30, in main
    from green.runner import run
  File "C:\Users\Chris\Documents\green\green\runner.py", line 18, in <module>
    from green.process import LoggingDaemonlessPool, poolRunner
  File "C:\Users\Chris\Documents\green\green\process.py", line 143, in <module>
    from multiprocessing.pool import MaybeEncodingError
ImportError: cannot import name MaybeEncodingError

Unfortunately, multiprocessing.pool.MaybeEncodingError, as imported here in green, wasn't introduced until 2.7.4.

2.7.3 is a fairly old version of Python, so feel free to just close this if you'd prefer, but it's also the "system" version (as opposed to the virtualenv version) that's present on Travis (w/Ubuntu 12.04) which I happen to use.

CleanCut commented 7 years ago

Well, that's just annoying. We have supported all versions of 2.7 so far.

If you patch it like this, does it work okay?

--- a/green/process.py
+++ b/green/process.py
@@ -140,7 +140,27 @@ class LoggingDaemonlessPool(Pool):
 import platform
 import multiprocessing.pool
 from multiprocessing import util
-from multiprocessing.pool import MaybeEncodingError
+try:
+    from multiprocessing.pool import MaybeEncodingError
+except:
+    # Python 2.7.4 introduced this class.  If we're on Python 2.7.0 to 2.7.3
+    # then we'll have to define it ourselves. :-/
+    class MaybeEncodingError(Exception):
+        """Wraps possible unpickleable errors, so they can be
+        safely sent through the socket."""
+
+        def __init__(self, exc, value):
+            self.exc = repr(exc)
+            self.value = repr(value)
+            super(MaybeEncodingError, self).__init__(self.exc, self.value)
+
+        def __str__(self):
+            return "Error sending result: '%s'. Reason: '%s'" % (self.value,
+                                                                 self.exc)
+
+        def __repr__(self):
+            return "<MaybeEncodingError: %s>" % str(self)
+

 # Python 2 and 3 raise a different error when they exit
 if platform.python_version_tuple()[0] == '2': # pragma: no cover
gurnec commented 7 years ago

Yes, that fixes it for me (Python 2.7.3 on Windows).

I'll give it a try on Travis at some point and let you know if I see anything wrong, but I expect that this would fix it there too.

Thanks ( and I promise I'll stop bugging you for a while ;-) )

CleanCut commented 7 years ago

Included in 2.5.2 (just released).

gurnec commented 7 years ago

Thanks! I've added it to my Travis build, and it's working great!