[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