python-progressbar icon indicating copy to clipboard operation
python-progressbar copied to clipboard

OSError exception from AbsoluteETA on Windows CPython

Open jdykstra opened this issue 1 year ago • 1 comments

Description

A progressbar containing an AbsoluteETA widget intermittently crashes with an OSError on Windows CPython.

Code

 File "R:\downloadImages\downloadImages.py", line 246, in update
    self.bar.update(self.alreadyCopied)
  File "R:\python-progressbar\progressbar\bar.py", line 909, in update
    self.start()
  File "R:\python-progressbar\progressbar\bar.py", line 1012, in start
    self.update(self.min_value, force=True)
  File "R:\python-progressbar\progressbar\bar.py", line 940, in update
    self._update_parents(value)
  File "R:\python-progressbar\progressbar\bar.py", line 959, in _update_parents
    StdRedirectMixin.update(self, value=value)  # type: ignore
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "R:\python-progressbar\progressbar\bar.py", line 462, in update
    DefaultFdMixin.update(self, value=value)
  File "R:\python-progressbar\progressbar\bar.py", line 305, in update
    line: str = converters.to_unicode(self._format_line())
                                      ^^^^^^^^^^^^^^^^^^^
  File "R:\python-progressbar\progressbar\bar.py", line 336, in _format_line
    widgets = ''.join(self._to_unicode(self._format_widgets()))
                                       ^^^^^^^^^^^^^^^^^^^^^^
  File "R:\python-progressbar\progressbar\bar.py", line 362, in _format_widgets
    widget_output = converters.to_unicode(widget(self, data))
                                          ^^^^^^^^^^^^^^^^^^
  File "R:\python-progressbar\progressbar\widgets.py", line 564, in __call__
    data['eta'] = utils.format_time(data['eta_seconds'])
                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "c:\Users\jwd\AppData\Local\Programs\Python\Python312\Lib\site-packages\python_utils\time.py", line 124, in format_time
    seconds = timestamp.timestamp()
              ^^^^^^^^^^^^^^^^^^^^^

Versions

CPython 3.12.3, Windows 11, progressbar 4.4.2.

Problem is not reproducible with CPython on current MacOS and Linux distributions. (C Library-dependent--see below)

Analysis

The datetime.timestamp() implementation on Windows CPython raises OSError when it's called on a very large datetime:

>>> from datetime import datetime
>>> dt = datetime.strptime("8362-03-01 09:53:14", "%Y-%m-%d %H:%M:%S")
>>> dt.timestamp()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OSError: [Errno 22] Invalid argument

This can happen if the initialization of data['elapsed'] at bar.py:758 comes up with a small non-zero value. (The cases I've seen are all values of 1 us.) The results of that calculation vary with CPU contention, etc., thus making the problem intermittent.

I've successfully tested a fix of adding OSError to the contextlib.suppress() call at widgets.py:547. However, I've been unable to craft a test that triggers the problem. Will you accept a pull request anyway?

jdykstra avatar Jun 01 '24 19:06 jdykstra

Even without a test it would still be useful to have this fixed, thank you for the research!

wolph avatar Jun 01 '24 19:06 wolph