Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fido.fetch now accepts pathlib.Path objects #2559

Merged
merged 11 commits into from
Mar 22, 2018

Conversation

vn-ki
Copy link
Member

@vn-ki vn-ki commented Mar 13, 2018

Closes #2400.

@pep8speaks
Copy link

pep8speaks commented Mar 13, 2018

Hello @vn-ki! Thanks for updating the PR.

Cheers ! There are no PEP8 issues in this Pull Request. 🍻

Comment last updated on March 21, 2018 at 20:18 Hours UTC

@@ -336,6 +337,15 @@ def fetch(self, qres, path=None, error_callback=None, **kwargs):
-------
Results Object
"""
# Check for type of path
if isinstance(path, str) or path is None:
pass
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need this if statement?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also I wonder why the documentation string for this is empty of the keywords.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is to ensure that the path which is None, str or pathlib.Path goes past. Any other type would raise a TypeError

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could the if,elif,else block be refactored to avoid having the if:pass part?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see how we can go past not checking whether path is str or None.

If you have some suggestion on how to do this, can you share?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Cadair might

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I haven't tested this, so it probably has several syntax issues, but something like this maybe:

if path is not None:
    if isinstance(path, pathlib.Path) and HAS_PATHLIB:
        path = str(path.absolute())
    elif not isinstance(path, str): # need py2 fix for six here?
        raise TypeError("path keyword is invalid. Should be a 'str' or 'pathlib.Path'.\
                         Got '{}'.".format(type(path)))

I think if we check for str we need to use six to ensure python 2 compatibility.

assert len(response1) == qr._numfile
path2 = pathlib.Path('.')
response2 = Fido.fetch(qr, path=path2)
assert len(response2) == qr._numfile
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if Fido.fetch doesn't already have tests for this somewhere else. Not sure that this should be added just under an eve test.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for not looking properly. Just found the real test under net.tests.test_fido

@nabobalis nabobalis added net Affects the net submodule No Changelog Entry Needed labels Mar 13, 2018
elif isinstance(path, pathlib.Path):
path = str(path.absolute())
else:
err = 'path should be either pathlib.Path object or str object. '\
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure I like using the word object here.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is a 'word' object?

@@ -97,6 +98,14 @@ def test_save_path():
assert target_dir in f
assert "eve{}0".format(os.path.sep) in f

with tempfile.TemporaryDirectory() as target_dir:
qr = Fido.search(a.Instrument('EVE'), a.Time("2016/10/01", "2016/10/02"), a.Level(0))
path = pathlib.Path(os.path.join(target_dir, "{instrument}"+os.path.sep+"{level}"))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do pathlib.Path need to use os.path.join?
I had thought that pathlib.Path was meant to handle that.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missed it while copy-pasting!

@@ -97,6 +98,14 @@ def test_save_path():
assert target_dir in f
assert "eve{}0".format(os.path.sep) in f

with tempfile.TemporaryDirectory() as target_dir:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do wonder if we should split it into two tests.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are downloading the same files. So I figured downloading the files into a different directory would be the best option to test for flaws.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well in that case, do we need to redo the Fido.search part? Could we not just fetch it twice one after the other?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should I split it into two tests? @nabobalis

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we not just fetch the files twice with two different paths?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now the searching is only done once.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add a comment somewhere to just state what the difference in the two parts of the test are.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is in a different test now! ^_^

Add changelog
Add keyword description in docstring
Change error message yo requested format
Remove recurrent os.path.join
@vn-ki vn-ki force-pushed the accept-pathlibPath-objects branch from b31ecb9 to 53be326 Compare March 13, 2018 12:58
import pathlib
HAS_PATHLIB = True
except ImportError:
HAS_PATHLIB = False
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would we not need this for the main file as well?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

instead of doing this we should use pytest.importorskip("pathlib") in the test

@vn-ki vn-ki force-pushed the accept-pathlibPath-objects branch from eab6efe to d767404 Compare March 13, 2018 13:53
@nabobalis
Copy link
Contributor

Looks my logic doesn't work:

TypeError: path should be either 'pathlib.Path' or 'str'. Got '<class 'NoneType'>'.


Exception occurred:
  File "/home/circleci/project/build/lib.linux-x86_64-3.6/sunpy/net/dataretriever/client.py", line 360, in fetch
    raise TypeError(err)

Returns
-------
Results Object
"""
# Check for type of path
if path is not None and HAS_PATHLIB and isinstance(path, pathlib.Path):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You want if path is not None to encompass the other if/elif

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops! Sorry!

@vn-ki vn-ki force-pushed the accept-pathlibPath-objects branch from 9f0808f to d66b2e3 Compare March 14, 2018 12:58
@@ -8,6 +8,15 @@
from abc import ABCMeta
from collections import OrderedDict, namedtuple
from functools import partial
import six
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You probably want this to be import sunpy.extern.six.

@nabobalis nabobalis requested a review from Cadair March 14, 2018 13:10
@vn-ki vn-ki force-pushed the accept-pathlibPath-objects branch from d66b2e3 to 3b226ce Compare March 14, 2018 13:17
files = Fido.fetch(qr, path=os.path.join(target_dir, "{instrument}"+os.path.sep+"{level}"))
for f in files:
assert target_dir in f
assert "eve{}0".format(os.path.sep) in f

# Test when path is pathlib.Path
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this go in its own test? It would be easier to manage and control when one or the other fails.

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}"))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

os.path.sep is not needed there... unless that's what you want to test. os.path.join does it for you.

files = Fido.fetch(qr, path=os.path.join(target_dir, "{instrument}", "{level}"))

# Test when path is pathlib.Path
if HAS_PATHLIB:
with tempfile.TemporaryDirectory() as target_dir:
path = pathlib.Path(target_dir, "{instrument}"+os.path.sep+"{level}")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You don't need it here either, pathlib will add the sep for each argument:

path = pathlib.Path(target_dir, "{instrument}", "{level}")

Copy link
Contributor

@nabobalis nabobalis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me.

@nabobalis
Copy link
Contributor

This also now fixes the two known test failures on the online tests.

@nabobalis nabobalis added this to the 0.9 milestone Mar 16, 2018
@vn-ki
Copy link
Member Author

vn-ki commented Mar 18, 2018

This can be merged now, right?

@nabobalis
Copy link
Contributor

I have requested a review and I am waiting on that before I merge this.

But as far as I am concerned, yes it can be merged in.

@@ -9,6 +9,14 @@
from collections import OrderedDict, namedtuple
from functools import partial

# Remove in 1.0
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you modify this comment to start with python 3: as I have been using that in a few places for post-0.9 grepping.

import pathlib
HAS_PATHLIB = True
except ImportError:
HAS_PATHLIB = False
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

instead of doing this we should use pytest.importorskip("pathlib") in the test


@pytest.mark.remote_data
def test_save_path_pathlib():
pathlib = pytest.importorskip('pathlib')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this not a decorator?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no, decorators are run at import time.

@nabobalis
Copy link
Contributor

We updated the Changelog, you will need to fix the conflict now.

@Cadair Cadair merged commit 4cfae7d into sunpy:master Mar 22, 2018
@vn-ki vn-ki deleted the accept-pathlibPath-objects branch May 11, 2018 18:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
net Affects the net submodule
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants