Submitter | Jun Wu |
---|---|
Date | May 9, 2016, 12:06 a.m. |
Message ID | <0e68b512f4d9dad9c064.1462752382@x1c> |
Download | mbox | patch |
Permalink | /patch/14978/ |
State | Changes Requested |
Headers | show |
Comments
On Mon, May 09, 2016 at 01:06:22AM +0100, Jun Wu wrote: > # HG changeset patch > # User Jun Wu <quark@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@mercurial-scm.org > https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
On 05/11/2016 03:01 AM, Augie Fackler wrote: > 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.) It's print(..., end=x). You are right, print_function works. Thanks for looking at these. I will send a V2 addressing all issues.
Patch
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.