Repository: python-pillow/Pillow

Issue:
Add a retry to fetch.py in case of network errors
### What did you do?

Build on AppVeyor.

### What did you expect to happen?

Build to pass. If there's a network error, retry.

### What actually happened?

Sometimes it fails if there's a network error.

From https://ci.appveyor.com/project/Python-pillow/pillow/builds/22999840/job/0iedt6bxyffke9xw (but since restarted).


```python
etching https://github.com/ArtifexSoftware/ghostpdl-downloads/releases/download/gs926/ghostscript-9.26.tar.gz
c:\python34\python.exe : Traceback (most recent call last):
At line:7 char:3
+   c:\python34\python.exe c:\pillow\winbuild\build_dep.py
+   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (Traceback (most recent call last)::String) [], RemoteException
    + FullyQualifiedErrorId : NativeCommandError
 
  File "C:\python34\lib\urllib\request.py", line 1183, in do_open
    h.request(req.get_method(), req.selector, req.data, headers)
  File "C:\python34\lib\http\client.py", line 1137, in request
    self._send_request(method, url, body, headers)
  File "C:\python34\lib\http\client.py", line 1182, in _send_request
    self.endheaders(body)
  File "C:\python34\lib\http\client.py", line 1133, in endheaders
    self._send_output(message_body)
  File "C:\python34\lib\http\client.py", line 963, in _send_output
    self.send(msg)
  File "C:\python34\lib\http\client.py", line 898, in send
    self.connect()
  File "C:\python34\lib\http\client.py", line 1279, in connect
    super().connect()
  File "C:\python34\lib\http\client.py", line 871, in connect
    self.timeout, self.source_address)
  File "C:\python34\lib\socket.py", line 498, in create_connection
    for res in getaddrinfo(host, port, 0, SOCK_STREAM):
  File "C:\python34\lib\socket.py", line 537, in getaddrinfo
    for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
socket.gaierror: [Errno 11001] getaddrinfo failed
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
  File "c:\pillow\winbuild\build_dep.py", line 300, in <module>
    extract_libs()
  File "c:\pillow\winbuild\build_dep.py", line 51, in extract_libs
    filename = fetch(lib['url'])
  File "c:\pillow\winbuild\fetch.py", line 12, in fetch
    content = urllib.request.urlopen(url).read()
  File "C:\python34\lib\urllib\request.py", line 161, in urlopen
    return opener.open(url, data, timeout)
  File "C:\python34\lib\urllib\request.py", line 470, in open
    response = meth(req, response)
  File "C:\python34\lib\urllib\request.py", line 580, in http_response
    'http', request, response, code, msg, hdrs)
  File "C:\python34\lib\urllib\request.py", line 502, in error
    result = self._call_chain(*args)
  File "C:\python34\lib\urllib\request.py", line 442, in _call_chain
    result = func(*args)
  File "C:\python34\lib\urllib\request.py", line 685, in http_error_302
    return self.parent.open(new, timeout=req.timeout)
  File "C:\python34\lib\urllib\request.py", line 464, in open
    response = self._open(req, data)
  File "C:\python34\lib\urllib\request.py", line 482, in _open
    '_open', req)
  File "C:\python34\lib\urllib\request.py", line 442, in _call_chain
    result = func(*args)
  File "C:\python34\lib\urllib\request.py", line 1226, in https_open
    context=self._context, check_hostname=self._check_hostname)
  File "C:\python34\lib\urllib\request.py", line 1185, in do_open
    raise URLError(err)
urllib.error.URLError: <urlopen error [Errno 11001] getaddrinfo failed>
c:\pillow\winbuild\build_deps.cmd : The term 'c:\pillow\winbuild\build_deps.cmd' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, 
verify that the path is correct and try again.
At line:8 char:3
+   c:\pillow\winbuild\build_deps.cmd
+   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (c:\pillow\winbuild\build_deps.cmd:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException
 
if ($env:PYTHON -eq "c:/msys64/mingw32")
{
  c:\msys64\usr\bin\bash -l -c c:\\pillow\\winbuild\\appveyor_build_msys2.sh
  Write-Host "through install"
  $host.SetShouldExit(0)
}
else
{
  & $env:PYTHON/$env:EXECUTABLE c:\pillow\winbuild\build.py
  $host.SetShouldExit(0)
}
Running 27
-- stderr --
The system cannot find the path specified.
warning: no files found matching '*.c'
```




Discussion:

Resolving patch:
diff --git a/winbuild/fetch.py b/winbuild/fetch.py
--- a/winbuild/fetch.py
+++ b/winbuild/fetch.py
@@ -9,7 +9,11 @@ def fetch(url):
 
     if not os.path.exists(name):
         print("Fetching", url)
-        content = urllib.request.urlopen(url).read()
+        try:
+            r = urllib.request.urlopen(url)
+        except urllib.error.URLError:
+            r = urllib.request.urlopen(url)
+        content = r.read()
         with open(name, 'wb') as fd:
             fd.write(content)
     return name


Test patch: