[PATCH 3 of 6] socketserver: make it compatible with python 2
Augie Fackler
raf at durin42.com
Tue May 10 22:01:31 EDT 2016
On Mon, May 09, 2016 at 01:06:22AM +0100, Jun Wu wrote:
> # 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.
The print difference could be handled with a from __future__ import,
couldn't it? (I think it's print_function, but maybe I'm missing something.)
>
> 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.
> _______________________________________________
> Mercurial-devel mailing list
> Mercurial-devel at mercurial-scm.org
> https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
More information about the Mercurial-devel
mailing list