Queer European MD passionate about IT
Browse Source

Prevent bad behaviour when terminal windows is too small

Davte 5 năm trước cách đây
mục cha
commit
63626b329f
2 tập tin đã thay đổi với 48 bổ sung6 xóa
  1. 1 0
      filebridging/client.py
  2. 47 6
      filebridging/utilities.py

+ 1 - 0
filebridging/client.py

@@ -485,6 +485,7 @@ class Client:
             )
         loop.close()
 
+    @utilities.timed_action(interval=0.4)
     def print_progress_bar(self, progress: int, bytes_: int):
         """Print client progress bar.
 

+ 47 - 6
filebridging/utilities.py

@@ -1,8 +1,10 @@
 """Useful functions."""
-
+import datetime
 import logging
+import shutil
 import signal
 import sys
+from typing import Union
 
 units_of_measurements = {
     1: 'bytes',
@@ -35,16 +37,55 @@ def print_progress_bar(prefix='',
                        progress=0,
                        scale=10):
     progress_showed = (progress // scale) * scale
+    line_width, _ = shutil.get_terminal_size()
+    line = (f"{prefix}"
+            f"{done_symbol * (progress_showed // scale)}"
+            f"{pending_symbol * ((100 - progress_showed) // scale)}\t"
+            f"{progress}%"
+            f"{suffix}      ")
+    line = line.replace('\t', ' ' * 4)
+    if line_width < 5:
+        line = '.' * line_width
+    elif len(line) > line_width:
+        line = line[:line_width-5] + '[...]'
     sys.stdout.write(
-        f"{prefix}"
-        f"{done_symbol * (progress_showed // scale)}"
-        f"{pending_symbol * ((100 - progress_showed) // scale)}\t"
-        f"{progress}%"
-        f"{suffix}      \r"
+        line + '\r'
     )
     sys.stdout.flush()
 
 
+def timed_action(interval: Union[int, float, datetime.timedelta] = None):
+    """Do not perform decorated action before `interval`.
+
+    `interval` may be an int number of seconds or a datetime.timedelta object.
+    Usage:
+    @timed_action(1)
+    def print_sum(a, b):
+        print(a + b)
+
+    for i, j in enumerate(range(1000, 10000, 10)):
+        print_sum(i, j)
+        time.sleep(0.1)
+    """
+    now = datetime.datetime.now
+    last_call = now()
+    if type(interval) in (int, float):
+        timedelta = datetime.timedelta(seconds=interval)
+    elif isinstance(interval, datetime.timedelta):
+        timedelta = interval
+
+    def timer(function_to_time):
+        def timed_function(*args, **kwargs):
+            nonlocal last_call
+            if now() > last_call + timedelta:
+                last_call = now()
+                return function_to_time(*args, **kwargs)
+            return
+        return timed_function
+
+    return timer
+
+
 def timed_input(message: str = None,
                 timeout: int = 5):
     class TimeoutExpired(Exception):