progress-table 0.1.26__tar.gz → 1.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {progress-table-0.1.26 → progress-table-1.0.0}/PKG-INFO +25 -15
- {progress-table-0.1.26 → progress-table-1.0.0}/README.md +24 -14
- progress-table-1.0.0/progress_table/__init__.py +8 -0
- {progress-table-0.1.26 → progress-table-1.0.0}/progress_table/devel.py +6 -7
- progress-table-1.0.0/progress_table/devel2.py +60 -0
- {progress-table-0.1.26 → progress-table-1.0.0}/progress_table.egg-info/PKG-INFO +25 -15
- {progress-table-0.1.26 → progress-table-1.0.0}/progress_table.egg-info/SOURCES.txt +1 -2
- {progress-table-0.1.26 → progress-table-1.0.0}/pyproject.toml +3 -3
- {progress-table-0.1.26 → progress-table-1.0.0}/setup.cfg +2 -2
- {progress-table-0.1.26 → progress-table-1.0.0}/setup.py +1 -1
- progress-table-0.1.26/progress_table/__init__.py +0 -5
- progress-table-0.1.26/progress_table/progress_table.py +0 -574
- progress-table-0.1.26/progress_table/symbols.py +0 -160
- {progress-table-0.1.26 → progress-table-1.0.0}/LICENSE.txt +0 -0
- {progress-table-0.1.26 → progress-table-1.0.0}/progress_table/test_docs_automated.py +0 -0
- {progress-table-0.1.26 → progress-table-1.0.0}/progress_table.egg-info/dependency_links.txt +0 -0
- {progress-table-0.1.26 → progress-table-1.0.0}/progress_table.egg-info/requires.txt +0 -0
- {progress-table-0.1.26 → progress-table-1.0.0}/progress_table.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: progress-table
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 1.0.0
|
|
4
4
|
Summary: Display progress as a pretty table in the command line.
|
|
5
5
|
Home-page: https://github.com/gahaalt/progress-table.git
|
|
6
6
|
Author: Szymon Mikler
|
|
@@ -31,6 +31,9 @@ Designed to monitor machine learning experiments, but can be used for anything.
|
|
|
31
31
|
Allows you to quickly see what is going on.
|
|
32
32
|
Increases readability and cuteness of your command line logging.
|
|
33
33
|
|
|
34
|
+
> Note: version 1.0 introduced new features and changes of default behaviour.
|
|
35
|
+
> The old version is still available by importing `progress_table.ProgressTableV0`.
|
|
36
|
+
|
|
34
37
|
## Features
|
|
35
38
|
|
|
36
39
|
* Displaying pretty table in the terminal
|
|
@@ -58,24 +61,32 @@ import random
|
|
|
58
61
|
import sys
|
|
59
62
|
import time
|
|
60
63
|
|
|
61
|
-
from progress_table import
|
|
64
|
+
from progress_table import ProgressTableV1
|
|
62
65
|
|
|
63
|
-
#
|
|
64
|
-
table =
|
|
65
|
-
columns=["step", "x", "x squared"],
|
|
66
|
+
# Create table object:
|
|
67
|
+
table = ProgressTableV1()
|
|
66
68
|
|
|
67
|
-
|
|
69
|
+
# Or customize its settings:
|
|
70
|
+
table = ProgressTableV1(
|
|
71
|
+
columns=["step"],
|
|
68
72
|
refresh_rate=10,
|
|
69
73
|
num_decimal_places=4,
|
|
70
|
-
default_column_width=
|
|
71
|
-
|
|
74
|
+
default_column_width=None,
|
|
75
|
+
default_column_color=None,
|
|
76
|
+
default_column_alignment=None,
|
|
77
|
+
default_column_aggregate=None,
|
|
78
|
+
default_row_color=None,
|
|
79
|
+
embedded_progress_bar=True,
|
|
80
|
+
pbar_show_throughput=True,
|
|
81
|
+
pbar_show_progress=False,
|
|
72
82
|
print_row_on_update=True,
|
|
73
83
|
reprint_header_every_n_rows=30,
|
|
74
84
|
custom_format=None,
|
|
75
|
-
|
|
76
|
-
table_style="normal",
|
|
85
|
+
table_style="round",
|
|
77
86
|
file=sys.stdout,
|
|
78
87
|
)
|
|
88
|
+
|
|
89
|
+
# You can define the columns at the beginning
|
|
79
90
|
table.add_column("x", width=3)
|
|
80
91
|
table.add_column("x root", color="red")
|
|
81
92
|
table.add_column("random average", color=["bright", "red"], aggregate="mean")
|
|
@@ -83,10 +94,9 @@ table.add_column("random average", color=["bright", "red"], aggregate="mean")
|
|
|
83
94
|
for step in range(10):
|
|
84
95
|
x = random.randint(0, 200)
|
|
85
96
|
|
|
86
|
-
# There are two
|
|
87
|
-
# First:
|
|
88
|
-
table["step"] = step
|
|
97
|
+
# There are two ways to add new values:
|
|
89
98
|
table["x"] = x
|
|
99
|
+
table["step"] = step
|
|
90
100
|
# Second:
|
|
91
101
|
table.update("x root", x ** 0.5)
|
|
92
102
|
table.update("x squared", x ** 2)
|
|
@@ -105,8 +115,8 @@ table.close()
|
|
|
105
115
|
|
|
106
116
|
# Export your data
|
|
107
117
|
data = table.to_list()
|
|
108
|
-
pandas_df = table.to_df()
|
|
109
|
-
np_array = table.to_numpy()
|
|
118
|
+
pandas_df = table.to_df() # Requires pandas to be installed
|
|
119
|
+
np_array = table.to_numpy() # Requires numpy to be installed
|
|
110
120
|
```
|
|
111
121
|
|
|
112
122
|

|
|
@@ -11,6 +11,9 @@ Designed to monitor machine learning experiments, but can be used for anything.
|
|
|
11
11
|
Allows you to quickly see what is going on.
|
|
12
12
|
Increases readability and cuteness of your command line logging.
|
|
13
13
|
|
|
14
|
+
> Note: version 1.0 introduced new features and changes of default behaviour.
|
|
15
|
+
> The old version is still available by importing `progress_table.ProgressTableV0`.
|
|
16
|
+
|
|
14
17
|
## Features
|
|
15
18
|
|
|
16
19
|
* Displaying pretty table in the terminal
|
|
@@ -38,24 +41,32 @@ import random
|
|
|
38
41
|
import sys
|
|
39
42
|
import time
|
|
40
43
|
|
|
41
|
-
from progress_table import
|
|
44
|
+
from progress_table import ProgressTableV1
|
|
42
45
|
|
|
43
|
-
#
|
|
44
|
-
table =
|
|
45
|
-
columns=["step", "x", "x squared"],
|
|
46
|
+
# Create table object:
|
|
47
|
+
table = ProgressTableV1()
|
|
46
48
|
|
|
47
|
-
|
|
49
|
+
# Or customize its settings:
|
|
50
|
+
table = ProgressTableV1(
|
|
51
|
+
columns=["step"],
|
|
48
52
|
refresh_rate=10,
|
|
49
53
|
num_decimal_places=4,
|
|
50
|
-
default_column_width=
|
|
51
|
-
|
|
54
|
+
default_column_width=None,
|
|
55
|
+
default_column_color=None,
|
|
56
|
+
default_column_alignment=None,
|
|
57
|
+
default_column_aggregate=None,
|
|
58
|
+
default_row_color=None,
|
|
59
|
+
embedded_progress_bar=True,
|
|
60
|
+
pbar_show_throughput=True,
|
|
61
|
+
pbar_show_progress=False,
|
|
52
62
|
print_row_on_update=True,
|
|
53
63
|
reprint_header_every_n_rows=30,
|
|
54
64
|
custom_format=None,
|
|
55
|
-
|
|
56
|
-
table_style="normal",
|
|
65
|
+
table_style="round",
|
|
57
66
|
file=sys.stdout,
|
|
58
67
|
)
|
|
68
|
+
|
|
69
|
+
# You can define the columns at the beginning
|
|
59
70
|
table.add_column("x", width=3)
|
|
60
71
|
table.add_column("x root", color="red")
|
|
61
72
|
table.add_column("random average", color=["bright", "red"], aggregate="mean")
|
|
@@ -63,10 +74,9 @@ table.add_column("random average", color=["bright", "red"], aggregate="mean")
|
|
|
63
74
|
for step in range(10):
|
|
64
75
|
x = random.randint(0, 200)
|
|
65
76
|
|
|
66
|
-
# There are two
|
|
67
|
-
# First:
|
|
68
|
-
table["step"] = step
|
|
77
|
+
# There are two ways to add new values:
|
|
69
78
|
table["x"] = x
|
|
79
|
+
table["step"] = step
|
|
70
80
|
# Second:
|
|
71
81
|
table.update("x root", x ** 0.5)
|
|
72
82
|
table.update("x squared", x ** 2)
|
|
@@ -85,8 +95,8 @@ table.close()
|
|
|
85
95
|
|
|
86
96
|
# Export your data
|
|
87
97
|
data = table.to_list()
|
|
88
|
-
pandas_df = table.to_df()
|
|
89
|
-
np_array = table.to_numpy()
|
|
98
|
+
pandas_df = table.to_df() # Requires pandas to be installed
|
|
99
|
+
np_array = table.to_numpy() # Requires numpy to be installed
|
|
90
100
|
```
|
|
91
101
|
|
|
92
102
|

