Repository: sunpy/sunpy

Issue:
Fido.fetch should accept pathlib.Path objects.
i.e.:

```python
path = Path('/home/stuart/sunpy/data/jsocflare/')
results = Fido.search(...)
files = Fido.fetch(results, path=path)
```


Discussion:
Would love to work on this.
@jnanjekye feel free. Ask here or in our matrix channel if you need any pointers.
@Cadair If it is still not assigned, I would love to give it a try. Should I start?

Resolving patch:
diff --git a/sunpy/net/dataretriever/client.py b/sunpy/net/dataretriever/client.py
--- a/sunpy/net/dataretriever/client.py
+++ b/sunpy/net/dataretriever/client.py
@@ -9,6 +9,14 @@
 from collections import OrderedDict, namedtuple
 from functools import partial
 
+# Python 3:
+# Remove in 1.0: Py2 does not have pathlib
+try:
+    import pathlib
+    HAS_PATHLIB = True
+except ImportError:
+    HAS_PATHLIB = False
+
 import numpy as np
 import astropy.table
 import astropy.units as u
@@ -332,10 +340,24 @@ def fetch(self, qres, path=None, error_callback=None, **kwargs):
         qres : `~sunpy.net.dataretriever.QueryResponse`
             Results to download.
 
+        path : string or pathlib.Path
+            Path to the download directory
+
+        error_callback : Function
+            Callback function for error during downloads
+
         Returns
         -------
         Results Object
         """
+        # Check for type of path
+        if path is not None:
+            if HAS_PATHLIB and isinstance(path, pathlib.Path):
+                path = str(path.absolute())
+            elif not isinstance(path, six.string_types):
+                err = "path should be either 'pathlib.Path' or 'str'. "\
+                    "Got '{}'.".format(type(path))
+                raise TypeError(err)
 
         urls = [qrblock.url for qrblock in qres]
 


Test patch:
diff --git a/sunpy/database/tests/test_database.py b/sunpy/database/tests/test_database.py
--- a/sunpy/database/tests/test_database.py
+++ b/sunpy/database/tests/test_database.py
@@ -912,7 +912,13 @@ def test_fetch_duplicates(database, download_query, tmpdir):
     database.default_waveunit = 'angstrom'
     database.fetch(
         *download_query, path=str(tmpdir.join('{file}.fits')), progress=True)
-    assert len(database) == 4
+    # FIXME The len(database) changes with time b/w 2 and 4.
+    # Temp fix is  len(db) in (2, 4) until we find a better solution
+
+    # 42 is the answer to life, the universe and everything ...
+    # ... and this is no coincidence. So ...
+    assert str(len(database)) in '42'
+
     download_time = database[0].download_time
     database.fetch(*download_query, path=str(tmpdir.join('{file}.fits')))
     # Make this resilitent to vso changes while we chase this up with VSO 2018-03-07
@@ -932,10 +938,10 @@ def test_fetch(database, download_query, tmpdir):
     assert len(database) == 0
     database.default_waveunit = 'angstrom'
     database.fetch(*download_query, path=str(tmpdir.join('{file}.fits')))
-    assert len(database) == 4
+    assert len(database) in (2, 4)
     download_time = database[0].download_time
     database.fetch(*download_query, path=str(tmpdir.join('{file}.fits')))
-    assert len(database) == 4
+    assert len(database) in (2, 4)
     assert database[0].download_time == download_time
 
 
diff --git a/sunpy/net/tests/test_fido.py b/sunpy/net/tests/test_fido.py
--- a/sunpy/net/tests/test_fido.py
+++ b/sunpy/net/tests/test_fido.py
@@ -90,9 +90,25 @@ def check_response(query, unifiedresp):
 
 @pytest.mark.remote_data
 def test_save_path():
+    qr = Fido.search(a.Instrument('EVE'), a.Time("2016/10/01", "2016/10/02"), a.Level(0))
+
+    # Test when path is str
+    with tempfile.TemporaryDirectory() as target_dir:
+        files = Fido.fetch(qr, path=os.path.join(target_dir, "{instrument}", "{level}"))
+        for f in files:
+            assert target_dir in f
+            assert "eve{}0".format(os.path.sep) in f
+
+
+@pytest.mark.remote_data
+def test_save_path_pathlib():
+    pathlib = pytest.importorskip('pathlib')
+    qr = Fido.search(a.Instrument('EVE'), a.Time("2016/10/01", "2016/10/02"), a.Level(0))
+
+    # Test when path is pathlib.Path
     with tempfile.TemporaryDirectory() as target_dir:
-        qr = Fido.search(a.Instrument('EVE'), a.Time("2016/10/01", "2016/10/02"), a.Level(0))
-        files = Fido.fetch(qr, path=os.path.join(target_dir, "{instrument}"+os.path.sep+"{level}"))
+        path = pathlib.Path(target_dir, "{instrument}", "{level}")
+        files = Fido.fetch(qr, path=path)
         for f in files:
             assert target_dir in f
             assert "eve{}0".format(os.path.sep) in f