66from __future__ import annotations
77
88from decimal import Decimal
9+ from typing import cast
910
1011from pytils .utils import check_length , check_positive , split_values
1112
7475FEMALE = 2 #: sex - female
7576NEUTER = 3 #: sex - neuter
7677
78+ FORMS_COUNT = 3
79+
7780
7881def _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