Repository: mitmproxy/mitmproxy

Issue:
Improve Rendering of the Size Column
#### Problem Description

The size column currently renders really badly:

![image](https://user-images.githubusercontent.com/1019198/126454966-10eda16c-518f-41da-a884-f0ca8ee03058.png)

`….64k` clearly is not what the user is interested in, something like `204k` would be much more useful.

#### Steps to reproduce the behavior:
1. Access a file with a size that is larger than 10kb, but smaller than 1MB.

#### Proposed fix

In short, we want to have a string here with a maximum length of 5 characters so that it does not get truncated. My proposal would be to just round to the nearest integer, e.g. `204k` instead of `204.64k`.

The relevant code is here:
https://github.com/mitmproxy/mitmproxy/blob/e270399a3eba7b3212bf7325beaa50e159a7ca0a/mitmproxy/utils/human.py#L18-L27
and the accompanying tests are here:
https://github.com/mitmproxy/mitmproxy/blob/0ca458fd6475ee48728147f3b529467a75e912a4/test/mitmproxy/utils/test_human.py#L28-L34

Fixing this should be really straightforward, so I'm leaving this open for new contributors. 😃 

#### System Information

```
Mitmproxy: 8.0.0.dev (+15, commit e270399)
Python:    3.9.4
OpenSSL:   OpenSSL 1.1.1f  31 Mar 2020
Platform:  Linux-4.4.0-19041-Microsoft-x86_64-with-glibc2.31
```


Discussion:
Hi, I'm fairly new to contributing to open source in general and I'd be happy to work on this when I can.
@aaron-tan: Excellent! We have a CONTRIBUTING.md in the repo that details how to set up a dev environment and run the tests. If you have any (stupid) questions please don't hesitate to ask here or ping me or anyone else on Slack! :)
Hi, I'm trying to reproduce the behavior but I don't seem able to. Here's a screenshot of what I see on my mitmproxy.

![Screenshot_2021-08-02_21-24-51](https://user-images.githubusercontent.com/70739609/127854818-a272b162-cf9f-4753-87e8-bb4af3c45076.png)

I wasn't really sure what you meant in the steps to reproduce, I assumed you were talking about the flows so I tried getting a flow that fit the criteria but it's still displayed in full. Do you mind elaborating on the steps to reproduce?
You need to increase the width of your console window (or decrease the font size) so that mitmproxy switches to a tabular view. :)

Resolving patch:
diff --git a/mitmproxy/utils/human.py b/mitmproxy/utils/human.py
--- a/mitmproxy/utils/human.py
+++ b/mitmproxy/utils/human.py
@@ -1,30 +1,34 @@
 import datetime
+import functools
 import ipaddress
 import time
-import functools
 import typing
 
-SIZE_TABLE = [
-    ("b", 1024 ** 0),
-    ("k", 1024 ** 1),
-    ("m", 1024 ** 2),
-    ("g", 1024 ** 3),
-    ("t", 1024 ** 4),
-]
-
-SIZE_UNITS = dict(SIZE_TABLE)
-
-
-def pretty_size(size):
-    for bottom, top in zip(SIZE_TABLE, SIZE_TABLE[1:]):
-        if bottom[1] <= size < top[1]:
-            suf = bottom[0]
-            lim = bottom[1]
-            x = round(size / lim, 2)
-            if x == int(x):
-                x = int(x)
-            return str(x) + suf
-    return "{}{}".format(size, SIZE_TABLE[0][0])
+
+SIZE_UNITS = {
+    "b": 1024 ** 0,
+    "k": 1024 ** 1,
+    "m": 1024 ** 2,
+    "g": 1024 ** 3,
+    "t": 1024 ** 4,
+}
+
+
+def pretty_size(size: int) -> str:
+    """Convert a number of bytes into a human-readable string.
+
+    len(return value) <= 5 always holds true.
+    """
+    s: float = size  # type cast for mypy
+    if s < 1024:
+        return f"{s}b"
+    for suffix in ["k", "m", "g", "t"]:
+        s /= 1024
+        if s < 99.95:
+            return f"{s:.1f}{suffix}"
+        if s < 1024 or suffix == "t":
+            return f"{s:.0f}{suffix}"
+    raise AssertionError
 
 
 @functools.lru_cache()


Test patch:
diff --git a/test/mitmproxy/utils/test_human.py b/test/mitmproxy/utils/test_human.py
--- a/test/mitmproxy/utils/test_human.py
+++ b/test/mitmproxy/utils/test_human.py
@@ -28,10 +28,11 @@ def test_parse_size():
 def test_pretty_size():
     assert human.pretty_size(0) == "0b"
     assert human.pretty_size(100) == "100b"
-    assert human.pretty_size(1024) == "1k"
-    assert human.pretty_size(1024 + (1024 / 2.0)) == "1.5k"
-    assert human.pretty_size(1024 * 1024) == "1m"
-    assert human.pretty_size(10 * 1024 * 1024) == "10m"
+    assert human.pretty_size(1024) == "1.0k"
+    assert human.pretty_size(1024 + 512) == "1.5k"
+    assert human.pretty_size(1024 * 1024) == "1.0m"
+    assert human.pretty_size(10 * 1024 * 1024) == "10.0m"
+    assert human.pretty_size(100 * 1024 * 1024) == "100m"
 
 
 def test_pretty_duration():