1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2024-12-22 14:28:07 +00:00

Merge pull request #447 from trezor/tsusanka/utils-strings

Introduce format_plural
This commit is contained in:
Tomas Susanka 2020-01-27 10:30:44 +01:00 committed by GitHub
commit cf73d8e499
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 116 additions and 59 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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")

View File

@ -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)

View File

@ -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):

View File

@ -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

View File

@ -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,

View File

@ -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

View File

@ -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):

View File

@ -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

View File

@ -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)

View File

@ -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),

View File

@ -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) -> 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)

View File

@ -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):

View File

@ -0,0 +1,37 @@
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"),
("We need {count} more {plural}", 1, "hash", "We need 1 more hash"),
("We need {count} more {plural}", 2, "hash", "We need 2 more hashes"),
("We need {count} more {plural}", 1, "fuzz", "We need 1 more fuzz"),
("We need {count} more {plural}", 2, "fuzz", "We need 2 more fuzzes"),
]
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()

View File

@ -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()