utils: introduce format_plural and move format functions to strings.py

pull/447/head
Tomas Susanka 5 years ago committed by matejcik
parent 75264a07a8
commit 0053511c66

@ -7,9 +7,9 @@ from trezor.messages import (
BinanceTransferMsg, BinanceTransferMsg,
ButtonRequestType, ButtonRequestType,
) )
from trezor.strings import format_amount
from trezor.ui.scroll import Paginated from trezor.ui.scroll import Paginated
from trezor.ui.text import Text from trezor.ui.text import Text
from trezor.utils import format_amount
from . import helpers from . import helpers

@ -1,9 +1,10 @@
from micropython import const from micropython import const
from trezor import ui from trezor import ui
from trezor.strings import format_amount
from trezor.ui.scroll import Paginated from trezor.ui.scroll import Paginated
from trezor.ui.text import Text from trezor.ui.text import Text
from trezor.utils import chunks, format_amount from trezor.utils import chunks
from apps.common.confirm import confirm, hold_to_confirm from apps.common.confirm import confirm, hold_to_confirm

@ -2,8 +2,9 @@ from ubinascii import hexlify
from trezor import ui from trezor import ui
from trezor.messages import ButtonRequestType from trezor.messages import ButtonRequestType
from trezor.strings import format_amount
from trezor.ui.text import Text from trezor.ui.text import Text
from trezor.utils import chunks, format_amount from trezor.utils import chunks
from apps.common.confirm import require_confirm, require_hold_to_confirm from apps.common.confirm import require_confirm, require_hold_to_confirm
from apps.common.layout import split_address from apps.common.layout import split_address

@ -1,7 +1,8 @@
from trezor import ui from trezor import ui
from trezor.messages import ButtonRequestType from trezor.messages import ButtonRequestType
from trezor.strings import format_amount
from trezor.ui.text import Text from trezor.ui.text import Text
from trezor.utils import chunks, format_amount from trezor.utils import chunks
from .helpers import get_vote_tx_text from .helpers import get_vote_tx_text

@ -2,7 +2,7 @@ import storage
import storage.device import storage.device
import storage.recovery import storage.recovery
import storage.recovery_shares import storage.recovery_shares
from trezor import utils, wire, workflow from trezor import strings, utils, wire, workflow
from trezor.crypto import slip39 from trezor.crypto import slip39
from trezor.crypto.hashlib import sha256 from trezor.crypto.hashlib import sha256
from trezor.errors import MnemonicError from trezor.errors import MnemonicError
@ -213,10 +213,7 @@ async def _request_share_next_screen(ctx: wire.GenericContext) -> None:
ctx, content, "Enter", _show_remaining_groups_and_shares ctx, content, "Enter", _show_remaining_groups_and_shares
) )
else: else:
if remaining[0] == 1: text = strings.format_plural("{count} more {plural}", remaining[0], "share")
text = "1 more share"
else:
text = "%d more shares" % remaining[0]
content = layout.RecoveryHomescreen(text, "needed to enter") content = layout.RecoveryHomescreen(text, "needed to enter")
await layout.homescreen_dialog(ctx, content, "Enter share") await layout.homescreen_dialog(ctx, content, "Enter share")

@ -1,5 +1,5 @@
import storage.recovery import storage.recovery
from trezor import ui, wire from trezor import strings, ui, wire
from trezor.crypto.slip39 import MAX_SHARE_COUNT from trezor.crypto.slip39 import MAX_SHARE_COUNT
from trezor.messages import ButtonRequestType from trezor.messages import ButtonRequestType
from trezor.messages.ButtonAck import ButtonAck from trezor.messages.ButtonAck import ButtonAck
@ -99,10 +99,11 @@ async def show_remaining_shares(
for remaining, group in groups: for remaining, group in groups:
if 0 < remaining < MAX_SHARE_COUNT: if 0 < remaining < MAX_SHARE_COUNT:
text = Text("Remaining Shares") text = Text("Remaining Shares")
if remaining > 1: text.bold(
text.bold("%s more shares starting" % remaining) strings.format_plural(
else: "{count} more {plural} starting", remaining, "share"
text.bold("%s more share starting" % remaining) )
)
for word in group: for word in group:
text.normal(word) text.normal(word)
pages.append(text) pages.append(text)
@ -111,10 +112,11 @@ async def show_remaining_shares(
): ):
text = Text("Remaining Shares") text = Text("Remaining Shares")
groups_remaining = group_threshold - shares_remaining.count(0) groups_remaining = group_threshold - shares_remaining.count(0)
if groups_remaining > 1: text.bold(
text.bold("%s more groups starting" % groups_remaining) strings.format_plural(
elif groups_remaining > 0: "{count} more {plural} starting", groups_remaining, "group"
text.bold("%s more group starting" % groups_remaining) )
)
for word in group: for word in group:
text.normal(word) text.normal(word)
pages.append(text) pages.append(text)

