|
13 | 13 | from collections.abc import Mapping, Sequence, Generator |
14 | 14 | from ast import literal_eval |
15 | 15 | from decimal import Decimal, localcontext, InvalidOperation as InvalidDecimalOperation |
| 16 | +from fractions import Fraction |
16 | 17 | from itertools import repeat |
17 | 18 | from orderly_set import StableSetEq as SetOrderedBase # median: 1.0867 s for cache test, 5.63s for all tests |
18 | 19 | from threading import Timer |
@@ -187,14 +188,14 @@ def get_semvar_as_integer(version: str) -> int: |
187 | 188 | unicode_type = str |
188 | 189 | bytes_type = bytes |
189 | 190 | only_complex_number: Tuple[Type[Any], ...] = (complex,) + numpy_complex_numbers |
190 | | -only_numbers: Tuple[Type[Any], ...] = (int, float, complex, Decimal) + numpy_numbers |
| 191 | +only_numbers: Tuple[Type[Any], ...] = (int, float, complex, Decimal, Fraction) + numpy_numbers |
191 | 192 | datetimes: Tuple[Type[Any], ...] = (datetime.datetime, datetime.date, datetime.timedelta, datetime.time, np_datetime64) |
192 | 193 | ipranges: Tuple[Type[Any], ...] = (ipaddress.IPv4Interface, ipaddress.IPv6Interface, ipaddress.IPv4Network, ipaddress.IPv6Network, ipaddress.IPv4Address, ipaddress.IPv6Address) |
193 | 194 | uuids: Tuple[Type[uuid.UUID]] = (uuid.UUID, ) |
194 | 195 | times: Tuple[Type[Any], ...] = (datetime.datetime, datetime.time, np_datetime64) |
195 | 196 | numbers: Tuple[Type[Any], ...] = only_numbers + datetimes |
196 | 197 | # Type alias for use in type annotations |
197 | | -NumberType = Union[int, float, complex, Decimal, datetime.datetime, datetime.date, datetime.timedelta, datetime.time, Any] |
| 198 | +NumberType = Union[int, float, complex, Decimal, Fraction, datetime.datetime, datetime.date, datetime.timedelta, datetime.time, Any] |
198 | 199 | booleans: Tuple[Type[bool], Type[Any]] = (bool, np_bool_) |
199 | 200 |
|
200 | 201 | basic_types: Tuple[Type[Any], ...] = strings + numbers + uuids + booleans + (type(None), ) |
@@ -433,6 +434,11 @@ def number_to_string(number: Any, significant_digits: int, number_format_notatio |
433 | 434 | # For example '999.99999999' will become '1000.000000' after quantize |
434 | 435 | ctx.prec += 1 |
435 | 436 | number = number.quantize(Decimal('0.' + '0' * significant_digits)) |
| 437 | + elif isinstance(number, Fraction): |
| 438 | + # Convert Fraction to float so that string formatting works on Python < 3.12 |
| 439 | + number = round(float(number), significant_digits) |
| 440 | + if significant_digits == 0: |
| 441 | + number = int(number) |
436 | 442 | elif isinstance(number, only_complex_number): # type: ignore |
437 | 443 | # Case for complex numbers. |
438 | 444 | number = number.__class__( |
|
0 commit comments