It looks like Python 3's futures library lacks set_exception_info
entirely. We'll just give up and use set_exception in that case.
- no-check-commit because the underbar naming is just saner here
| indygreg |
| hg-reviewers |
It looks like Python 3's futures library lacks set_exception_info
entirely. We'll just give up and use set_exception in that case.
| Automatic diff as part of commit; lint not applicable. |
| Automatic diff as part of commit; unit tests not applicable. |
| Path | Packages | |||
|---|---|---|---|---|
| M | mercurial/httppeer.py (3 lines) | |||
| M | mercurial/localrepo.py (2 lines) | |||
| M | mercurial/pycompat.py (6 lines) | |||
| M | mercurial/wireprotov1peer.py (8 lines) |
| if meta['cbor']: | if meta['cbor']: | ||||
| payload = util.bytesio(meta['data']) | payload = util.bytesio(meta['data']) | ||||
| decoder = cbor.CBORDecoder(payload) | decoder = cbor.CBORDecoder(payload) | ||||
| while payload.tell() + 1 < len(meta['data']): | while payload.tell() + 1 < len(meta['data']): | ||||
| try: | try: | ||||
| result.append(decoder.decode()) | result.append(decoder.decode()) | ||||
| except Exception: | except Exception: | ||||
| f.set_exception_info(*sys.exc_info()[1:]) | pycompat.future_set_exception_info( | ||||
| f, sys.exc_info()[1:]) | |||||
| continue | continue | ||||
| else: | else: | ||||
| result.append(meta['data']) | result.append(meta['data']) | ||||
| if meta['eos']: | if meta['eos']: | ||||
| f.set_result(result) | f.set_result(result) | ||||
| del results[request.requestid] | del results[request.requestid] | ||||
| # method on the peer and return a resolved future. | # method on the peer and return a resolved future. | ||||
| fn = getattr(self._peer, pycompat.sysstr(command)) | fn = getattr(self._peer, pycompat.sysstr(command)) | ||||
| f = pycompat.futures.Future() | f = pycompat.futures.Future() | ||||
| try: | try: | ||||
| result = fn(**args) | result = fn(**args) | ||||
| except Exception: | except Exception: | ||||
| f.set_exception_info(*sys.exc_info()[1:]) | pycompat.future_set_exception_info(f, sys.exc_info()[1:]) | ||||
| else: | else: | ||||
| f.set_result(result) | f.set_result(result) | ||||
| return f | return f | ||||
| def sendcommands(self): | def sendcommands(self): | ||||
| self._sent = True | self._sent = True | ||||
| import cookielib | import cookielib | ||||
| import cPickle as pickle | import cPickle as pickle | ||||
| import httplib | import httplib | ||||
| import Queue as _queue | import Queue as _queue | ||||
| import SocketServer as socketserver | import SocketServer as socketserver | ||||
| import xmlrpclib | import xmlrpclib | ||||
| from .thirdparty.concurrent import futures | from .thirdparty.concurrent import futures | ||||
| def future_set_exception_info(f, exc_info): | |||||
| f.set_exception_info(*exc_info) | |||||
| else: | else: | ||||
| import concurrent.futures as futures | import concurrent.futures as futures | ||||
| import http.cookiejar as cookielib | import http.cookiejar as cookielib | ||||
| import http.client as httplib | import http.client as httplib | ||||
| import pickle | import pickle | ||||
| import queue as _queue | import queue as _queue | ||||
| import socketserver | import socketserver | ||||
| import xmlrpc.client as xmlrpclib | import xmlrpc.client as xmlrpclib | ||||
| def future_set_exception_info(f, exc_info): | |||||
| f.set_exception(exc_info[0]) | |||||
| empty = _queue.Empty | empty = _queue.Empty | ||||
| queue = _queue.Queue | queue = _queue.Queue | ||||
| def identity(a): | def identity(a): | ||||
| return a | return a | ||||
| if ispy3: | if ispy3: | ||||
| import builtins | import builtins | ||||
| # Future was cancelled. Ignore it. | # Future was cancelled. Ignore it. | ||||
| if not f.set_running_or_notify_cancel(): | if not f.set_running_or_notify_cancel(): | ||||
| return | return | ||||
| try: | try: | ||||
| result = fn(**pycompat.strkwargs(args)) | result = fn(**pycompat.strkwargs(args)) | ||||
| except Exception: | except Exception: | ||||
| f.set_exception_info(*sys.exc_info()[1:]) | pycompat.future_set_exception_info(f, sys.exc_info()[1:]) | ||||
| else: | else: | ||||
| f.set_result(result) | f.set_result(result) | ||||
| return | return | ||||
| # Batch commands are a bit harder. First, we have to deal with the | # Batch commands are a bit harder. First, we have to deal with the | ||||
| # @batchable coroutine. That's a bit annoying. Furthermore, we also | # @batchable coroutine. That's a bit annoying. Furthermore, we also | ||||
| # need to preserve streaming. i.e. it should be possible for the | # need to preserve streaming. i.e. it should be possible for the | ||||
| # futures to resolve as data is coming in off the wire without having | # futures to resolve as data is coming in off the wire without having | ||||
| # to wait for the final byte of the final response. We do this by | # to wait for the final byte of the final response. We do this by | ||||
| # spinning up a thread to read the responses. | # spinning up a thread to read the responses. | ||||
| requests = [] | requests = [] | ||||
| states = [] | states = [] | ||||
| for command, args, fn, f in calls: | for command, args, fn, f in calls: | ||||
| # Future was cancelled. Ignore it. | # Future was cancelled. Ignore it. | ||||
| if not f.set_running_or_notify_cancel(): | if not f.set_running_or_notify_cancel(): | ||||
| continue | continue | ||||
| try: | try: | ||||
| batchable = fn.batchable(fn.__self__, | batchable = fn.batchable(fn.__self__, | ||||
| **pycompat.strkwargs(args)) | **pycompat.strkwargs(args)) | ||||
| except Exception: | except Exception: | ||||
| f.set_exception_info(*sys.exc_info()[1:]) | pycompat.future_set_exception_info(f, sys.exc_info()[1:]) | ||||
| return | return | ||||
| # Encoded arguments and future holding remote result. | # Encoded arguments and future holding remote result. | ||||
| try: | try: | ||||
| encodedargs, fremote = next(batchable) | encodedargs, fremote = next(batchable) | ||||
| except Exception: | except Exception: | ||||
| f.set_exception_info(*sys.exc_info()[1:]) | pycompat.future_set_exception_info(f, sys.exc_info()[1:]) | ||||
| return | return | ||||
| requests.append((command, encodedargs)) | requests.append((command, encodedargs)) | ||||
| states.append((command, f, batchable, fremote)) | states.append((command, f, batchable, fremote)) | ||||
| if not requests: | if not requests: | ||||
| return | return | ||||
| # about it. | # about it. | ||||
| remoteresult = next(wireresults) | remoteresult = next(wireresults) | ||||
| fremote.set(remoteresult) | fremote.set(remoteresult) | ||||
| # And ask the coroutine to decode that value. | # And ask the coroutine to decode that value. | ||||
| try: | try: | ||||
| result = next(batchable) | result = next(batchable) | ||||
| except Exception: | except Exception: | ||||
| f.set_exception_info(*sys.exc_info()[1:]) | pycompat.future_set_exception_info(f, sys.exc_info()[1:]) | ||||
| else: | else: | ||||
| f.set_result(result) | f.set_result(result) | ||||
| @zi.implementer(repository.ipeercommands, repository.ipeerlegacycommands) | @zi.implementer(repository.ipeercommands, repository.ipeerlegacycommands) | ||||
| class wirepeer(repository.peer): | class wirepeer(repository.peer): | ||||
| """Client-side interface for communicating with a peer repository. | """Client-side interface for communicating with a peer repository. | ||||
| Methods commonly call wire protocol commands of the same name. | Methods commonly call wire protocol commands of the same name. | ||||