@ -1,4 +1,4 @@
from trezor import ui, utils from trezor import strings, ui, utils
from trezor.messages import ButtonRequestType from trezor.messages import ButtonRequestType
from trezor.messages.ButtonAck import ButtonAck from trezor.messages.ButtonAck import ButtonAck
from trezor.messages.ButtonRequest import ButtonRequest from trezor.messages.ButtonRequest import ButtonRequest
@ -59,7 +59,7 @@ def paginate_lines(lines, lines_per_page=5):
def format_amount(value): def format_amount(value):
return "%s XMR" % utils.format_amount(value, 12) return "%s XMR" % strings.format_amount(value, 12)
def split_address(address): def split_address(address):

@ -1,7 +1,7 @@
from trezor import ui from trezor import ui
from trezor.messages import ButtonRequestType from trezor.messages import ButtonRequestType
from trezor.strings import format_amount
from trezor.ui.text import Text from trezor.ui.text import Text
from trezor.utils import format_amount
from .helpers import NEM_MAX_DIVISIBILITY from .helpers import NEM_MAX_DIVISIBILITY

@ -8,8 +8,8 @@ from trezor.messages import (
NEMTransactionCommon, NEMTransactionCommon,
NEMTransfer, NEMTransfer,
) )
from trezor.strings import format_amount
from trezor.ui.text import Text from trezor.ui.text import Text
from trezor.utils import format_amount
from ..helpers import ( from ..helpers import (
NEM_LEVY_PERCENTILE_DIVISOR_ABSOLUTE, NEM_LEVY_PERCENTILE_DIVISOR_ABSOLUTE,

@ -1,7 +1,7 @@
from trezor import ui from trezor import ui
from trezor.messages import ButtonRequestType from trezor.messages import ButtonRequestType
from trezor.strings import format_amount
from trezor.ui.text import Text from trezor.ui.text import Text
from trezor.utils import format_amount
from . import helpers from . import helpers

@ -1,4 +1,4 @@
from trezor import ui, utils from trezor import strings, ui, utils
from trezor.messages import ButtonRequestType from trezor.messages import ButtonRequestType
from trezor.ui.text import Text from trezor.ui.text import Text
@ -77,7 +77,7 @@ def format_amount(amount: int, ticker=True) -> str:
t = "" t = ""
if ticker: if ticker:
t = " XLM" t = " XLM"
return utils.format_amount(amount, consts.AMOUNT_DECIMALS) + t return strings.format_amount(amount, consts.AMOUNT_DECIMALS) + t
def split(text): def split(text):

@ -1,8 +1,9 @@
from trezor import ui from trezor import ui
from trezor.messages import ButtonRequestType from trezor.messages import ButtonRequestType
from trezor.strings import format_amount
from trezor.ui.scroll import Paginated from trezor.ui.scroll import Paginated
from trezor.ui.text import Text from trezor.ui.text import Text
from trezor.utils import chunks, format_amount from trezor.utils import chunks
from apps.common.confirm import require_confirm, require_hold_to_confirm from apps.common.confirm import require_confirm, require_hold_to_confirm
from apps.tezos.helpers import TEZOS_AMOUNT_DECIMALS from apps.tezos.helpers import TEZOS_AMOUNT_DECIMALS

@ -3,7 +3,8 @@ from ubinascii import hexlify
from trezor import ui from trezor import ui
from trezor.messages import ButtonRequestType, OutputScriptType from trezor.messages import ButtonRequestType, OutputScriptType
from trezor.utils import chunks, format_amount from trezor.strings import format_amount
from trezor.utils import chunks
_LOCKTIME_TIMESTAMP_MIN_VALUE = const(500000000) _LOCKTIME_TIMESTAMP_MIN_VALUE = const(500000000)

@ -1,6 +1,6 @@
from ustruct import unpack from ustruct import unpack
from trezor.utils import format_amount from trezor.strings import format_amount
currencies = { currencies = {
1: ("OMNI", True), 1: ("OMNI", True),

@ -0,0 +1,47 @@
def format_amount(amount: int, decimals: int) -> str:
if amount < 0:
amount = -amount
sign = "-"
else:
sign = ""
d = pow(10, decimals)
s = (
("%s%d.%0*d" % (sign, amount // d, decimals, amount % d))
.rstrip("0")
.rstrip(".")
)
return s
def format_ordinal(number: int) -> str:
return str(number) + {1: "st", 2: "nd", 3: "rd"}.get(
4 if 10 <= number % 100 < 20 else number % 10, "th"
)
def format_plural(string: str, count: int, plural: str):
"""
Adds plural form to a string based on `count`.
!! Does not work with irregular words !!
Example:
>>> format_plural("We need {count} more {plural}", 3, "share")
'We need 3 more shares'
>>> format_plural("We need {count} more {plural}", 1, "share")
'We need 1 more share'
>>> format_plural("{count} {plural}", 4, "candy")
'4 candies'
"""
if not all(s in string for s in ("{count}", "{plural}")):
# string needs to have {count} and {plural} inside
raise ValueError
if count == 0 or count > 1:
if plural[-1] == "y":
plural = plural[:-1] + "ies"
elif plural[-1] in "hsxz":
plural = plural + "es"
else:
plural = plural + "s"
return string.format(count=count, plural=plural)

@ -70,27 +70,6 @@ def chunks(items: Chunkable, size: int) -> Iterator[Chunkable]:
yield items[i : i + size] yield items[i : i + size]
def format_amount(amount: int, decimals: int) -> str:
if amount < 0:
amount = -amount
sign = "-"
else:
sign = ""
d = pow(10, decimals)
s = (
("%s%d.%0*d" % (sign, amount // d, decimals, amount % d))
.rstrip("0")
.rstrip(".")
)
return s
def format_ordinal(number: int) -> str:
return str(number) + {1: "st", 2: "nd", 3: "rd"}.get(
4 if 10 <= number % 100 < 20 else number % 10, "th"
)
if False: if False:
class HashContext(Protocol): class HashContext(Protocol):

@ -0,0 +1,34 @@
from common import *
from trezor import strings
class TestStrings(unittest.TestCase):
def test_format_amount(self):
VECTORS = [
(123456, 3, "123.456"),
(4242, 7, "0.0004242"),
(-123456, 3, "-123.456"),
(-4242, 7, "-0.0004242"),
]
for v in VECTORS:
self.assertEqual(strings.format_amount(v[0], v[1]), v[2])
def test_format_plural(self):
VECTORS = [
("We need {count} more {plural}", 3, "share", "We need 3 more shares"),
("We need {count} more {plural}", 1, "share", "We need 1 more share"),
("We need {count} more {plural}", 1, "candy", "We need 1 more candy"),
("We need {count} more {plural}", 7, "candy", "We need 7 more candies"),
]
for v in VECTORS:
self.assertEqual(strings.format_plural(v[0], v[1], v[2]), v[3])
with self.assertRaises(ValueError):
strings.format_plural("Hello", 1, "share")
if __name__ == '__main__':
unittest.main()

@ -13,16 +13,6 @@ class TestUtils(unittest.TestCase):
self.assertEqual(c[i].stop, 100 if (i == 14) else (i + 1) * 7) self.assertEqual(c[i].stop, 100 if (i == 14) else (i + 1) * 7)
self.assertEqual(c[i].step, 1) self.assertEqual(c[i].step, 1)
def test_format_amount(self):
VECTORS = [
(123456, 3, "123.456"),
(4242, 7, "0.0004242"),
(-123456, 3, "-123.456"),
(-4242, 7, "-0.0004242"),
]
for v in VECTORS:
self.assertEqual(utils.format_amount(v[0], v[1]), v[2])
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main()

Loading…
Cancel
Save