Skip to content

Commit 6b928ad

Browse files
authored
chore: Refactor/update numeral (#74)
1 parent a900615 commit 6b928ad

File tree

1 file changed

+25
-20
lines changed

1 file changed

+25
-20
lines changed

pytils/numeral.py

Lines changed: 25 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from __future__ import annotations
77

88
from decimal import Decimal
9+
from typing import cast
910

1011
from pytils.utils import check_length, check_positive, split_values
1112

@@ -74,6 +75,8 @@
7475
FEMALE = 2 #: sex - female
7576
NEUTER = 3 #: sex - neuter
7677

78+
FORMS_COUNT = 3
79+
7780

7881
def _get_float_remainder(fvalue: int | float | Decimal, signs: int = 9) -> str:
7982
"""
@@ -146,7 +149,8 @@ def choose_plural(amount: int, variants: str | tuple[str, ...]) -> str:
146149

147150
if isinstance(variants, str):
148151
variants = split_values(variants)
149-
check_length(variants, 3)
152+
check_length(variants, FORMS_COUNT)
153+
150154
amount = abs(amount)
151155

152156
if amount % 10 == 1 and amount % 100 != 11:
@@ -235,15 +239,15 @@ def rubles(amount: int | float | Decimal, zero_for_kopeck: bool = False) -> str:
235239

236240
pts = []
237241
amount = round(amount, 2)
238-
pts.append(sum_string(int(amount), 1, ("рубль", "рубля", "рублей")))
242+
pts.append(sum_string(int(amount), MALE, ("рубль", "рубля", "рублей")))
239243
remainder = _get_float_remainder(amount, 2)
240244
iremainder = int(remainder)
241245

242246
if iremainder != 0 or zero_for_kopeck:
243247
# если 3.1, то это 10 копеек, а не одна
244248
if iremainder < 10 and len(remainder) == 1:
245249
iremainder *= 10
246-
pts.append(sum_string(iremainder, 2, ("копейка", "копейки", "копеек")))
250+
pts.append(sum_string(iremainder, FEMALE, ("копейка", "копейки", "копеек")))
247251

248252
return " ".join(pts)
249253

@@ -268,7 +272,7 @@ def in_words_int(amount: int, gender: int = MALE) -> str:
268272
return sum_string(amount, gender)
269273

270274

271-
def in_words_float(amount: float | Decimal, _gender: int = FEMALE) -> str:
275+
def in_words_float(amount: float | Decimal) -> str:
272276
"""
273277
Float in words
274278
@@ -284,11 +288,11 @@ def in_words_float(amount: float | Decimal, _gender: int = FEMALE) -> str:
284288

285289
pts = []
286290
# преобразуем целую часть
287-
pts.append(sum_string(int(amount), 2, ("целая", "целых", "целых")))
291+
pts.append(sum_string(int(amount), FEMALE, ("целая", "целых", "целых")))
288292
# теперь то, что после запятой
289293
remainder = _get_float_remainder(amount)
290294
signs = len(str(remainder)) - 1
291-
pts.append(sum_string(int(remainder), 2, FRACTIONS[signs]))
295+
pts.append(sum_string(int(remainder), FEMALE, FRACTIONS[signs]))
292296

293297
return " ".join(pts)
294298

@@ -323,7 +327,7 @@ def in_words(amount: int | float | Decimal, gender: int | None = None) -> str:
323327
return in_words_int(*args) # ty: ignore[invalid-argument-type]
324328
# если дробное
325329
elif isinstance(amount, (float, Decimal)):
326-
return in_words_float(*args) # ty: ignore[invalid-argument-type]
330+
return in_words_float(amount)
327331
# ни float, ни int, ни Decimal
328332
else:
329333
# до сюда не должно дойти
@@ -358,16 +362,17 @@ def sum_string(
358362
@raise ValueError: amount is negative
359363
"""
360364
if isinstance(items, str):
361-
items = split_values(items)
362-
if items is None:
363-
items = ("", "", "")
364-
365-
try:
366-
one_item, two_items, five_items = items
367-
except ValueError:
368-
raise ValueError("Items must be 3-element sequence")
365+
items_tuple = split_values(items)
366+
elif items is None:
367+
items_tuple = ("", "", "")
368+
else:
369+
items_tuple = items
369370

370371
check_positive(amount)
372+
check_length(items_tuple, FORMS_COUNT)
373+
items_tuple = cast(tuple[str, str, str], items_tuple)
374+
375+
_, _, five_items = items_tuple
371376

372377
if amount == 0:
373378
if five_items:
@@ -379,7 +384,7 @@ def sum_string(
379384
tmp_val = amount
380385

381386
# единицы
382-
into, tmp_val = _sum_string_fn(into, tmp_val, gender, items)
387+
into, tmp_val = _sum_string_fn(into, tmp_val, gender, items_tuple)
383388
# тысячи
384389
into, tmp_val = _sum_string_fn(into, tmp_val, FEMALE, ("тысяча", "тысячи", "тысяч"))
385390
# миллионы
@@ -396,7 +401,9 @@ def sum_string(
396401
raise ValueError("Cannot operand with numbers bigger than 10**11")
397402

398403

399-
def _sum_string_fn(into, tmp_val, gender, items=None):
404+
def _sum_string_fn(
405+
into: str, tmp_val: int, gender: int, items: tuple[str, str, str]
406+
) -> tuple[str, int]:
400407
"""
401408
Make in-words representation of single order
402409
@@ -417,9 +424,7 @@ def _sum_string_fn(into, tmp_val, gender, items=None):
417424
418425
@raise ValueError: tmp_val is negative
419426
"""
420-
if items is None:
421-
items = ("", "", "")
422-
one_item, two_items, five_items = items
427+
_, _, five_items = items
423428

424429
check_positive(tmp_val)
425430

0 commit comments

Comments
 (0)