diffoscope fails with python-progressbar 4.3.0 installed
Introduction
Hi,
Arch Linux recently updated python-progressbar from 4.2.0 to 4.3.2. I've been building diffoscope for unrelated reasons and during checking, the below error occurred.
=================================== FAILURES ===================================
________________________________ test_progress _________________________________
capsys = <_pytest.capture.CaptureFixture object at 0x7f2468118710>
progressbar_err = ''
@skip_unless_module_exists("progressbar")
def test_progress(capsys, progressbar_err):
ret, _, err = run(capsys, TEST_TAR1_PATH, TEST_TAR2_PATH, "--progress")
> assert ret == 1
E assert 2 == 1
tests/test_progress.py:69: AssertionError
=========================== short test summary info ============================
FAILED tests/test_progress.py::test_progress - assert 2 == 1
===== 1 failed, 620 passed, 91 skipped, 5 deselected, 1 xpassed in 43.06s ======
Rebuilding with 4.2.0 (the previous Arch package) worked fine, 4.3.0 and 4.3.1 failed as above.
Description
Running diffoscope with python-progressbar 4.3.0 or higher leads to a runtime failure:
Traceback (most recent call last):
File "/usr/lib/python3.11/site-packages/diffoscope/main.py", line 762, in main
log_handler = ProgressManager().setup(parsed_args)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3.11/site-packages/diffoscope/progress.py", line 83, in setup
bar = ProgressBar()
^^^^^^^^^^^^^
File "/usr/lib/python3.11/site-packages/diffoscope/progress.py", line 258, in __init__
Message(),
^^^^^^^^^
TypeError: Can't instantiate abstract class Message with abstract method __call__
Analysis
The mentioned class Message in diffoscope/progress.py inherits from WidgetsBase in progressbar.
The immediate reason for the error seems to be the commit python-progressbar@633585 which makes WidgetsBase a true abstract class, so Message - which does not implement the abstract __call__ method - becomes an abstract class too. Previously, the Python runtime wasn't able to detect the class as an abstract one, so it didn't fail, i.e. no intended behaviour has changed, speaking from progressbar.
The issue lies further back. The Message class implements update, seemingly overriding something, eventhough there is no such abstract method defined. That looks like a relic from an earlier version of progressbar. The update method was renamed to __call__ in python-progressbar@12df6a which also introduced the WidgetBase as a rename of Widget. That must have led to issues, right? It has, and the switch to WidgetBase was fixed in 8e176158. The change update->__call__ was missed however, so it stands to reason that this particular functionality didn't work correctly since then as the latter is just an empty call (for reference, the relevant code in progressbar is python-progressbar:progressbar/bar.py#L334).
Possible solutions
From above analysis, the simplest change is renaming the update method here to __call__. Further fixes might be necessary given that this part of the code wasn't run for 6 years.
System
OS: Arch Linux
Kernel: Linux 6.6.9.arch1-1
diffoscope: 253-2
python-progressbar (working): 4.2.0-3
python-progressbar (failing): 4.3.0, 4.3.1, 4.3.2-1
Does my analysis seem reasonable?
If there are any questions, I'll be glad to answer.
-- Vekhir