Repository: getpelican/pelican

Issue:
pelican-import wp-attach UnicodeEncodeError
Pelican-import assert when download Wordpress attach with accent on filename.

```
$ pelican-import --wpfile --wp-attach -o blog wordpress.2018-12-26.xml 
...
downloading Django-avancé.jpg
Traceback (most recent call last):
  File "/home/apapillon/workspace/website/env/bin/pelican-import", line 11, in <module>
    sys.exit(main())
  File "/home/apapillon/workspace/website/env/lib/python3.5/site-packages/pelican/tools/pelican_import.py", line 1023, in main
    attachments=attachments or None)
  File "/home/apapillon/workspace/website/env/lib/python3.5/site-packages/pelican/tools/pelican_import.py", line 795, in fields2pelican
    links = download_attachments(output_path, urls)
  File "/home/apapillon/workspace/website/env/lib/python3.5/site-packages/pelican/tools/pelican_import.py", line 739, in download_attachments
    urlretrieve(url, os.path.join(full_path, filename))
  File "/usr/lib/python3.5/urllib/request.py", line 188, in urlretrieve
    with contextlib.closing(urlopen(url, data)) as fp:
  File "/usr/lib/python3.5/urllib/request.py", line 163, in urlopen
    return opener.open(url, data, timeout)
  File "/usr/lib/python3.5/urllib/request.py", line 466, in open
    response = self._open(req, data)
  File "/usr/lib/python3.5/urllib/request.py", line 484, in _open
    '_open', req)
  File "/usr/lib/python3.5/urllib/request.py", line 444, in _call_chain
    result = func(*args)
  File "/usr/lib/python3.5/urllib/request.py", line 1297, in https_open
    context=self._context, check_hostname=self._check_hostname)
  File "/usr/lib/python3.5/urllib/request.py", line 1254, in do_open
    h.request(req.get_method(), req.selector, req.data, headers)
  File "/usr/lib/python3.5/http/client.py", line 1107, in request
    self._send_request(method, url, body, headers)
  File "/usr/lib/python3.5/http/client.py", line 1142, in _send_request
    self.putrequest(method, url, **skips)
  File "/usr/lib/python3.5/http/client.py", line 984, in putrequest
    self._output(request.encode('ascii'))
UnicodeEncodeError: 'ascii' codec can't encode character '\xe9' in position 49: ordinal not in range(128)
```


Discussion:
I resolve this issue with this patch :

```patch
--- pelican/tools/pelican_import.py-old	2018-12-26 10:56:50.705637454 +0100
+++ pelican/tools/pelican_import.py	2018-12-26 10:58:51.623449330 +0100
@@ -12,7 +12,7 @@
 from collections import defaultdict
 
 from six.moves.urllib.error import URLError
-from six.moves.urllib.parse import urlparse
+from six.moves.urllib.parse import urlparse, urlsplit, urlunsplit, quote
 from six.moves.urllib.request import urlretrieve
 
 # because logging.setLoggerClass has to be called before logging.getLogger
@@ -729,6 +729,12 @@
         full_path = os.path.join(output_path, localpath)
         if not os.path.exists(full_path):
             os.makedirs(full_path)
+
+        # Generate percent-encoded URL
+        scheme, netloc, path, query, fragment = urlsplit(url)
+        path = quote(path)
+        url = urlunsplit((scheme, netloc, path, query, fragment))
+
         print('downloading {}'.format(filename))
         try:
             urlretrieve(url, os.path.join(full_path, filename))
```
Hi, thanks for reporting the issue and your fix. Would you mind filing it as a pull request? :-)
I will create a PR for this.

Resolving patch:
diff --git a/pelican/tools/pelican_import.py b/pelican/tools/pelican_import.py
--- a/pelican/tools/pelican_import.py
+++ b/pelican/tools/pelican_import.py
@@ -12,7 +12,7 @@
 from collections import defaultdict
 
 from six.moves.urllib.error import URLError
-from six.moves.urllib.parse import urlparse
+from six.moves.urllib.parse import quote, urlparse, urlsplit, urlunsplit
 from six.moves.urllib.request import urlretrieve
 
 # because logging.setLoggerClass has to be called before logging.getLogger
@@ -727,6 +727,12 @@ def download_attachments(output_path, urls):
             if sys.platform != 'win32' or ':' not in item:
                 localpath = os.path.join(localpath, item)
         full_path = os.path.join(output_path, localpath)
+
+        # Generate percent-encoded URL
+        scheme, netloc, path, query, fragment = urlsplit(url)
+        path = quote(path)
+        url = urlunsplit((scheme, netloc, path, query, fragment))
+
         if not os.path.exists(full_path):
             os.makedirs(full_path)
         print('downloading {}'.format(filename))


Test patch: