Skip to content

Commit 42d3020

Browse files
Ken KundertKen Kundert
authored andcommitted
enhancements to truth()
1 parent bffa4c6 commit 42d3020

File tree

4 files changed

+57
-14
lines changed

4 files changed

+57
-14
lines changed

doc/releases.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ Latest development release
99
| Version: 1.35
1010
| Released: 2025-07-30
1111
12+
- Added *is_true* argument and value format specification to :class:`truth`.
13+
1214

1315
1.35 (2025-07-30)
1416
-----------------

inform/inform.py

Lines changed: 52 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1566,17 +1566,55 @@ class truth:
15661566
15671567
If '/', or '%' are inconvenient, you can change them by passing the
15681568
*slash* and *interpolate* arguments to truth().
1569+
1570+
By default *bool*() is used to determine whether the value is true or false.
1571+
However you can override this behavior by passing a value to *is_true*. It
1572+
may be a simple value or it may be a callable that accepts the given value
1573+
as its only argument.
1574+
1575+
The formatter may contain a third section, which if present is taken to be a
1576+
format specification that is applied to value before it is interpolated into
1577+
the output.
1578+
1579+
As an example of these features, consider this example:
1580+
1581+
>>> contestants = [
1582+
... dict(name="Elinor", index=27, wins="car" ),
1583+
... dict(name="Vernon", index=130, wins="phone"),
1584+
... dict(name="Lee", index=0),
1585+
... dict(name="Lita", comment='disqualified'),
1586+
... ]
1587+
1588+
>>> for contestant in contestants:
1589+
... name = contestant.get('name')
1590+
... index = contestant.get('index')
1591+
... index = truth(index, is_true=index is not None)
1592+
... wins = truth(contestant.get('wins'))
1593+
... comment = truth(contestant.get('comment'))
1594+
... print(f"{index:%/ ✗/>3}: {name}{wins: wins a %/ loses}{comment: (%)/}")
1595+
27: Elinor wins a car
1596+
130: Vernon wins a phone
1597+
0: Lee loses
1598+
✗: Lita loses (disqualified)
1599+
15691600
"""
15701601

1571-
def __init__(self, value, formatter=None, *, interpolate='%', slash='/'):
1602+
def __init__(self, value, formatter=None, *, is_true=None, interpolate='%', slash='/'):
15721603
self.value = value
1604+
if is_true is None:
1605+
self.is_true = bool(value)
1606+
elif callable(is_true):
1607+
self.is_true = is_true(value)
1608+
else:
1609+
self.is_true = bool(is_true)
15731610
self.interpolate = interpolate
15741611
self.slash = slash
15751612
if formatter:
1576-
use_if_true, _, use_if_false = formatter.partition(self.slash)
1577-
self.defaults = use_if_true, use_if_false
1613+
use_if_true, _, rest = formatter.partition(self.slash)
1614+
use_if_false, _, preformatter = rest.partition(self.slash)
1615+
self.defaults = use_if_true, use_if_false, preformatter
15781616
else:
1579-
self.defaults = 'yes', 'no'
1617+
self.defaults = 'yes', 'no', ''
15801618

15811619
def format(self, formatter=None):
15821620
"""Expand truth to a string.
@@ -1593,19 +1631,22 @@ def format(self, formatter=None):
15931631
return self.__format__(formatter)
15941632

15951633
def __format__(self, formatter):
1596-
value = self.value
15971634
if formatter:
1598-
use_if_true, _, use_if_false = formatter.partition(self.slash)
1635+
use_if_true, _, rest = formatter.partition(self.slash)
1636+
use_if_false, _, preformatter = rest.partition(self.slash)
15991637
else:
1600-
use_if_true, use_if_false = self.defaults
1601-
out = use_if_true if bool(value) else use_if_false
1602-
return out.replace(self.interpolate, str(value))
1638+
use_if_true, use_if_false, preformatter = self.defaults
1639+
out = use_if_true if self.is_true else use_if_false
1640+
value = str(self.value)
1641+
if preformatter and self.interpolate in out:
1642+
value = f"{self.value:{preformatter}}"
1643+
return out.replace(self.interpolate, value)
16031644

16041645
def __str__(self):
1605-
return self.defaults[0] if self.value else self.defaults[1]
1646+
return self.defaults[0] if self.is_true else self.defaults[1]
16061647

16071648
def __bool__(self):
1608-
return bool(self.value)
1649+
return self.is_true
16091650

16101651
def __repr__(self):
16111652
return f"{self.__class__.__name__}({bool(self.value)})"

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ build-backend = "flit_core.buildapi"
4949
addopts = "--tb=short"
5050

5151
[tool.ruff]
52-
exclude = [".tox", "doc", "Diffs"]
52+
exclude = [".tox", "doc", ".diffs"]
5353

5454
[tool.ruff.lint]
5555
select = ["F"]

tests/test_zdoctests.py

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

2424
rv = doctest.testfile('../inform/inform.py', optionflags=doctest.ELLIPSIS)
25-
assert rv.attempted in [183, 184]
26-
# for some reason 181 test are run on my laptop, and 180 on github
25+
assert rv.attempted in [185, 186]
26+
# for some reason my laptop runs one more test that github
2727
assert rv.failed == 0
2828

2929
def test_manual():

0 commit comments

Comments
 (0)