|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# Copyright (c) 2022 Szymon Mikler
|
|
2
|
+
|
|
3
|
+
from progress_table.v0.progress_table import ProgressTableV0
|
|
4
|
+
from progress_table.v1.progress_table import ProgressTableV1
|
|
5
|
+
|
|
6
|
+
ProgressTable = ProgressTableV1
|
|
7
|
+
|
|
8
|
+
__all__ = ["ProgressTable", "ProgressTableV0", "ProgressTableV1"]
|
|
@@ -3,14 +3,13 @@ import shutil
|
|
|
3
3
|
import sys
|
|
4
4
|
import time
|
|
5
5
|
|
|
6
|
-
from progress_table import
|
|
6
|
+
from progress_table import ProgressTableV1
|
|
7
7
|
|
|
8
8
|
shutil.get_terminal_size()
|
|
9
9
|
|
|
10
10
|
# Define the columns at the beginning
|
|
11
|
-
table =
|
|
11
|
+
table = ProgressTableV1(
|
|
12
12
|
columns=["step", "x", "x squared"],
|
|
13
|
-
|
|
14
13
|
# Default arguments:
|
|
15
14
|
refresh_rate=10,
|
|
16
15
|
num_decimal_places=4,
|
|
@@ -35,17 +34,17 @@ for step in range(100):
|
|
|
35
34
|
table["step"] = step
|
|
36
35
|
table["x"] = x
|
|
37
36
|
# Second:
|
|
38
|
-
table.update("x root", x
|
|
39
|
-
table.update("x squared", x
|
|
37
|
+
table.update("x root", x**0.5)
|
|
38
|
+
table.update("x squared", x**2)
|
|
40
39
|
|
|
41
40
|
# Display the progress bar by wrapping the iterator
|
|
42
41
|
for _ in table(10):
|
|
43
42
|
# You can use weights for aggregated values
|
|
44
43
|
table.update("random average", random.random(), weight=1)
|
|
45
|
-
time.sleep(0.
|
|
44
|
+
time.sleep(0.1)
|
|
46
45
|
|
|
47
46
|
# Go to the next row when you're ready
|
|
48
|
-
if step % 5 ==
|
|
47
|
+
if step % 5 == 0:
|
|
49
48
|
split = True
|
|
50
49
|
else:
|
|
51
50
|
split = False
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import random
|
|
2
|
+
import sys
|
|
3
|
+
import time
|
|
4
|
+
|
|
5
|
+
from progress_table import ProgressTableV1
|
|
6
|
+
|
|
7
|
+
# Create table object:
|
|
8
|
+
table = ProgressTableV1()
|
|
9
|
+
|
|
10
|
+
# Or customize its settings:
|
|
11
|
+
table = ProgressTableV1(
|
|
12
|
+
columns=["step"],
|
|
13
|
+
refresh_rate=10,
|
|
14
|
+
num_decimal_places=4,
|
|
15
|
+
default_column_width=None,
|
|
16
|
+
default_column_color=None,
|
|
17
|
+
default_column_alignment=None,
|
|
18
|
+
default_column_aggregate=None,
|
|
19
|
+
default_row_color=None,
|
|
20
|
+
embedded_progress_bar=True,
|
|
21
|
+
pbar_show_throughput=True,
|
|
22
|
+
pbar_show_progress=False,
|
|
23
|
+
print_row_on_update=True,
|
|
24
|
+
reprint_header_every_n_rows=30,
|
|
25
|
+
custom_format=None,
|
|
26
|
+
table_style="round",
|
|
27
|
+
file=sys.stdout,
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
# You can define the columns at the beginning
|
|
31
|
+
table.add_column("x", width=3)
|
|
32
|
+
table.add_column("x root", color="red")
|
|
33
|
+
table.add_column("random average", color=["bright", "red"], aggregate="mean")
|
|
34
|
+
|
|
35
|
+
for step in range(10):
|
|
36
|
+
x = random.randint(0, 200)
|
|
37
|
+
|
|
38
|
+
# There are two ways to add new values:
|
|
39
|
+
table["x"] = x
|
|
40
|
+
table["step"] = step
|
|
41
|
+
# Second:
|
|
42
|
+
table.update("x root", x**0.5)
|
|
43
|
+
table.update("x squared", x**2)
|
|
44
|
+
|
|
45
|
+
# Display the progress bar by wrapping the iterator
|
|
46
|
+
for _ in table(10): # -> Equivalent to `table(range(10))`
|
|
47
|
+
# You can use weights for aggregated values
|
|
48
|
+
table.update("random average", random.random(), weight=1)
|
|
49
|
+
time.sleep(0.1)
|
|
50
|
+
|
|
51
|
+
# Go to the next row when you're ready
|
|
52
|
+
table.next_row()
|
|
53
|
+
|
|
54
|
+
# Close the table when it's ready
|
|
55
|
+
table.close()
|
|
56
|
+
|
|
57
|
+
# Export your data
|
|
58
|
+
data = table.to_list()
|
|
59
|
+
pandas_df = table.to_df() # Requires pandas to be installed
|
|
60
|
+
np_array = table.to_numpy() # Requires numpy to be installed
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: progress-table
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 1.0.0
|
|
4
4
|
Summary: Display progress as a pretty table in the command line.
|
|
5
5
|
Home-page: https://github.com/gahaalt/progress-table.git
|
|
6
6
|
Author: Szymon Mikler
|
|
@@ -31,6 +31,9 @@ Designed to monitor machine learning experiments, but can be used for anything.
|
|
|
31
31
|
Allows you to quickly see what is going on.
|
|
32
32
|
Increases readability and cuteness of your command line logging.
|
|
33
33
|
|
|
34
|
+
> Note: version 1.0 introduced new features and changes of default behaviour.
|
|
35
|
+
> The old version is still available by importing `progress_table.ProgressTableV0`.
|
|
36
|
+
|
|
34
37
|
## Features
|
|
35
38
|
|
|
36
39
|
* Displaying pretty table in the terminal
|
|
@@ -58,24 +61,32 @@ import random
|
|
|
58
61
|
import sys
|
|
59
62
|
import time
|
|
60
63
|
|
|
61
|
-
from progress_table import
|
|
64
|
+
from progress_table import ProgressTableV1
|
|
62
65
|
|
|
63
|
-
#
|
|
64
|
-
table =
|
|
65
|
-
columns=["step", "x", "x squared"],
|
|
66
|
+
# Create table object:
|
|
67
|
+
table = ProgressTableV1()
|
|
66
68
|
|
|
67
|
-
|
|
69
|
+
# Or customize its settings:
|
|
70
|
+
table = ProgressTableV1(
|
|
71
|
+
columns=["step"],
|
|
68
72
|
refresh_rate=10,
|
|
69
73
|
num_decimal_places=4,
|
|
70
|
-
default_column_width=
|
|
71
|
-
|
|
74
|
+
default_column_width=None,
|
|
75
|
+
default_column_color=None,
|
|
76
|
+
default_column_alignment=None,
|
|
77
|
+
default_column_aggregate=None,
|
|
78
|
+
default_row_color=None,
|
|
79
|
+
embedded_progress_bar=True,
|
|
80
|
+
pbar_show_throughput=True,
|
|
81
|
+
pbar_show_progress=False,
|
|
72
82
|
print_row_on_update=True,
|
|
73
83
|
reprint_header_every_n_rows=30,
|
|
74
84
|
custom_format=None,
|
|
75
|
-
|
|
76
|
-
table_style="normal",
|
|
85
|
+
table_style="round",
|
|
77
86
|
file=sys.stdout,
|
|
78
87
|
)
|
|
88
|
+
|
|
89
|
+
# You can define the columns at the beginning
|
|
79
90
|
table.add_column("x", width=3)
|
|
80
91
|
table.add_column("x root", color="red")
|
|
81
92
|
table.add_column("random average", color=["bright", "red"], aggregate="mean")
|
|
@@ -83,10 +94,9 @@ table.add_column("random average", color=["bright", "red"], aggregate="mean")
|
|
|
83
94
|
for step in range(10):
|
|
84
95
|
x = random.randint(0, 200)
|
|
85
96
|
|
|
86
|
-
# There are two
|
|
87
|
-
# First:
|
|
88
|
-
table["step"] = step
|
|
97
|
+
# There are two ways to add new values:
|
|
89
98
|
table["x"] = x
|
|
99
|
+
table["step"] = step
|
|
90
100
|
# Second:
|
|
91
101
|
table.update("x root", x ** 0.5)
|
|
92
102
|
table.update("x squared", x ** 2)
|
|
@@ -105,8 +115,8 @@ table.close()
|
|
|
105
115
|
|
|
106
116
|
# Export your data
|
|
107
117
|
data = table.to_list()
|
|
108
|
-
pandas_df = table.to_df()
|
|
109
|
-
np_array = table.to_numpy()
|
|
118
|
+
pandas_df = table.to_df() # Requires pandas to be installed
|
|
119
|
+
np_array = table.to_numpy() # Requires numpy to be installed
|
|
110
120
|
```
|
|
111
121
|
|
|
112
122
|

|
|
@@ -5,8 +5,7 @@ setup.cfg
|
|
|
5
5
|
setup.py
|
|
6
6
|
progress_table/__init__.py
|
|
7
7
|
progress_table/devel.py
|
|
8
|
-
progress_table/
|
|
9
|
-
progress_table/symbols.py
|
|
8
|
+
progress_table/devel2.py
|
|
10
9
|
progress_table/test_docs_automated.py
|
|
11
10
|
progress_table.egg-info/PKG-INFO
|
|
12
11
|
progress_table.egg-info/SOURCES.txt
|
|
@@ -3,11 +3,11 @@ pythonpath = ["."]
|
|
|
3
3
|
|
|
4
4
|
[tool.mypy]
|
|
5
5
|
ignore_missing_imports = true
|
|
6
|
-
exclude = "devel"
|
|
6
|
+
exclude = ["devel", "build", "dist"]
|
|
7
7
|
|
|
8
8
|
[tool.isort]
|
|
9
9
|
profile = "black"
|
|
10
|
-
line_length =
|
|
10
|
+
line_length = 140
|
|
11
11
|
|
|
12
12
|
[tool.black]
|
|
13
|
-
line_length =
|
|
13
|
+
line_length = 140
|
|
@@ -9,7 +9,7 @@ long_description = (this_directory / "README.md").read_text(encoding="UTF-8")
|
|
|
9
9
|
|
|
10
10
|
setup(
|
|
11
11
|
name="progress-table",
|
|
12
|
-
version="0.
|
|
12
|
+
version="1.0.0",
|
|
13
13
|
url="https://github.com/gahaalt/progress-table.git",
|
|
14
14
|
author="Szymon Mikler",
|
|
15
15
|
author_email="sjmikler@gmail.com",
|
|
@@ -1,574 +0,0 @@
|
|
|
1
|
-
# Copyright (c) 2022 Szymon Mikler
|
|
2
|
-
|
|
3
|
-
from __future__ import annotations
|
|
4
|
-
|
|
5
|
-
import inspect
|
|
6
|
-
import logging
|
|
7
|
-
import math
|
|
8
|
-
import shutil
|
|
9
|
-
import sys
|
|
10
|
-
import time
|
|
11
|
-
from builtins import KeyError, staticmethod
|
|
12
|
-
from collections import defaultdict
|
|
13
|
-
from typing import Any, Callable, Dict, List, Tuple
|
|
14
|
-
|
|
15
|
-
from colorama import Fore, Style
|
|
16
|
-
|
|
17
|
-
from . import symbols
|
|
18
|
-
|
|
19
|
-
ALL_COLOR_NAMES = [x for x in dir(Fore) if not x.startswith("__")]
|
|
20
|
-
ALL_STYLE_NAMES = [x for x in dir(Style) if not x.startswith("__")]
|
|
21
|
-
ALL_COLORS_STYLES_NAMES = ALL_COLOR_NAMES + ALL_STYLE_NAMES
|
|
22
|
-
|
|
23
|
-
ALL_COLORS = [getattr(Fore, x) for x in ALL_COLOR_NAMES]
|
|
24
|
-
ALL_STYLES = [getattr(Style, x) for x in ALL_STYLE_NAMES]
|
|
25
|
-
ALL_COLORS_STYLES = ALL_COLORS + ALL_STYLES
|
|
26
|
-
|
|
27
|
-
ITERATOR_LENGTH_UNKNOWN_WARNED_ONCE = False
|
|
28
|
-
ITERATOR_LENGTH_CACHE: Dict[int, int] = {}
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
class ProgressTable:
|
|
32
|
-
def __init__(
|
|
33
|
-
self,
|
|
34
|
-
columns: Tuple | List = (),
|
|
35
|
-
refresh_rate: int = 10,
|
|
36
|
-
num_decimal_places: int = 4,
|
|
37
|
-
default_column_width: int = 8,
|
|
38
|
-
default_column_alignment: str = "center",
|
|
39
|
-
print_row_on_update: bool = True,
|
|
40
|
-
reprint_header_every_n_rows: int = 30,
|
|
41
|
-
custom_format: Callable[[Any], Any] | None = None,
|
|
42
|
-
embedded_progress_bar: bool = False,
|
|
43
|
-
table_style: str = "normal",
|
|
44
|
-
file=sys.stdout,
|
|
45
|
-
):
|
|
46
|
-
"""Progress Table instance.
|
|
47
|
-
|
|
48
|
-
Columns have to be specified before displaying the first row or launching a progress bar!
|
|
49
|
-
|
|
50
|
-
Args:
|
|
51
|
-
columns: Columns that will be displayed in the header. Columns can be provided directly in
|
|
52
|
-
`__init__` or through methods `add_column` and `add_columns`. Columns added through
|
|
53
|
-
`__init__` will have default settings like alignment, color and width, while
|
|
54
|
-
columns added through methods can have those customized.
|
|
55
|
-
refresh_rate: The maximal number of times per second the last row of the Table will be refreshed.
|
|
56
|
-
This applies only when using Progress Bar or when `print_row_on_update = True`.
|
|
57
|
-
num_decimal_places: This is only applicable when using the default formatting. This won't be used
|
|
58
|
-
if `custom_format` is set. If applicable, for every displayed value except
|
|
59
|
-
integers there will be an attempt to round it.
|
|
60
|
-
default_column_width: Width of the column excluding cell padding. This can be overwritten by
|
|
61
|
-
columns by using an argument in `add_column` method.
|
|
62
|
-
default_column_alignment: Alignment in the column. Can be aligned either to `left`, `right` or
|
|
63
|
-
`center` (default). This can be overwritten by columns by using
|
|
64
|
-
an argument in `add_column` method.
|
|
65
|
-
print_row_on_update: True by default. If False, the current row will be displayed only when
|
|
66
|
-
it's ready. Row is considered ready after calling `.next_row` or `.close`
|
|
67
|
-
methods.
|
|
68
|
-
reprint_header_every_n_rows: 30 by default. When table has a lot of rows, it can be useful to
|
|
69
|
-
remind what the header is. If True, hedaer will be displayed
|
|
70
|
-
periodically after the selected number of rows. 0 to supress.
|
|
71
|
-
custom_format: A function that allows specyfing custom formatting for values in cells.
|
|
72
|
-
This function should be universal and work for all datatypes as inputs.
|
|
73
|
-
It takes one value as an input and returns one value as an output.
|
|
74
|
-
embedded_progress_bar: False by default. If True, changes the way the progress bar looks.
|
|
75
|
-
Embedded version is more subtle, but does not prevent the current row
|
|
76
|
-
from being displayed. If False, the progress bar covers the current
|
|
77
|
-
row, preventing the user from seeing values that are being updated
|
|
78
|
-
until the progress bar finishes.
|
|
79
|
-
table_style: Change the borders of the table. Cause KeyError to see all the available styles.
|
|
80
|
-
file: Redirect the output to another stream. There can be multiple streams at once passed as
|
|
81
|
-
a list or a tuple. Defaults to sys.stdout.
|
|
82
|
-
"""
|
|
83
|
-
self.refresh_rate = refresh_rate
|
|
84
|
-
self.default_width = default_column_width
|
|
85
|
-
self.default_alignment = default_column_alignment
|
|
86
|
-
self.print_row_on_update = print_row_on_update
|
|
87
|
-
self.reprint_header_every_n_rows = reprint_header_every_n_rows
|
|
88
|
-
self.custom_format = custom_format or self.get_default_format_func(num_decimal_places)
|
|
89
|
-
self.embedded_progress_bar = embedded_progress_bar
|
|
90
|
-
|
|
91
|
-
if not isinstance(file, list) and not isinstance(file, tuple):
|
|
92
|
-
file = (file,)
|
|
93
|
-
self.files = file
|
|
94
|
-
|
|
95
|
-
# Helpers
|
|
96
|
-
self._widths: Dict[str, int] = {}
|
|
97
|
-
self._colors: Dict[str, str] = {}
|
|
98
|
-
self._alignment: Dict[str, str] = {}
|
|
99
|
-
self._aggregate: Dict[str, str | None] = {}
|
|
100
|
-
self._new_row: Dict[str, Any] = defaultdict(str)
|
|
101
|
-
self._aggregate_n: Dict[str, int] = defaultdict(int)
|
|
102
|
-
|
|
103
|
-
self.num_rows = 0
|
|
104
|
-
self.columns: List[str] = []
|
|
105
|
-
self.finished_rows: List[Dict[Any, Any]] = []
|
|
106
|
-
|
|
107
|
-
self._needs_line_ending = False
|
|
108
|
-
self._last_time_row_printed = 0
|
|
109
|
-
self._last_header_printed_at_row_count = 0
|
|
110
|
-
|
|
111
|
-
self.header_printed = False
|
|
112
|
-
self.progress_bar_active = False
|
|
113
|
-
self._refresh_progress_bar: Callable = lambda: None
|
|
114
|
-
self._needs_splitter = False
|
|
115
|
-
|
|
116
|
-
self._last_row_content = None
|
|
117
|
-
|
|
118
|
-
allowed_styles = [getattr(symbols, class_name) for class_name in dir(symbols)]
|
|
119
|
-
allowed_styles = [x for x in allowed_styles if inspect.isclass(x) and issubclass(x, symbols.Symbols)]
|
|
120
|
-
style_name_to_style = {x.name: x for x in allowed_styles if hasattr(x, "name")}
|
|
121
|
-
|
|
122
|
-
if table_style in style_name_to_style:
|
|
123
|
-
self._symbols = style_name_to_style[table_style]
|
|
124
|
-
else:
|
|
125
|
-
allowed_style_names = list(style_name_to_style)
|
|
126
|
-
raise KeyError(f"Style '{table_style}' not in {allowed_style_names}!")
|
|
127
|
-
|
|
128
|
-
for column in columns:
|
|
129
|
-
self.add_column(column)
|
|
130
|
-
|
|
131
|
-
@staticmethod
|
|
132
|
-
def get_default_format_func(decimal_places):
|
|
133
|
-
def fmt(x):
|
|
134
|
-
if isinstance(x, int):
|
|
135
|
-
return x
|
|
136
|
-
else:
|
|
137
|
-
try:
|
|
138
|
-
return format(x, f".{decimal_places}f")
|
|
139
|
-
except Exception:
|
|
140
|
-
return x
|
|
141
|
-
|
|
142
|
-
return fmt
|
|
143
|
-
|
|
144
|
-
def add_column(self, name, *, width=None, alignment=None, color=None, aggregate=None):
|
|
145
|
-
"""Add column to the table.
|
|
146
|
-
|
|
147
|
-
Args:
|
|
148
|
-
name: Name of the column. Will be displayed in the header.
|
|
149
|
-
width: Width of the column. If width is smaller than the name, width will be automatically
|
|
150
|
-
increased to the smallest possible value. This means setting `width=0` will set the column
|
|
151
|
-
to the smallest possible width allowed by `name`.
|
|
152
|
-
alignment: Alignment of the data in the column.
|
|
153
|
-
color: Color of the header and the data in the column.
|
|
154
|
-
aggregate: By default, there's no aggregation. But if this is for example 'mean', then
|
|
155
|
-
after every update in the current row, the mean of the provided values will be
|
|
156
|
-
displayed. Aggregation is reset at every new row.
|
|
157
|
-
"""
|
|
158
|
-
assert not self.header_printed, "Columns cannot be modified after displaying the first row!"
|
|
159
|
-
|
|
160
|
-
if name in self.columns:
|
|
161
|
-
logging.info(f"Column '{name}' already exists!")
|
|
162
|
-
else:
|
|
163
|
-
self.columns.append(name)
|
|
164
|
-
|
|
165
|
-
self._colors.setdefault(name, "")
|
|
166
|
-
if color is not None:
|
|
167
|
-
if isinstance(color, str):
|
|
168
|
-
color = [color]
|
|
169
|
-
for str_color in color:
|
|
170
|
-
byte_color = self._maybe_convert_to_colorama(str_color)
|
|
171
|
-
self._check_color(byte_color, str_color)
|
|
172
|
-
self._colors[name] += byte_color
|
|
173
|
-
|
|
174
|
-
alignment = alignment if alignment is not None else self.default_alignment
|
|
175
|
-
self._alignment[name] = alignment
|
|
176
|
-
|
|
177
|
-
assert aggregate in [
|
|
178
|
-
None,
|
|
179
|
-
"mean",
|
|
180
|
-
"sum",
|
|
181
|
-
"max",
|
|
182
|
-
"min",
|
|
183
|
-
], "Allowed aggregate types: [None, 'mean', 'sum', 'max', 'min']"
|
|
184
|
-
self._aggregate[name] = aggregate
|
|
185
|
-
|
|
186
|
-
width = width if width is not None else self.default_width
|
|
187
|
-
if width < len(name):
|
|
188
|
-
width = len(name)
|
|
189
|
-
self._widths[name] = width
|
|
190
|
-
|
|
191
|
-
def add_columns(self, iterable, **kwds):
|
|
192
|
-
"""Add multiple columns to the table."""
|
|
193
|
-
for column in iterable:
|
|
194
|
-
self.add_column(column, **kwds)
|
|
195
|
-
|
|
196
|
-
def next_row(self, save=True, split=False, header=False):
|
|
197
|
-
"""End the current row."""
|
|
198
|
-
self._print_row()
|
|
199
|
-
self._maybe_line_ending()
|
|
200
|
-
if self.progress_bar_active:
|
|
201
|
-
self._refresh_progress_bar()
|
|
202
|
-
sys.stdout.flush()
|
|
203
|
-
|
|
204
|
-
if save and len(self._new_row) > 0:
|
|
205
|
-
self.finished_rows.append(self._new_row)
|
|
206
|
-
self.num_rows += 1
|
|
207
|
-
|
|
208
|
-
self._new_row = defaultdict(str)
|
|
209
|
-
self._aggregate_n = defaultdict(int)
|
|
210
|
-
|
|
211
|
-
if split:
|
|
212
|
-
self._needs_splitter = True
|
|
213
|
-
|
|
214
|
-
if header:
|
|
215
|
-
self._print_header(top=False)
|
|
216
|
-
|
|
217
|
-
def close(self):
|
|
218
|
-
"""End the table and close it."""
|
|
219
|
-
self._needs_splitter = False
|
|
220
|
-
|
|
221
|
-
self.next_row()
|
|
222
|
-
self._print_bottom_bar()
|
|
223
|
-
self.header_printed = False
|
|
224
|
-
self._print()
|
|
225
|
-
|
|
226
|
-
def to_list(self):
|
|
227
|
-
"""Convert to Python nested list."""
|
|
228
|
-
return [[row[col] for col in self.columns] for row in self.finished_rows]
|
|
229
|
-
|
|
230
|
-
def to_numpy(self):
|
|
231
|
-
"""Convert to numpy array."""
|
|
232
|
-
import numpy as np
|
|
233
|
-
|
|
234
|
-
return np.array(self.to_list())
|
|
235
|
-
|
|
236
|
-
def to_df(self):
|
|
237
|
-
"""Convert to pandas DataFrame."""
|
|
238
|
-
import pandas as pd
|
|
239
|
-
|
|
240
|
-
return pd.DataFrame(self.to_list(), columns=self.columns)
|
|
241
|
-
|
|
242
|
-
def display(self):
|
|
243
|
-
"""Display the whole table. Can be used after closing the table."""
|
|
244
|
-
if self.header_printed:
|
|
245
|
-
self.close()
|
|
246
|
-
self._display_custom(self.to_list())
|
|
247
|
-
|
|
248
|
-
def update(self, key, value, *, weight=1):
|
|
249
|
-
"""Update value in the current row."""
|
|
250
|
-
assert key in self.columns, f"Column '{key}' not in {self.columns}"
|
|
251
|
-
|
|
252
|
-
if self._aggregate[key] == "sum":
|
|
253
|
-
aggr_value = self._new_row[key] if self._aggregate_n[key] > 0 else 0
|
|
254
|
-
self._new_row[key] = aggr_value + value * weight
|
|
255
|
-
self._aggregate_n[key] += weight
|
|
256
|
-
|
|
257
|
-
elif self._aggregate[key] == "mean":
|
|
258
|
-
n = self._aggregate_n[key]
|
|
259
|
-
aggr_value = self._new_row[key] if n > 0 else 0
|
|
260
|
-
self._new_row[key] = (aggr_value * n + value * weight) / (n + weight)
|
|
261
|
-
self._aggregate_n[key] += weight
|
|
262
|
-
|
|
263
|
-
elif self._aggregate[key] == "max":
|
|
264
|
-
n = self._aggregate_n[key]
|
|
265
|
-
aggr_value = self._new_row[key] if n > 0 else -float("inf")
|
|
266
|
-
self._new_row[key] = max(aggr_value, value)
|
|
267
|
-
self._aggregate_n[key] += 1
|
|
268
|
-
|
|
269
|
-
elif self._aggregate[key] == "min":
|
|
270
|
-
n = self._aggregate_n[key]
|
|
271
|
-
aggr_value = self._new_row[key] if n > 0 else float("inf")
|
|
272
|
-
self._new_row[key] = min(aggr_value, value)
|
|
273
|
-
self._aggregate_n[key] += 1
|
|
274
|
-
|
|
275
|
-
else:
|
|
276
|
-
self._new_row[key] = value
|
|
277
|
-
|
|
278
|
-
t0 = time.time()
|
|
279
|
-
td = t0 - self._last_time_row_printed
|
|
280
|
-
if self.print_row_on_update and td > 1 / self.refresh_rate:
|
|
281
|
-
self._last_time_row_printed = t0
|
|
282
|
-
|
|
283
|
-
if not self.progress_bar_active:
|
|
284
|
-
self._print_row()
|
|
285
|
-
elif self.embedded_progress_bar:
|
|
286
|
-
self._refresh_progress_bar()
|
|
287
|
-
|
|
288
|
-
def update_from_dict(self, dictionary):
|
|
289
|
-
"""Update multiple values in the current row."""
|
|
290
|
-
for key, value in dictionary.items():
|
|
291
|
-
self.update(key, value)
|
|
292
|
-
|
|
293
|
-
def _apply_cell_formatting(self, str_value: str, column: str):
|
|
294
|
-
width = self._widths[column]
|
|
295
|
-
|
|
296
|
-
alignment = self._alignment[column]
|
|
297
|
-
if alignment == "center":
|
|
298
|
-
str_value = str_value.center(width)
|
|
299
|
-
elif alignment == "left":
|
|
300
|
-
str_value = str_value.ljust(width)
|
|
301
|
-
elif alignment == "right":
|
|
302
|
-
str_value = str_value.rjust(width)
|
|
303
|
-
else:
|
|
304
|
-
allowed_alignments = ["center", "left", "right"]
|
|
305
|
-
raise KeyError(f"Alignment '{alignment}' not in {allowed_alignments}!")
|
|
306
|
-
|
|
307
|
-
clipped = len(str_value) > width
|
|
308
|
-
str_value = "".join(
|
|
309
|
-
[
|
|
310
|
-
" ", # space at the beginning of the row
|
|
311
|
-
str_value[:width].center(width),
|
|
312
|
-
self._symbols.dots if clipped else " ",
|
|
313
|
-
]
|
|
314
|
-
)
|
|
315
|
-
|
|
316
|
-
if self._colors[column] is not None:
|
|
317
|
-
str_value = f"{self._colors[column]}{str_value}{Style.RESET_ALL}"
|
|
318
|
-
return str_value
|
|
319
|
-
|
|
320
|
-
def _bar(self, left: str, center: str, right: str):
|
|
321
|
-
content_list: List[str] = []
|
|
322
|
-
for col in self.columns:
|
|
323
|
-
content_list.append(self._symbols.horizontal * (self._widths[col] + 2))
|
|
324
|
-
|
|
325
|
-
center = center.join(content_list)
|
|
326
|
-
content = ["\r", left, center, right]
|
|
327
|
-
self._print("".join(content), end="")
|
|
328
|
-
|
|
329
|
-
def _bar_custom_center(self, left: str, center: List[str] | str, right: str):
|
|
330
|
-
"""UNUSED"""
|
|
331
|
-
content_list: List[str] = []
|
|
332
|
-
|
|
333
|
-
if isinstance(center, str):
|
|
334
|
-
center = [center] * (len(self.columns) - 1)
|
|
335
|
-
assert len(center) == len(self.columns) - 1
|
|
336
|
-
|
|
337
|
-
for col in self.columns:
|
|
338
|
-
content_list.append(self._symbols.horizontal * (self._widths[col] + 2))
|
|
339
|
-
if center:
|
|
340
|
-
content_list.append(center.pop(0))
|
|
341
|
-
|
|
342
|
-
center = "".join(content_list)
|
|
343
|
-
content = ["\r", left, center, right]
|
|
344
|
-
self._print("".join(content), end="")
|
|
345
|
-
|
|
346
|
-
def _print_transition_bar(self, previous_n_cols, new_n_cols):
|
|
347
|
-
"""UNUSED"""
|
|
348
|
-
assert previous_n_cols > 0
|
|
349
|
-
assert new_n_cols > previous_n_cols
|
|
350
|
-
added_cols = new_n_cols - previous_n_cols
|
|
351
|
-
|
|
352
|
-
symbols = [
|
|
353
|
-
*([self._symbols.all] * previous_n_cols),
|
|
354
|
-
*([self._symbols.no_up] * (added_cols - 1)),
|
|
355
|
-
]
|
|
356
|
-
return self._bar_custom_center(left=self._symbols.no_left, center=symbols, right=self._symbols.down_left)
|
|
357
|
-
|
|
358
|
-
def _print_top_bar(self):
|
|
359
|
-
return self._bar(left=self._symbols.down_right, center=self._symbols.no_up, right=self._symbols.down_left)
|
|
360
|
-
|
|
361
|
-
def _print_bottom_bar(self):
|
|
362
|
-
return self._bar(left=self._symbols.up_right, center=self._symbols.no_down, right=self._symbols.up_left)
|
|
363
|
-
|
|
364
|
-
def _print_center_bar(self):
|
|
365
|
-
return self._bar(left=self._symbols.no_left, center=self._symbols.all, right=self._symbols.no_right)
|
|
366
|
-
|
|
367
|
-
@staticmethod
|
|
368
|
-
def _maybe_convert_to_colorama(color):
|
|
369
|
-
if isinstance(color, str):
|
|
370
|
-
if hasattr(Fore, color.upper()):
|
|
371
|
-
return getattr(Fore, color.upper())
|
|
372
|
-
if hasattr(Style, color.upper()):
|
|
373
|
-
return getattr(Style, color.upper())
|
|
374
|
-
return color
|
|
375
|
-
|
|
376
|
-
@staticmethod
|
|
377
|
-
def _check_color(color, color_str=None):
|
|
378
|
-
if color_str is None:
|
|
379
|
-
color_str = color
|
|
380
|
-
assert (
|
|
381
|
-
color in ALL_COLORS_STYLES
|
|
382
|
-
), f"Only colorama colors are allowed, not '{color_str}'! Available: {ALL_COLORS_STYLES_NAMES}"
|
|
383
|
-
|
|
384
|
-
def _print_header(self, top=True):
|
|
385
|
-
assert self.columns, "Columns are required! Use .add_column method or specify them in __init__!"
|
|
386
|
-
|
|
387
|
-
self._needs_splitter = False
|
|
388
|
-
|
|
389
|
-
if top:
|
|
390
|
-
self._print_top_bar()
|
|
391
|
-
else:
|
|
392
|
-
self._print_center_bar()
|
|
393
|
-
self._print()
|
|
394
|
-
|
|
395
|
-
content = []
|
|
396
|
-
for column in self.columns:
|
|
397
|
-
value = self._apply_cell_formatting(column, column)
|
|
398
|
-
content.append(value)
|
|
399
|
-
s = "".join(["\r", self._symbols.vertical, self._symbols.vertical.join(content), self._symbols.vertical])
|
|
400
|
-
self._print(s)
|
|
401
|
-
|
|
402
|
-
self._last_header_printed_at_row_count = self.num_rows
|
|
403
|
-
self.header_printed = True
|
|
404
|
-
self._print_center_bar()
|
|
405
|
-
self._print()
|
|
406
|
-
self._last_row_content = "header"
|
|
407
|
-
|
|
408
|
-
def _print_splitter(self):
|
|
409
|
-
if self._last_row_content == "row":
|
|
410
|
-
self._print_center_bar()
|
|
411
|
-
self._print()
|
|
412
|
-
|
|
413
|
-
self._needs_splitter = False
|
|
414
|
-
self._last_row_content = "splitter"
|
|
415
|
-
|
|
416
|
-
def _get_row(self):
|
|
417
|
-
content = []
|
|
418
|
-
for column in self.columns:
|
|
419
|
-
value = self._new_row[column]
|
|
420
|
-
value = self.custom_format(value)
|
|
421
|
-
value = self._apply_cell_formatting(str_value=str(value), column=column)
|
|
422
|
-
content.append(value)
|
|
423
|
-
return "".join(["\r", self._symbols.vertical, self._symbols.vertical.join(content), self._symbols.vertical])
|
|
424
|
-
|
|
425
|
-
def _print_row(self):
|
|
426
|
-
if not self.header_printed:
|
|
427
|
-
self._print_header(top=True)
|
|
428
|
-
|
|
429
|
-
if self.reprint_header_every_n_rows != 0:
|
|
430
|
-
if self.num_rows - self._last_header_printed_at_row_count >= self.reprint_header_every_n_rows:
|
|
431
|
-
self._print_header(top=False)
|
|
432
|
-
|
|
433
|
-
if self._needs_splitter:
|
|
434
|
-
self._print_splitter()
|
|
435
|
-
|
|
436
|
-
if len(self._new_row) == 0:
|
|
437
|
-
return
|
|
438
|
-
self._needs_line_ending = True
|
|
439
|
-
self._print(self._get_row(), end="")
|
|
440
|
-
|
|
441
|
-
def _print_progress_bar(self, i, n, show_before=" ", show_after=" ", embedded=False):
|
|
442
|
-
i = min(i, n) # clip the iteration number to be not bigger than the total number of iterations
|
|
443
|
-
terminal_width = shutil.get_terminal_size(fallback=(0, 0)).columns or float("inf")
|
|
444
|
-
|
|
445
|
-
if not embedded:
|
|
446
|
-
tot_width = sum(self._widths.values()) + 3 * (len(self._widths) - 1) + 2
|
|
447
|
-
if tot_width >= terminal_width - 1:
|
|
448
|
-
tot_width = terminal_width - 2
|
|
449
|
-
|
|
450
|
-
tot_width = tot_width - len(show_before) - len(show_after)
|
|
451
|
-
num_hashes = math.ceil(i / n * tot_width)
|
|
452
|
-
num_empty = tot_width - num_hashes
|
|
453
|
-
|
|
454
|
-
self._print(
|
|
455
|
-
self._symbols.vertical,
|
|
456
|
-
show_before,
|
|
457
|
-
self._symbols.pbar_filled * num_hashes,
|
|
458
|
-
self._symbols.pbar_empty * num_empty,
|
|
459
|
-
show_after,
|
|
460
|
-
self._symbols.vertical,
|
|
461
|
-
end="\r",
|
|
462
|
-
sep="",
|
|
463
|
-
)
|
|
464
|
-
else:
|
|
465
|
-
row = self._get_row()
|
|
466
|
-
new_row = []
|
|
467
|
-
for idx, letter in enumerate(row):
|
|
468
|
-
if idx / len(row) <= i / n:
|
|
469
|
-
if letter == " ":
|
|
470
|
-
letter = self._symbols.embedded_pbar_filled
|
|
471
|
-
new_row.append(letter)
|
|
472
|
-
row = "".join(new_row)
|
|
473
|
-
self._print(row, end="\r")
|
|
474
|
-
sys.stdout.flush()
|
|
475
|
-
|
|
476
|
-
def _maybe_line_ending(self):
|
|
477
|
-
if self._needs_line_ending:
|
|
478
|
-
self._print()
|
|
479
|
-
self._needs_splitter = False
|
|
480
|
-
self._needs_line_ending = False
|
|
481
|
-
self._last_row_content = "row"
|
|
482
|
-
|
|
483
|
-
def _display_custom(self, data):
|
|
484
|
-
if self.header_printed:
|
|
485
|
-
self.close()
|
|
486
|
-
|
|
487
|
-
for row in data:
|
|
488
|
-
assert len(row) == len(self.columns)
|
|
489
|
-
for key, value in zip(self.columns, row):
|
|
490
|
-
self._new_row[key] = value
|
|
491
|
-
self._print_row()
|
|
492
|
-
self.next_row(save=False)
|
|
493
|
-
self.close()
|
|
494
|
-
self._last_row_content = "close"
|
|
495
|
-
|
|
496
|
-
def _print(self, *args, **kwds):
|
|
497
|
-
for file in self.files:
|
|
498
|
-
print(*args, **kwds, file=file)
|
|
499
|
-
|
|
500
|
-
def __call__(self, iterator, *range_args, length=None, prefix="", show_throughput=True):
|
|
501
|
-
"""Display progress bar over the iterator. Try to figure out the iterator length."""
|
|
502
|
-
global ITERATOR_LENGTH_UNKNOWN_WARNED_ONCE, ITERATOR_LENGTH_CACHE
|
|
503
|
-
|
|
504
|
-
if not self.header_printed:
|
|
505
|
-
self._print_header()
|
|
506
|
-
|
|
507
|
-
if isinstance(iterator, int):
|
|
508
|
-
iterator = range(iterator, *range_args)
|
|
509
|
-
else:
|
|
510
|
-
assert len(range_args) == 0, "Unnamed args are not allowed here!"
|
|
511
|
-
|
|
512
|
-
if length is None and not hasattr(iterator, "__len__"):
|
|
513
|
-
if not ITERATOR_LENGTH_UNKNOWN_WARNED_ONCE:
|
|
514
|
-
logging.warning("Iterator length is unknown!")
|
|
515
|
-
ITERATOR_LENGTH_UNKNOWN_WARNED_ONCE = True
|
|
516
|
-
|
|
517
|
-
# We have a back-up mechanism in case of unknown-length iterators.
|
|
518
|
-
# If we progress over the same unknown length iterator more than once,
|
|
519
|
-
# we will use its length from the previous launch.
|
|
520
|
-
save_length_to_cache = True
|
|
521
|
-
|
|
522
|
-
if id(iterator) in ITERATOR_LENGTH_CACHE:
|
|
523
|
-
length = ITERATOR_LENGTH_CACHE[id(iterator)]
|
|
524
|
-
else:
|
|
525
|
-
length = 1
|
|
526
|
-
else:
|
|
527
|
-
save_length_to_cache = False
|
|
528
|
-
length = length or len(iterator)
|
|
529
|
-
|
|
530
|
-
t_last_printed = -float("inf")
|
|
531
|
-
t_beginning = time.time()
|
|
532
|
-
|
|
533
|
-
self.progress_bar_active = True
|
|
534
|
-
|
|
535
|
-
idx = 0
|
|
536
|
-
for idx, element in enumerate(iterator):
|
|
537
|
-
if time.time() - t_last_printed > 1 / self.refresh_rate:
|
|
538
|
-
# Reenable here, in case of nested progress bars
|
|
539
|
-
self.progress_bar_active = True
|
|
540
|
-
|
|
541
|
-
self._print(end="\r")
|
|
542
|
-
s = time.time() - t_beginning
|
|
543
|
-
throughput = idx / s if s > 0 else 0.0
|
|
544
|
-
|
|
545
|
-
full_prefix = [" [", prefix]
|
|
546
|
-
if show_throughput:
|
|
547
|
-
full_prefix.append(f"{throughput: <.2f} it/s")
|
|
548
|
-
full_prefix.append("] ")
|
|
549
|
-
full_prefix = "".join(full_prefix)
|
|
550
|
-
full_prefix = full_prefix if full_prefix != " [] " else " "
|
|
551
|
-
|
|
552
|
-
self._refresh_progress_bar = lambda: self._print_progress_bar(
|
|
553
|
-
idx,
|
|
554
|
-
length,
|
|
555
|
-
show_before=full_prefix,
|
|
556
|
-
embedded=self.embedded_progress_bar,
|
|
557
|
-
)
|
|
558
|
-
self._refresh_progress_bar()
|
|
559
|
-
|
|
560
|
-
t_last_printed = time.time()
|
|
561
|
-
yield element
|
|
562
|
-
if save_length_to_cache:
|
|
563
|
-
ITERATOR_LENGTH_CACHE[id(iterator)] = idx
|
|
564
|
-
|
|
565
|
-
self.progress_bar_active = False
|
|
566
|
-
self._print_row()
|
|
567
|
-
|
|
568
|
-
def __setitem__(self, key, value):
|
|
569
|
-
self.update(key, value, weight=1)
|
|
570
|
-
|
|
571
|
-
def __getitem__(self, key):
|
|
572
|
-
assert key in self.columns, f"Column '{key}' not in {self.columns}"
|
|
573
|
-
|
|
574
|
-
return self._new_row[key]
|
|
@@ -1,160 +0,0 @@
|
|
|
1
|
-
from dataclasses import dataclass
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
@dataclass
|
|
5
|
-
class Symbols:
|
|
6
|
-
pbar_filled: str
|
|
7
|
-
pbar_empty: str
|
|
8
|
-
embedded_pbar_filled: str
|
|
9
|
-
dots: str
|
|
10
|
-
horizontal: str
|
|
11
|
-
vertical: str
|
|
12
|
-
all: str
|
|
13
|
-
up_left: str
|
|
14
|
-
up_right: str
|
|
15
|
-
down_left: str
|
|
16
|
-
down_right: str
|
|
17
|
-
no_left: str
|
|
18
|
-
no_right: str
|
|
19
|
-
no_up: str
|
|
20
|
-
no_down: str
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
@dataclass
|
|
24
|
-
class SymbolsUnicode(Symbols):
|
|
25
|
-
name = "normal"
|
|
26
|
-
pbar_filled = "■"
|
|
27
|
-
pbar_empty = "□"
|
|
28
|
-
embedded_pbar_filled = "_"
|
|
29
|
-
dots = "…"
|
|
30
|
-
horizontal = "─"
|
|
31
|
-
vertical = "│"
|
|
32
|
-
all = "┼"
|
|
33
|
-
up_left = "┘"
|
|
34
|
-
up_right = "└"
|
|
35
|
-
down_left = "┐"
|
|
36
|
-
down_right = "┌"
|
|
37
|
-
no_left = "├"
|
|
38
|
-
no_right = "┤"
|
|
39
|
-
no_up = "┬"
|
|
40
|
-
no_down = "┴"
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
@dataclass
|
|
44
|
-
class SymbolsUnicodeBare(Symbols):
|
|
45
|
-
name = "bare"
|
|
46
|
-
pbar_filled = "■"
|
|
47
|
-
pbar_empty = "□"
|
|
48
|
-
embedded_pbar_filled = "_"
|
|
49
|
-
dots = "…"
|
|
50
|
-
horizontal = "─"
|
|
51
|
-
vertical = " "
|
|
52
|
-
all = "─"
|
|
53
|
-
up_left = "─"
|
|
54
|
-
up_right = "─"
|
|
55
|
-
down_left = "─"
|
|
56
|
-
down_right = "─"
|
|
57
|
-
no_left = "─"
|
|
58
|
-
no_right = "─"
|
|
59
|
-
no_up = "─"
|
|
60
|
-
no_down = "─"
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
@dataclass
|
|
64
|
-
class SymbolsUnicodeRound(Symbols):
|
|
65
|
-
name = "round"
|
|
66
|
-
pbar_filled = "■"
|
|
67
|
-
pbar_empty = "□"
|
|
68
|
-
embedded_pbar_filled = "_"
|
|
69
|
-
dots = "…"
|
|
70
|
-
horizontal = "─"
|
|
71
|
-
vertical = "│"
|
|
72
|
-
all = "┼"
|
|
73
|
-
up_left = "╯"
|
|
74
|
-
up_right = "╰"
|
|
75
|
-
down_left = "╮"
|
|
76
|
-
down_right = "╭"
|
|
77
|
-
no_left = "├"
|
|
78
|
-
no_right = "┤"
|
|
79
|
-
no_up = "┬"
|
|
80
|
-
no_down = "┴"
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
@dataclass
|
|
84
|
-
class SymbolsUnicodeDouble(Symbols):
|
|
85
|
-
name = "double"
|
|
86
|
-
pbar_filled = "■"
|
|
87
|
-
pbar_empty = "□"
|
|
88
|
-
embedded_pbar_filled = "_"
|
|
89
|
-
dots = "…"
|
|
90
|
-
horizontal = "═"
|
|
91
|
-
vertical = "║"
|
|
92
|
-
all = "╬"
|
|
93
|
-
up_left = "╝"
|
|
94
|
-
up_right = "╚"
|
|
95
|
-
down_left = "╗"
|
|
96
|
-
down_right = "╔"
|
|
97
|
-
no_left = "╠"
|
|
98
|
-
no_right = "╣"
|
|
99
|
-
no_up = "╦"
|
|
100
|
-
no_down = "╩"
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
@dataclass
|
|
104
|
-
class SymbolsUnicodeBold(Symbols):
|
|
105
|
-
name = "bold"
|
|
106
|
-
pbar_filled = "■"
|
|
107
|
-
pbar_empty = "□"
|
|
108
|
-
embedded_pbar_filled = "_"
|
|
109
|
-
dots = "…"
|
|
110
|
-
horizontal = "━"
|
|
111
|
-
vertical = "┃"
|
|
112
|
-
all = "╋"
|
|
113
|
-
up_left = "┛"
|
|
114
|
-
up_right = "┗"
|
|
115
|
-
down_left = "┓"
|
|
116
|
-
down_right = "┏"
|
|
117
|
-
no_left = "┣"
|
|
118
|
-
no_right = "┫"
|
|
119
|
-
no_up = "┳"
|
|
120
|
-
no_down = "┻"
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
@dataclass
|
|
124
|
-
class SymbolsAscii(Symbols):
|
|
125
|
-
name = "ascii"
|
|
126
|
-
pbar_filled = "#"
|
|
127
|
-
pbar_empty = "."
|
|
128
|
-
embedded_pbar_filled = "_"
|
|
129
|
-
dots = "_"
|
|
130
|
-
horizontal = "-"
|
|
131
|
-
vertical = "|"
|
|
132
|
-
all = "+"
|
|
133
|
-
up_left = "+"
|
|
134
|
-
up_right = "+"
|
|
135
|
-
down_left = "+"
|
|
136
|
-
down_right = "+"
|
|
137
|
-
no_left = "+"
|
|
138
|
-
no_right = "+"
|
|
139
|
-
no_up = "+"
|
|
140
|
-
no_down = "+"
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
@dataclass
|
|
144
|
-
class SymbolsAsciiBare(Symbols):
|
|
145
|
-
name = "ascii_bare"
|
|
146
|
-
pbar_filled = "#"
|
|
147
|
-
pbar_empty = "."
|
|
148
|
-
embedded_pbar_filled = "_"
|
|
149
|
-
dots = "_"
|
|
150
|
-
horizontal = "-"
|
|
151
|
-
vertical = " "
|
|
152
|
-
all = "-"
|
|
153
|
-
up_left = "-"
|
|
154
|
-
up_right = "-"
|
|
155
|
-
down_left = "-"
|
|
156
|
-
down_right = "-"
|
|
157
|
-
no_left = "-"
|
|
158
|
-
no_right = "-"
|
|
159
|
-
no_up = "-"
|
|
160
|
-
no_down = "-"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|