[PATCH 3 of 6] socketserver: make it compatible with python 2
Jun Wu
quark at fb.com
Sun May 8 20:06:22 EDT 2016
# HG changeset patch
# User Jun Wu <quark at fb.com>
# Date 1462502252 -3600
# Fri May 06 03:37:32 2016 +0100
# Node ID 0e68b512f4d9dad9c064342b0deebd45238f0cdf
# Parent d94e32fbb8c35c2b536a74780f54d563a48e19c5
socketserver: make it compatible with python 2
The unmodified socketserver.py from Python 3 has issues with Python 2, namely
"import selectors" and a "print" difference.
This patch adds shim code for Python 2.6, 2.7 to makes it just work.
diff --git a/mercurial/socketserver.py b/mercurial/socketserver.py
--- a/mercurial/socketserver.py
+++ b/mercurial/socketserver.py
@@ -140,7 +140,11 @@
import dummy_threading as threading
import time as timemod
-time = timemod.monotonic
+if hasattr(timemod, 'monotonic'):
+ time = timemod.monotonic
+else:
+ # Python 2 does not have monotonic
+ time = timemod.time
__all__ = ["BaseServer", "TCPServer", "UDPServer", "ForkingUDPServer",
"ForkingTCPServer", "ThreadingUDPServer", "ThreadingTCPServer",
@@ -161,8 +165,44 @@
try:
import selectors
except ImportError:
- # Python 2 does not have selectors
- pass
+ # Python 2 does not have selectors. This is a minimal "selectors"
+ # module just satisfying the needs of the "socketserver" module.
+ import select
+ class selectors(object):
+ EVENT_READ = (1 << 0)
+
+ class SelectSelector(object):
+ def __init__(self):
+ self._fileobj = None
+
+ def register(self, fileobj, events, data=None):
+ assert events == selectors.EVENT_READ
+ assert data is None
+ self._fileobj = fileobj
+
+ def select(self, timeout=None):
+ if self._fileobj is None:
+ return False
+ # copied from Python 2.7 SocketServer._eintr_retry
+ while True:
+ try:
+ r, w, e = select.select([self._fileobj], [], [],
+ timeout)
+ # the return value is incompatible with Python 3
+ # since we don't want to introduce heavy stuff like
+ # SelectorKey.
+ # it's good enough for all the use cases in this
+ # socketserver module.
+ return r
+ except (OSError, select.error) as e:
+ if e.args[0] != errno.EINTR:
+ raise
+
+ def __enter__(self):
+ return self
+
+ def __exit__(self, *args):
+ pass
# poll/select have the advantage of not requiring any extra file descriptor,
# contrarily to epoll/kqueue (also, they require a single syscall).
@@ -388,8 +428,8 @@
"""
print('-'*40)
- print('Exception happened during processing of request from', end=' ')
- print(client_address)
+ print('Exception happened during processing of request from %s'
+ % client_address)
import traceback
traceback.print_exc() # XXX But this goes to stderr!
print('-'*40)
@@ -573,7 +613,10 @@
except ChildProcessError:
# we don't have any children, we're done
self.active_children.clear()
- except OSError:
+ except OSError as e:
+ # "ChildProcessError" for Python 2
+ if e.errno == errno.ECHILD:
+ self.active_children.clear()
break
# Now reap all defunct children.
@@ -586,8 +629,10 @@
except ChildProcessError:
# someone else reaped it
self.active_children.discard(pid)
- except OSError:
- pass
+ except OSError as e:
+ # "ChildProcessError" for Python 2
+ if e.errno == errno.ECHILD:
+ self.active_children.discard(pid)
def handle_timeout(self):
"""Wait for zombies after self.timeout seconds of inactivity.
More information about the Mercurial-devel
mailing list