fixed percentage and mb/s view
This commit is contained in:
parent
f0b9d50f85
commit
b76ffbf656
@ -1,24 +1,5 @@
|
||||
{
|
||||
"pending": [
|
||||
{
|
||||
"id": "54533241-ed24-482f-85d7-c9218352ae7f",
|
||||
"serie_id": "highschool-dxd",
|
||||
"serie_name": "Highschool DxD",
|
||||
"episode": {
|
||||
"season": 4,
|
||||
"episode": 7,
|
||||
"title": null
|
||||
},
|
||||
"status": "pending",
|
||||
"priority": "normal",
|
||||
"added_at": "2025-11-01T14:30:56.882358Z",
|
||||
"started_at": null,
|
||||
"completed_at": null,
|
||||
"progress": null,
|
||||
"error": null,
|
||||
"retry_count": 0,
|
||||
"source_url": null
|
||||
},
|
||||
{
|
||||
"id": "7e80b3c4-6837-4af7-bea3-ca037df594ce",
|
||||
"serie_id": "highschool-dxd",
|
||||
@ -1485,5 +1466,5 @@
|
||||
],
|
||||
"active": [],
|
||||
"failed": [],
|
||||
"timestamp": "2025-11-01T15:42:52.117823+00:00"
|
||||
"timestamp": "2025-11-01T15:48:49.007428+00:00"
|
||||
}
|
||||
@ -253,15 +253,48 @@ class SeriesApp:
|
||||
if isinstance(progress_info, dict):
|
||||
# Calculate percentage based on downloaded/total bytes
|
||||
downloaded = progress_info.get('downloaded_bytes', 0)
|
||||
total = progress_info.get('total_bytes') or progress_info.get('total_bytes_estimate', 0)
|
||||
total_bytes = (
|
||||
progress_info.get('total_bytes')
|
||||
or progress_info.get('total_bytes_estimate', 0)
|
||||
)
|
||||
|
||||
if total > 0:
|
||||
progress = (downloaded / total) * 100
|
||||
if total_bytes > 0:
|
||||
progress = (downloaded / total_bytes) * 100
|
||||
else:
|
||||
progress = 0
|
||||
|
||||
# Extract speed and ETA from yt-dlp progress dict
|
||||
speed = progress_info.get('speed', 0) # bytes/sec
|
||||
eta = progress_info.get('eta') # seconds
|
||||
|
||||
# Convert to expected format for web API callback
|
||||
# Web API expects: percent, downloaded_mb, total_mb,
|
||||
# speed_mbps, eta_seconds
|
||||
web_progress_dict = {
|
||||
'percent': progress,
|
||||
# Convert bytes to MB
|
||||
'downloaded_mb': downloaded / (1024 * 1024),
|
||||
'total_mb': (
|
||||
total_bytes / (1024 * 1024)
|
||||
if total_bytes > 0
|
||||
else None
|
||||
),
|
||||
# Convert bytes/sec to MB/sec
|
||||
'speed_mbps': (
|
||||
speed / (1024 * 1024) if speed else None
|
||||
),
|
||||
'eta_seconds': eta,
|
||||
}
|
||||
else:
|
||||
# Fallback for old-style float progress
|
||||
progress = float(progress_info)
|
||||
web_progress_dict = {
|
||||
'percent': progress,
|
||||
'downloaded_mb': 0.0,
|
||||
'total_mb': None,
|
||||
'speed_mbps': None,
|
||||
'eta_seconds': None,
|
||||
}
|
||||
|
||||
# Notify progress via new callback system
|
||||
self._callback_manager.notify_progress(
|
||||
@ -281,13 +314,14 @@ class SeriesApp:
|
||||
)
|
||||
)
|
||||
|
||||
# Call legacy callback if provided
|
||||
# Call callback with web API format
|
||||
# (dict with detailed progress info)
|
||||
if callback:
|
||||
callback(progress)
|
||||
callback(web_progress_dict)
|
||||
|
||||
# Propagate progress into the legacy callback chain so existing
|
||||
# UI surfaces continue to receive updates without rewriting the
|
||||
# old interfaces.
|
||||
# Propagate progress into the legacy callback chain so
|
||||
# existing UI surfaces continue to receive updates without
|
||||
# rewriting the old interfaces.
|
||||
# Call legacy progress_callback if provided
|
||||
if self.progress_callback:
|
||||
self.progress_callback(ProgressInfo(
|
||||
|
||||
@ -470,6 +470,82 @@ class TestBroadcastCallbacks:
|
||||
# Verify callback was called
|
||||
mock_callback.assert_called()
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_progress_callback_format(self, download_service):
|
||||
"""Test that progress callback receives correct data format."""
|
||||
# Set up a mock callback to capture progress updates
|
||||
progress_updates = []
|
||||
|
||||
def capture_progress(progress_data: dict):
|
||||
progress_updates.append(progress_data)
|
||||
|
||||
# Mock download to simulate progress
|
||||
async def mock_download_with_progress(*args, **kwargs):
|
||||
# Get the callback from kwargs
|
||||
callback = kwargs.get('callback')
|
||||
if callback:
|
||||
# Simulate progress updates with the expected format
|
||||
callback({
|
||||
'percent': 50.0,
|
||||
'downloaded_mb': 250.5,
|
||||
'total_mb': 501.0,
|
||||
'speed_mbps': 5.2,
|
||||
'eta_seconds': 48,
|
||||
})
|
||||
return True
|
||||
|
||||
download_service._anime_service.download = mock_download_with_progress
|
||||
|
||||
# Add an item to the queue
|
||||
await download_service.add_to_queue(
|
||||
serie_id="series-1",
|
||||
serie_name="Test Series",
|
||||
episodes=[EpisodeIdentifier(season=1, episode=1)],
|
||||
)
|
||||
|
||||
# Process the download
|
||||
item = download_service._pending_queue.popleft()
|
||||
del download_service._pending_items_by_id[item.id]
|
||||
|
||||
# Replace the progress callback with our capture function
|
||||
original_callback = download_service._create_progress_callback
|
||||
|
||||
def wrapper(item):
|
||||
callback = original_callback(item)
|
||||
|
||||
def wrapped_callback(data):
|
||||
capture_progress(data)
|
||||
callback(data)
|
||||
|
||||
return wrapped_callback
|
||||
|
||||
download_service._create_progress_callback = wrapper
|
||||
|
||||
await download_service._process_download(item)
|
||||
|
||||
# Verify progress callback was called with correct format
|
||||
assert len(progress_updates) > 0
|
||||
progress_data = progress_updates[0]
|
||||
|
||||
# Check all expected keys are present
|
||||
assert 'percent' in progress_data
|
||||
assert 'downloaded_mb' in progress_data
|
||||
assert 'total_mb' in progress_data
|
||||
assert 'speed_mbps' in progress_data
|
||||
assert 'eta_seconds' in progress_data
|
||||
|
||||
# Verify values are of correct type
|
||||
assert isinstance(progress_data['percent'], (int, float))
|
||||
assert isinstance(progress_data['downloaded_mb'], (int, float))
|
||||
assert (
|
||||
progress_data['total_mb'] is None
|
||||
or isinstance(progress_data['total_mb'], (int, float))
|
||||
)
|
||||
assert (
|
||||
progress_data['speed_mbps'] is None
|
||||
or isinstance(progress_data['speed_mbps'], (int, float))
|
||||
)
|
||||
|
||||
|
||||
class TestServiceLifecycle:
|
||||
"""Test service start and stop operations."""
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user