comparison mercurial/scmutil.py @ 45838:ae00e170f2d1

errors: catch urllib errors specifically instead of using safehasattr() Before this patch, we would catch `IOError` and `OSError` and check if the instance had a `.code` member (indicates `HTTPError`) or a `.reason` member (indicates the more generic `URLError`). It seems to me that can simply catch those exception specifically instead, so that's what this code does. The existing code is from fbe8834923c5 (commands: report http exceptions nicely, 2005-06-17), so I suspect it's just that there was no `urllib2` (where `URLError` lives) back then. The old code mentioned `SSLError` in a comment. The new code does *not* try to catch that. The documentation for `ssl.SSLError` says that it has a `.reason` property, but `python -c 'import ssl; print(dir(ssl.SSLError("foo", Exception("bar"))))` doesn't mention that property on either Python 2 or Python 3 on my system. It also seems that `sslutil` is pretty careful about converting `ssl.SSLError` to `error.Abort`. It also is carefult to not assume that instances of the exception have a `.reason`. So I at least don't want to catch `ssl.SSLError` and handle it the same way as `URLError` because that would likely result in a crash. I also wonder if we don't need to handle it at all (because `sslutil` might handle all the cases). It's now early in the release cycle, so perhaps we can just see how it goes? Differential Revision: https://phab.mercurial-scm.org/D9318
author Martin von Zweigbergk <martinvonz@google.com>
date Thu, 12 Nov 2020 21:56:52 -0800
parents e0dbfbd4062c
children ebee234d952a
comparison
equal deleted inserted replaced
45837:2eb8ad899fa6 45838:ae00e170f2d1
234 m = stringutil.forcebytestr(inst).split()[-1] 234 m = stringutil.forcebytestr(inst).split()[-1]
235 if m in b"mpatch bdiff".split(): 235 if m in b"mpatch bdiff".split():
236 ui.error(_(b"(did you forget to compile extensions?)\n")) 236 ui.error(_(b"(did you forget to compile extensions?)\n"))
237 elif m in b"zlib".split(): 237 elif m in b"zlib".split():
238 ui.error(_(b"(is your Python install correct?)\n")) 238 ui.error(_(b"(is your Python install correct?)\n"))
239 except util.urlerr.httperror as inst:
240 ui.error(_(b"abort: %s\n") % stringutil.forcebytestr(inst))
241 except util.urlerr.urlerror as inst:
242 try: # usually it is in the form (errno, strerror)
243 reason = inst.reason.args[1]
244 except (AttributeError, IndexError):
245 # it might be anything, for example a string
246 reason = inst.reason
247 if isinstance(reason, pycompat.unicode):
248 # SSLError of Python 2.7.9 contains a unicode
249 reason = encoding.unitolocal(reason)
250 ui.error(_(b"abort: error: %s\n") % stringutil.forcebytestr(reason))
239 except (IOError, OSError) as inst: 251 except (IOError, OSError) as inst:
240 if util.safehasattr(inst, b"code"): # HTTPError 252 if (
241 ui.error(_(b"abort: %s\n") % stringutil.forcebytestr(inst))
242 elif util.safehasattr(inst, b"reason"): # URLError or SSLError
243 try: # usually it is in the form (errno, strerror)
244 reason = inst.reason.args[1]
245 except (AttributeError, IndexError):
246 # it might be anything, for example a string
247 reason = inst.reason
248 if isinstance(reason, pycompat.unicode):
249 # SSLError of Python 2.7.9 contains a unicode
250 reason = encoding.unitolocal(reason)
251 ui.error(_(b"abort: error: %s\n") % stringutil.forcebytestr(reason))
252 elif (
253 util.safehasattr(inst, b"args") 253 util.safehasattr(inst, b"args")
254 and inst.args 254 and inst.args
255 and inst.args[0] == errno.EPIPE 255 and inst.args[0] == errno.EPIPE
256 ): 256 ):
257 pass 257 pass