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
Use progress bar in downloading File and FileSet #1620
Conversation
Codecov ReportAttention:
Additional details and impacted files@@ Coverage Diff @@
## dev/fetch-ui-parity #1620 +/- ##
=======================================================
- Coverage 76.58% 74.01% -2.58%
=======================================================
Files 292 292
Lines 14703 14429 -274
=======================================================
- Hits 11261 10679 -582
- Misses 3442 3750 +308
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. |
Additionally:
|
progress_bar: (bool or Type of progress bar, optional): progress bar to be used while downloading assets. | ||
If `None` or `True` the default tqdm-based progress bar will be used. | ||
If `False` no progress bar will be used. | ||
If a type of progress bar is passed, it will be used instead of the default one. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How would you recommend to instruct the end-user on how to accomplish this? Is it correct to say that they can define a class that inherits from ProgressBarCallback
and pass its type as the argument? (Asking also for docs purposes)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, just like in the example with click
in the docstrings. You can pass this ClickProgressBar
.
Maybe link it somehow?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very good; your example did make it super clear. Just wanted to double-check that I've got it right and that this alias didn't change anything on the user-end.
Co-authored-by: Sabine <sabine.nyholm@neptune.ai>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good!
All my comments are code quality related so nothing blocking :)
src/neptune/typing.py
Outdated
@@ -80,3 +84,6 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: | |||
@abc.abstractmethod | |||
def update(self, *, by: int, total: Optional[int] = None) -> None: | |||
... | |||
|
|||
|
|||
ProgressBarType: TypeAlias = Optional[Union[bool, Type[ProgressBarCallback]]] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suggest unwrapping ProgressBarType
from Optional
as its kinda unusual practice. I think that
def f(x: Optional[ProgressBarType] = None)
pass
is more clear then
def f(x: ProgressBarType = None)
pass
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point. Done :)
src/neptune/handler.py
Outdated
def download(self, destination: str = None) -> None: | ||
def download( | ||
self, | ||
destination: str = None, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
destination
should have type Optional[str]
if you are allowed to pass None.
Not sure why mypy is passing on that
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Interesting. I see that it's been here for a long time, so yeah - weird. Worth looking into that. Thanks for noticing! Won't hurt to correct it anyway I guess, so let me do that quickly ;)
with construct_progress_bar(progress_bar, "Fetching fileset...") as bar: | ||
with response: | ||
with open(target_file, "wb") as f: | ||
for chunk in response.iter_content(chunk_size=1024 * 1024): | ||
if chunk: | ||
f.write(chunk) | ||
bar.update(by=len(chunk), total=total_size) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
its getting a bit nested. There is cool python trick, you can actually use with
with multiple context managers with only one indent :))
total_size = int(response.headers.get("content-length", 0))
with (
construct_progress_bar(progress_bar, "Fetching file...") as bar,
response,
open(target_file, "wb") as f
):
for chunk in response.iter_content(chunk_size=1024 * 1024):
if chunk:
f.write(chunk)
bar.update(by=len(chunk), total=total_size)
its added in python 3.10 so not sure if we can use it tho :(
but there are other ways around it in pre 3.10 versions like
with A() as a, \
B() as b, \
C() as c:
doSomething(a,b,c)
more info: https://stackoverflow.com/questions/893333/multiple-variables-in-a-with-statement
python 3.10 doc: https://docs.python.org/3/whatsnew/3.10.html#parenthesized-context-managers
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thought of it too, but unfortunately, it is not compatible with lower python versions, so we cannot support that. I can leave a TODO though to update it once we have 3.10 as the minimum version, what do you think?
Also, a workaround here could be to use try-finally
syntax, but I'm not certain if we need that so much
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yep I think moving from python 3.7 to newer versions is crucial as we will keep running into issues like that.
1-st seems good, I'm not big fan of try-finally
approach (its only nesting at the end).
How about ExitStack have you seen that? Its supported since python 3.3
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Didn't know that. Looks promising :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done ;)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM! 🚀
Co-authored-by: Sabine <sabine.nyholm@neptune.ai>
Before submitting checklist