You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
124 lines
3.1 KiB
Python
124 lines
3.1 KiB
Python
# Copyright (C) 2022 Intel Corporation
|
|
# Copyright (C) 2022 CVAT.ai Corporation
|
|
#
|
|
# SPDX-License-Identifier: MIT
|
|
|
|
from __future__ import annotations
|
|
|
|
import math
|
|
from typing import Iterable, Optional, Tuple, TypeVar
|
|
|
|
T = TypeVar("T")
|
|
|
|
|
|
class ProgressReporter:
|
|
"""
|
|
Only one set of methods must be called:
|
|
- start - report_status / advance - finish
|
|
- iter
|
|
- split
|
|
|
|
This class is supposed to manage the state of children progress bars
|
|
and release of their resources, if necessary.
|
|
"""
|
|
|
|
@property
|
|
def period(self) -> float:
|
|
"""
|
|
Returns reporting period.
|
|
|
|
For example, 0.1 would mean every 10%.
|
|
"""
|
|
raise NotImplementedError
|
|
|
|
def start(self, total: int, *, desc: Optional[str] = None):
|
|
"""Initializes the progress bar"""
|
|
raise NotImplementedError
|
|
|
|
def report_status(self, progress: int):
|
|
"""Updates the progress bar"""
|
|
raise NotImplementedError
|
|
|
|
def advance(self, delta: int):
|
|
"""Updates the progress bar"""
|
|
raise NotImplementedError
|
|
|
|
def finish(self):
|
|
"""Finishes the progress bar"""
|
|
pass # pylint: disable=unnecessary-pass
|
|
|
|
def iter(
|
|
self,
|
|
iterable: Iterable[T],
|
|
*,
|
|
total: Optional[int] = None,
|
|
desc: Optional[str] = None,
|
|
) -> Iterable[T]:
|
|
"""
|
|
Traverses the iterable and reports progress simultaneously.
|
|
|
|
Starts and finishes the progress bar automatically.
|
|
|
|
Args:
|
|
iterable: An iterable to be traversed
|
|
total: The expected number of iterations. If not provided, will
|
|
try to use iterable.__len__.
|
|
desc: The status message
|
|
|
|
Returns:
|
|
An iterable over elements of the input sequence
|
|
"""
|
|
|
|
if total is None and hasattr(iterable, "__len__"):
|
|
total = len(iterable)
|
|
|
|
self.start(total, desc=desc)
|
|
|
|
if total:
|
|
display_step = math.ceil(total * self.period)
|
|
|
|
for i, elem in enumerate(iterable):
|
|
if not total or i % display_step == 0:
|
|
self.report_status(i)
|
|
|
|
yield elem
|
|
|
|
self.finish()
|
|
|
|
def split(self, count: int) -> Tuple[ProgressReporter, ...]:
|
|
"""
|
|
Splits the progress bar into few independent parts.
|
|
In case of 0 must return an empty tuple.
|
|
|
|
This class is supposed to manage the state of children progress bars
|
|
and release of their resources, if necessary.
|
|
"""
|
|
raise NotImplementedError
|
|
|
|
|
|
class NullProgressReporter(ProgressReporter):
|
|
@property
|
|
def period(self) -> float:
|
|
return 0
|
|
|
|
def start(self, total: int, *, desc: Optional[str] = None):
|
|
pass
|
|
|
|
def report_status(self, progress: int):
|
|
pass
|
|
|
|
def advance(self, delta: int):
|
|
pass
|
|
|
|
def iter(
|
|
self,
|
|
iterable: Iterable[T],
|
|
*,
|
|
total: Optional[int] = None,
|
|
desc: Optional[str] = None,
|
|
) -> Iterable[T]:
|
|
yield from iterable
|
|
|
|
def split(self, count: int) -> Tuple[ProgressReporter]:
|
|
return (self,) * count
|