|
1 | | -import locale |
2 | 1 | import inspect |
3 | 2 | import os.path |
4 | 3 | import os |
@@ -598,100 +597,6 @@ def broadcast_get(seq, row, col): |
598 | 597 | return seq |
599 | 598 |
|
600 | 599 |
|
601 | | - |
602 | | -def create_formatter(fmt): |
603 | | - """Creates a value formatter based on a format string. |
604 | | -
|
605 | | - In addition to Python builtin format specifiers, this function supports |
606 | | - the 'm' specifier which use locale-aware separators for thousands and |
607 | | - decimals (like the builtin 'n' specifier) but does not use scientific |
608 | | - format and allows specifying a fixed number of decimals, unlike the 'n' |
609 | | - specifier. |
610 | | -
|
611 | | - The desired presence of thousands separators should be given by a |
612 | | - comma (',') in the format string, whether or not a comma is the |
613 | | - separator used for the current system locale. |
614 | | -
|
615 | | - Using 'm' as the specifier in the hope that it gets one day supported by |
616 | | - CPython : https://github.com/python/cpython/issues/79819 |
617 | | -
|
618 | | - Parameters |
619 | | - ---------- |
620 | | - fmt : str |
621 | | - The format string, e.g., "{:,.2m}". |
622 | | -
|
623 | | - Returns |
624 | | - ------- |
625 | | - function |
626 | | - A function that takes a value and returns it formatted as a string. |
627 | | -
|
628 | | - References |
629 | | - ---------- |
630 | | - * https://docs.python.org/3/library/string.html#formatspec |
631 | | -
|
632 | | - Examples |
633 | | - -------- |
634 | | - >>> import locale, doctest |
635 | | - >>> try: |
636 | | - ... _ = locale.setlocale(locale.LC_NUMERIC, 'be_FR.UTF-8') |
637 | | - ... except locale.Error: |
638 | | - ... raise doctest.SkipTest("be_FR.UTF-8 locale not available") |
639 | | - >>> value = 1234.567 |
640 | | - >>> create_formatter("{:,.2f}")(value) # US style |
641 | | - '1,234.57' |
642 | | - >>> create_formatter("{:,.2m}")(value) # EU style |
643 | | - '1.234,57' |
644 | | - >>> create_formatter("{:.2f}")(value) # No thousand separator - US style |
645 | | - '1234.57' |
646 | | - >>> create_formatter("{:.2m}")(value) # No thousand separator - EU style |
647 | | - '1234,57' |
648 | | - >>> create_formatter("{:,f}")(value) # 6 decimals by default - US style |
649 | | - '1,234.567000' |
650 | | - >>> create_formatter("{:,m}")(value) # 6 decimals by default - EU style |
651 | | - '1.234,567000' |
652 | | -
|
653 | | - Robust to separators in the format string (outside the format_spec) |
654 | | -
|
655 | | - >>> create_formatter(",,, {:,.0f} ...")(value) # 0 decimals - US style |
656 | | - ',,, 1,235 ...' |
657 | | - >>> create_formatter(",,, {:,.0m} ...")(value) # 0 decimals - EU style |
658 | | - ',,, 1.235 ...' |
659 | | - """ |
660 | | - match_m_specifier = M_SPECIFIER_PATTERN.search(fmt) |
661 | | - if match_m_specifier is None: |
662 | | - return fmt.format |
663 | | - |
664 | | - locale.setlocale(locale.LC_NUMERIC, "") # Use system locale |
665 | | - localeconv = locale.localeconv() |
666 | | - locale_thousands_sep = localeconv["thousands_sep"] |
667 | | - locale_decimal_point = localeconv["decimal_point"] |
668 | | - |
669 | | - if locale_decimal_point == "." and locale_thousands_sep == ",": |
670 | | - return fmt.format |
671 | | - |
672 | | - head = fmt[:match_m_specifier.start(0)] |
673 | | - tail = fmt[match_m_specifier.end(0):] |
674 | | - field = match_m_specifier.group('field') |
675 | | - format_spec = match_m_specifier.group('format_spec') |
676 | | - value_format = f"{{{field}:{format_spec}f}}" |
677 | | - value_formatter = value_format.format |
678 | | - # use a nul byte as placeholder to avoid conflicts with other "normal" characters |
679 | | - placeholder = '\x00' |
680 | | - |
681 | | - # we intentionally do not handle *args and **kwargs because that could give the |
682 | | - # impression we support multiple {} in the format string, which we don't |
683 | | - def formatter(value): |
684 | | - # * using + is a tad faster than using ''.join in this case |
685 | | - # * chained replaces are ugly but faster than str.make_trans and then str.translate |
686 | | - return (head + |
687 | | - value_formatter(value) |
688 | | - .replace('.', placeholder) |
689 | | - .replace(',', locale_thousands_sep) |
690 | | - .replace(placeholder, locale_decimal_point) + |
691 | | - tail) |
692 | | - return formatter |
693 | | - |
694 | | - |
695 | 600 | # The following two functions (_allow_interrupt and _allow_interrupt_qt) are |
696 | 601 | # copied from matplotlib code, because they are not part of their public API |
697 | 602 | # and relying on them would require us to pin the matplotlib version, which |
|
0 commit comments