Skip to content

Commit 71dcfaa

Browse files
Ken KundertKen Kundert
authored andcommitted
in bar class, convert clip to a real value and add overflow marker
1 parent b864897 commit 71dcfaa

File tree

2 files changed

+57
-49
lines changed

2 files changed

+57
-49
lines changed

inform/inform.py

Lines changed: 55 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1725,16 +1725,26 @@ class bar:
17251725
trailing spaces. This is useful if anything follows the bar on its
17261726
line, such as if you wish to mark the end of the bar.
17271727
1728-
clip (bool):
1729-
Should the length of the bar be limited to *width* if a value
1730-
greater than 1 is specified.
1728+
clip (real):
1729+
Maximum allowed value.
1730+
If value is larger than clip, it is plotted as if it equals clip
1731+
except bar is terminated with the overflow marker.
1732+
1733+
overflow (str):
1734+
The overflow marker. If value is greater than clip the overflow
1735+
marker is appended to the bar. If False, no marker is used.
1736+
Common values are '➔', '∎', '►', '▞', '▋▍▎▏' or '>>>'.
17311737
17321738
When rendered within a string you can specify a format that overrides the
1733-
above arguments. The format strings take the form *WFC* where:
1739+
above arguments. The format strings take the form *WFCO* where:
17341740
17351741
- *W* is an integer that overrides *width*.
17361742
- *F* is either 'f' or 'F' overrides *full_width*; is true if capitalized.
1737-
- *C* is either 'c' or 'C' overrides *clip*; is true if capitalized.
1743+
- *C* is a simple real number, 1 or greater.
1744+
- *O* is an arbitrary string that becomes the overflow marker.
1745+
1746+
The format fields are optional, but if one is given, the one listed before
1747+
it must also be given.
17381748
17391749
**Examples**::
17401750
@@ -1748,81 +1758,78 @@ class bar:
17481758
cash: ❭████▊ ❬
17491759
equities: ❭████████████████████████████████▊ ❬
17501760
1761+
In this second example a clipping value of 2 and an overflow marker is added
1762+
to the end of the end of the format string. When the life exceeds 2× the
1763+
maximum life the overflow marker is added to the end of the bar, which adds
1764+
a few vertical bars, a newline, and 20 spaced of indent.
1765+
1766+
>>> hours = dict(drill01=6, drill02=34, drill03=89, drill04=57)
1767+
>>> max_life = 40
1768+
>>> for name, life in hours.items():
1769+
... print(f"{bar(life/max_life):20F2▋▍▎▏\n }", name)
1770+
███ drill01
1771+
█████████████████ drill02
1772+
████████████████████████████████████████▋▍▎▏
1773+
drill03
1774+
████████████████████████████▌ drill04
1775+
17511776
"""
1752-
def __init__(self, value, width=72, full_width=False, clip=True):
1777+
def __init__(self, value, width=72, full_width=False, clip=1, overflow=False):
17531778
self.value = value
17541779
self.width = width
17551780
self.full_width = full_width
17561781
self.clip = clip
1782+
self.overflow = overflow or ''
17571783

1758-
def render(self, value=None, width=None, full_width=None, clip=None):
1784+
def render(self, value=None, width=None, full_width=None, clip=None, overflow=None):
17591785
"""Render bar to string
17601786
1761-
Any arguments given will override those specified when class was
1762-
instantiated.
1763-
1764-
Args:
1765-
value (real): Should be normalized (fall between 0 and 1)
1766-
1767-
width (int): The width of the bar in characters when value is 1.
1768-
1769-
full_width (bool):
1770-
Whether bar should be rendered to fill the whole width using
1771-
trailing spaces. This is useful if you plan to mark the end of
1772-
the bar.
1773-
1774-
clip (bool):
1775-
Should the length of the bar be limited to *width* if a value
1776-
greater than 1 is specified.
1787+
Arguments given override those specified when class was instantiated.
17771788
"""
1778-
17791789
value = self.value if value is None else value
17801790
width = self.width if width is None else width
17811791
full_width = self.full_width if full_width is None else full_width
17821792
clip = self.clip if clip is None else clip
1783-
scaled = value*width
1784-
if clip and scaled > width:
1785-
scaled = width
1786-
if scaled < 0:
1787-
scaled = 0
1793+
overflow = self.overflow if overflow is None else overflow
1794+
1795+
scaled = max(min(value, clip), 0)*width
17881796
buckets = int(scaled)
17891797
frac = int((NUM_BAR_CHARS*scaled) % NUM_BAR_CHARS)
1790-
extra = BAR_CHARS[frac-1:frac]
1791-
bar = buckets*BAR_CHARS[-1] + extra
1798+
if value > clip:
1799+
last = overflow
1800+
else:
1801+
last = BAR_CHARS[frac-1:frac]
1802+
bar = buckets*BAR_CHARS[-1] + last
17921803
if full_width:
17931804
bar += (width - len(bar))*' '
17941805
return bar
17951806

17961807
def __format__(self, formatter):
1797-
# format strings take the form WFC where:
1808+
# format strings take the form WFCO where:
17981809
# W is an integer indicating desired width
17991810
# F is either 'f' or 'F' for full_width, cap is true
1800-
# C is either 'c' or 'C' for clip, cap is true
1801-
value = self.value
1802-
width = self.width
1803-
full_width = self.full_width
1804-
clip = self.clip
1811+
# C is a simple real number, 1 or greater.
1812+
# O is an arbitrary string that will be used as overflow marker
1813+
value = width = full_width = clip = overflow = None
18051814
if formatter:
1806-
match = re.match(r'(\d*)([fFcC]{0,2})', formatter)
1815+
match = re.match(r'(\d*)([fF]?)(\d\.?\d*)?(.*)\Z', formatter, re.S)
18071816
try:
18081817
if match[1]:
18091818
width = int(match[1])
18101819
if 'f' in match[2]:
18111820
full_width = False
18121821
if 'F' in match[2]:
18131822
full_width = True
1814-
if 'c' in match[2]:
1815-
clip = False
1816-
if 'C' in match[2]:
1817-
clip = True
1823+
clip = float(match[3]) if match[3] else None
1824+
overflow = match[4] or None
18181825
except (TypeError, ValueError):
18191826
warn('invalid format string')
1820-
return self.render(value, width, full_width, clip)
1827+
return self.render(value, width, full_width, clip, overflow)
18211828

18221829
def __str__(self):
18231830
return self.render()
18241831

1825-
def render_bar(value, width=72, full_width=False, clip=True):
1832+
def render_bar(value, width=72, full_width=False, clip=1):
18261833
"""Render graphic representation of a value in the form of a bar
18271834
18281835
This function is deprecated. You should instead use::
@@ -1839,9 +1846,10 @@ def render_bar(value, width=72, full_width=False, clip=True):
18391846
trailing spaces. This is useful if you plan to mark the end of
18401847
the bar.
18411848
1842-
clip (bool):
1843-
Should the length of the bar be limited to *width* if a value
1844-
greater than 1 is specified.
1849+
clip (real):
1850+
Maximum allowed value.
1851+
If value is larger than clip, it is plotted as if it equals clip
1852+
except bar is terminated with the overflow marker.
18451853
"""
18461854
return bar(value, width, full_width, clip).render()
18471855

tests/test_zdoctests.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ def test_inform():
2323
return
2424

2525
rv = doctest.testfile('../inform/inform.py', optionflags=doctest.ELLIPSIS)
26-
assert rv.attempted in [180, 181]
27-
# for some reasons 181 test are run on my laptop, and 180 on github
26+
assert rv.attempted in [183, 184]
27+
# for some reason 181 test are run on my laptop, and 180 on github
2828
assert rv.failed == 0
2929

3030
def test_manual():

0 commit comments

Comments
 (0)