wcwidth 0.8.0__tar.gz → 0.8.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {wcwidth-0.8.0 → wcwidth-0.8.2}/PKG-INFO +17 -7
- {wcwidth-0.8.0 → wcwidth-0.8.2}/bin/update-tables.py +23 -5
- {wcwidth-0.8.0 → wcwidth-0.8.2}/code_templates/grapheme_override_per_terminal.py.j2 +1 -1
- {wcwidth-0.8.0 → wcwidth-0.8.2}/code_templates/grapheme_registry.py.j2 +1 -1
- {wcwidth-0.8.0 → wcwidth-0.8.2}/code_templates/table_overrides.py.j2 +7 -4
- {wcwidth-0.8.0 → wcwidth-0.8.2}/docs/intro.rst +16 -6
- {wcwidth-0.8.0 → wcwidth-0.8.2}/docs/specs.rst +2 -2
- {wcwidth-0.8.0 → wcwidth-0.8.2}/pyproject.toml +1 -1
- {wcwidth-0.8.0 → wcwidth-0.8.2}/tests/test_core.py +6 -0
- {wcwidth-0.8.0 → wcwidth-0.8.2}/tests/test_term_overrides.py +105 -1
- {wcwidth-0.8.0 → wcwidth-0.8.2}/ucs-detect/data/alacritty.yaml +97 -31
- {wcwidth-0.8.0 → wcwidth-0.8.2}/ucs-detect/data/bobcat.yaml +31 -7
- wcwidth-0.8.0/ucs-detect/data/extraterm.yaml → wcwidth-0.8.2/ucs-detect/data/conemu.exe.yaml +1072 -625
- {wcwidth-0.8.0 → wcwidth-0.8.2}/ucs-detect/data/contour.yaml +10809 -5811
- wcwidth-0.8.2/ucs-detect/data/coolretroterm.yaml +10734 -0
- wcwidth-0.8.2/ucs-detect/data/emoji-test-latest.txt +5518 -0
- wcwidth-0.8.2/ucs-detect/data/emoji-variation-sequences-latest.txt +757 -0
- wcwidth-0.8.2/ucs-detect/data/emoji-zwj-sequences-latest.txt +1675 -0
- wcwidth-0.8.0/ucs-detect/data/conemu.exe.yaml → wcwidth-0.8.2/ucs-detect/data/extraterm.yaml +20909 -16815
- {wcwidth-0.8.0 → wcwidth-0.8.2}/ucs-detect/data/foot.yaml +61 -139
- {wcwidth-0.8.0 → wcwidth-0.8.2}/ucs-detect/data/ghostty.yaml +32 -23
- wcwidth-0.8.0/ucs-detect/data/xfce4terminal.yaml → wcwidth-0.8.2/ucs-detect/data/gnometerminal.yaml +4807 -1580
- {wcwidth-0.8.0 → wcwidth-0.8.2}/ucs-detect/data/hyper.yaml +899 -827
- {wcwidth-0.8.0 → wcwidth-0.8.2}/ucs-detect/data/iterm2.yaml +15 -27
- {wcwidth-0.8.0 → wcwidth-0.8.2}/ucs-detect/data/kitty.yaml +293 -221
- {wcwidth-0.8.0 → wcwidth-0.8.2}/ucs-detect/data/konsole.yaml +1845 -408
- {wcwidth-0.8.0 → wcwidth-0.8.2}/ucs-detect/data/libvterm.yaml +7624 -5719
- {wcwidth-0.8.0 → wcwidth-0.8.2}/ucs-detect/data/lxterminal.yaml +1206 -1134
- wcwidth-0.8.0/ucs-detect/data/terminology.yaml → wcwidth-0.8.2/ucs-detect/data/mintty.yaml +5186 -5682
- {wcwidth-0.8.0 → wcwidth-0.8.2}/ucs-detect/data/mlterm.yaml +8223 -5451
- {wcwidth-0.8.0 → wcwidth-0.8.2}/ucs-detect/data/putty.yaml +65 -41
- {wcwidth-0.8.0 → wcwidth-0.8.2}/ucs-detect/data/qterminal.yaml +3290 -2531
- {wcwidth-0.8.0 → wcwidth-0.8.2}/ucs-detect/data/rio.yaml +5820 -4398
- {wcwidth-0.8.0 → wcwidth-0.8.2}/ucs-detect/data/rxvtunicode.yaml +46 -136
- {wcwidth-0.8.0 → wcwidth-0.8.2}/ucs-detect/data/screen.yaml +10626 -9206
- {wcwidth-0.8.0 → wcwidth-0.8.2}/ucs-detect/data/st.yaml +45 -135
- {wcwidth-0.8.0 → wcwidth-0.8.2}/ucs-detect/data/tabby.yaml +6382 -4876
- {wcwidth-0.8.0 → wcwidth-0.8.2}/ucs-detect/data/teraterm.yaml +11 -5
- {wcwidth-0.8.0 → wcwidth-0.8.2}/ucs-detect/data/terminalapp.yaml +14 -8
- wcwidth-0.8.2/ucs-detect/data/terminalexe.yaml +3078 -0
- {wcwidth-0.8.0 → wcwidth-0.8.2}/ucs-detect/data/terminator.yaml +4024 -1781
- wcwidth-0.8.2/ucs-detect/data/terminology.yaml +31854 -0
- {wcwidth-0.8.0 → wcwidth-0.8.2}/ucs-detect/data/tmux.yaml +2003 -527
- {wcwidth-0.8.0 → wcwidth-0.8.2}/ucs-detect/data/warp.yaml +6827 -4568
- {wcwidth-0.8.0 → wcwidth-0.8.2}/ucs-detect/data/wezterm.yaml +309 -303
- wcwidth-0.8.0/ucs-detect/data/gnometerminal.yaml → wcwidth-0.8.2/ucs-detect/data/xfce4terminal.yaml +1558 -1613
- {wcwidth-0.8.0 → wcwidth-0.8.2}/ucs-detect/data/xterm.yaml +44 -131
- {wcwidth-0.8.0 → wcwidth-0.8.2}/ucs-detect/data/zellij.yaml +6607 -5224
- {wcwidth-0.8.0 → wcwidth-0.8.2}/ucs-detect/data/zutty.yaml +74 -167
- {wcwidth-0.8.0 → wcwidth-0.8.2}/wcwidth/__init__.py +1 -1
- {wcwidth-0.8.0 → wcwidth-0.8.2}/wcwidth/_constants.py +17 -4
- {wcwidth-0.8.0 → wcwidth-0.8.2}/wcwidth/_wcswidth.py +14 -2
- {wcwidth-0.8.0 → wcwidth-0.8.2}/wcwidth/_width.py +12 -0
- wcwidth-0.8.0/wcwidth/table_grapheme_overrides/_known_c0d5dc9e.py → wcwidth-0.8.2/wcwidth/table_grapheme_overrides/_known_3d4826b8.py +6068 -6033
- {wcwidth-0.8.0 → wcwidth-0.8.2}/wcwidth/table_grapheme_overrides/_registry.py +1 -1
- {wcwidth-0.8.0 → wcwidth-0.8.2}/wcwidth/table_overrides.py +408 -269
- wcwidth-0.8.0/ucs-detect/data/coolretroterm.yaml +0 -10905
- wcwidth-0.8.0/ucs-detect/data/mintty.yaml +0 -27871
- wcwidth-0.8.0/ucs-detect/data/terminalexe.yaml +0 -5649
- {wcwidth-0.8.0 → wcwidth-0.8.2}/.gitignore +0 -0
- {wcwidth-0.8.0 → wcwidth-0.8.2}/.pylintrc +0 -0
- {wcwidth-0.8.0 → wcwidth-0.8.2}/LICENSE +0 -0
- {wcwidth-0.8.0 → wcwidth-0.8.2}/README.rst +0 -0
- {wcwidth-0.8.0 → wcwidth-0.8.2}/bin/show-sequences +0 -0
- {wcwidth-0.8.0 → wcwidth-0.8.2}/bin/strip-sequences +0 -0
- {wcwidth-0.8.0 → wcwidth-0.8.2}/bin/verify-table-integrity.py +0 -0
- {wcwidth-0.8.0 → wcwidth-0.8.2}/bin/wcwidth-browser.py +0 -0
- {wcwidth-0.8.0 → wcwidth-0.8.2}/bin/wcwidth-libc-comparator.py +0 -0
- {wcwidth-0.8.0 → wcwidth-0.8.2}/code_templates/grapheme_override_table.py.j2 +0 -0
- {wcwidth-0.8.0 → wcwidth-0.8.2}/code_templates/grapheme_table.py.j2 +0 -0
- {wcwidth-0.8.0 → wcwidth-0.8.2}/code_templates/python_table.py.j2 +0 -0
- {wcwidth-0.8.0 → wcwidth-0.8.2}/code_templates/term_programs.py.j2 +0 -0
- {wcwidth-0.8.0 → wcwidth-0.8.2}/code_templates/unicode_version.rst.j2 +0 -0
- {wcwidth-0.8.0 → wcwidth-0.8.2}/code_templates/unicode_versions.py.j2 +0 -0
- {wcwidth-0.8.0 → wcwidth-0.8.2}/docs/api.rst +0 -0
- {wcwidth-0.8.0 → wcwidth-0.8.2}/docs/conf.py +0 -0
- {wcwidth-0.8.0 → wcwidth-0.8.2}/docs/index.rst +0 -0
- {wcwidth-0.8.0 → wcwidth-0.8.2}/docs/requirements.txt +0 -0
- {wcwidth-0.8.0 → wcwidth-0.8.2}/docs/unicode_version.rst +0 -0
- {wcwidth-0.8.0 → wcwidth-0.8.2}/requirements-develop.txt +0 -0
- {wcwidth-0.8.0 → wcwidth-0.8.2}/requirements-docs.in +0 -0
- {wcwidth-0.8.0 → wcwidth-0.8.2}/requirements-tests38.in +0 -0
- {wcwidth-0.8.0 → wcwidth-0.8.2}/requirements-tests38.txt +0 -0
- {wcwidth-0.8.0 → wcwidth-0.8.2}/requirements-tests39.in +0 -0
- {wcwidth-0.8.0 → wcwidth-0.8.2}/requirements-tests39.txt +0 -0
- {wcwidth-0.8.0 → wcwidth-0.8.2}/requirements-update.in +0 -0
- {wcwidth-0.8.0 → wcwidth-0.8.2}/requirements-update.txt +0 -0
- {wcwidth-0.8.0 → wcwidth-0.8.2}/tests/__init__.py +0 -0
- {wcwidth-0.8.0 → wcwidth-0.8.2}/tests/conftest.py +0 -0
- {wcwidth-0.8.0 → wcwidth-0.8.2}/tests/test_ambiguous.py +0 -0
- {wcwidth-0.8.0 → wcwidth-0.8.2}/tests/test_benchmarks.py +0 -0
- {wcwidth-0.8.0 → wcwidth-0.8.2}/tests/test_clip.py +0 -0
- {wcwidth-0.8.0 → wcwidth-0.8.2}/tests/test_clip_cjk_emoji.py +0 -0
- {wcwidth-0.8.0 → wcwidth-0.8.2}/tests/test_clip_overtyping.py +0 -0
- {wcwidth-0.8.0 → wcwidth-0.8.2}/tests/test_emojis.py +0 -0
- {wcwidth-0.8.0 → wcwidth-0.8.2}/tests/test_grapheme.py +0 -0
- {wcwidth-0.8.0 → wcwidth-0.8.2}/tests/test_hyperlink.py +0 -0
- {wcwidth-0.8.0 → wcwidth-0.8.2}/tests/test_justify.py +0 -0
- {wcwidth-0.8.0 → wcwidth-0.8.2}/tests/test_sgr_state.py +0 -0
- {wcwidth-0.8.0 → wcwidth-0.8.2}/tests/test_text_sizing.py +0 -0
- {wcwidth-0.8.0 → wcwidth-0.8.2}/tests/test_textwrap.py +0 -0
- {wcwidth-0.8.0 → wcwidth-0.8.2}/tests/test_ucslevel.py +0 -0
- {wcwidth-0.8.0 → wcwidth-0.8.2}/tests/test_width.py +0 -0
- {wcwidth-0.8.0 → wcwidth-0.8.2}/tox.ini +0 -0
- {wcwidth-0.8.0 → wcwidth-0.8.2}/ucs-detect/data/AbsoluteTelnetSSH.yaml +0 -0
- {wcwidth-0.8.0 → wcwidth-0.8.2}/ucs-detect/data/_linuxfbdev.yaml +0 -0
- {wcwidth-0.8.0 → wcwidth-0.8.2}/ucs-detect/data/_syncterm.yaml +0 -0
- {wcwidth-0.8.0 → wcwidth-0.8.2}/ucs-detect/data/securecrt.yaml +0 -0
- {wcwidth-0.8.0 → wcwidth-0.8.2}/ucs-detect/data/vscodeterminal.yaml +0 -0
- {wcwidth-0.8.0 → wcwidth-0.8.2}/ucs-detect/data/westonterminal.yaml +0 -0
- {wcwidth-0.8.0 → wcwidth-0.8.2}/wcwidth/_clip.py +0 -0
- {wcwidth-0.8.0 → wcwidth-0.8.2}/wcwidth/_wcwidth.py +0 -0
- {wcwidth-0.8.0 → wcwidth-0.8.2}/wcwidth/align.py +0 -0
- {wcwidth-0.8.0 → wcwidth-0.8.2}/wcwidth/bisearch.py +0 -0
- {wcwidth-0.8.0 → wcwidth-0.8.2}/wcwidth/control_codes.py +0 -0
- {wcwidth-0.8.0 → wcwidth-0.8.2}/wcwidth/escape_sequences.py +0 -0
- {wcwidth-0.8.0 → wcwidth-0.8.2}/wcwidth/grapheme.py +0 -0
- {wcwidth-0.8.0 → wcwidth-0.8.2}/wcwidth/hyperlink.py +0 -0
- {wcwidth-0.8.0 → wcwidth-0.8.2}/wcwidth/py.typed +0 -0
- {wcwidth-0.8.0 → wcwidth-0.8.2}/wcwidth/sgr_state.py +0 -0
- {wcwidth-0.8.0 → wcwidth-0.8.2}/wcwidth/table_ambiguous.py +0 -0
- {wcwidth-0.8.0 → wcwidth-0.8.2}/wcwidth/table_grapheme.py +0 -0
- {wcwidth-0.8.0 → wcwidth-0.8.2}/wcwidth/table_grapheme_overrides/__init__.py +0 -0
- {wcwidth-0.8.0 → wcwidth-0.8.2}/wcwidth/table_grapheme_overrides/_known_27e0693f.py +2478 -2478
- {wcwidth-0.8.0 → wcwidth-0.8.2}/wcwidth/table_grapheme_overrides/_known_45d92e98.py +1677 -1677
- {wcwidth-0.8.0 → wcwidth-0.8.2}/wcwidth/table_grapheme_overrides/_known_4cdf59ce.py +0 -0
- {wcwidth-0.8.0 → wcwidth-0.8.2}/wcwidth/table_grapheme_overrides/_known_50bf0759.py +2437 -2437
- {wcwidth-0.8.0 → wcwidth-0.8.2}/wcwidth/table_grapheme_overrides/_known_529fbb4a.py +1470 -1470
- {wcwidth-0.8.0 → wcwidth-0.8.2}/wcwidth/table_grapheme_overrides/_known_5bfac390.py +2437 -2437
- {wcwidth-0.8.0 → wcwidth-0.8.2}/wcwidth/table_grapheme_overrides/_known_813fee16.py +2437 -2437
- {wcwidth-0.8.0 → wcwidth-0.8.2}/wcwidth/table_grapheme_overrides/_known_8589765c.py +870 -870
- {wcwidth-0.8.0 → wcwidth-0.8.2}/wcwidth/table_grapheme_overrides/_known_8f94b404.py +2437 -2437
- {wcwidth-0.8.0 → wcwidth-0.8.2}/wcwidth/table_grapheme_overrides/_known_970dbe10.py +2693 -2693
- {wcwidth-0.8.0 → wcwidth-0.8.2}/wcwidth/table_grapheme_overrides/_known_c0a2cdbf.py +3246 -3246
- {wcwidth-0.8.0 → wcwidth-0.8.2}/wcwidth/table_grapheme_overrides/_known_c2157f7e.py +906 -906
- {wcwidth-0.8.0 → wcwidth-0.8.2}/wcwidth/table_grapheme_overrides/_known_c3db41c0.py +3199 -3199
- {wcwidth-0.8.0 → wcwidth-0.8.2}/wcwidth/table_grapheme_overrides/_known_da9ceb0a.py +1598 -1598
- {wcwidth-0.8.0 → wcwidth-0.8.2}/wcwidth/table_grapheme_overrides/_known_e08bd75e.py +2461 -2461
- {wcwidth-0.8.0 → wcwidth-0.8.2}/wcwidth/table_grapheme_overrides/_known_e22030f3.py +5927 -5927
- {wcwidth-0.8.0 → wcwidth-0.8.2}/wcwidth/table_grapheme_overrides/_known_fcc05a0f.py +6173 -6173
- {wcwidth-0.8.0 → wcwidth-0.8.2}/wcwidth/table_grapheme_overrides/_known_fd9d4c44.py +3300 -3300
- {wcwidth-0.8.0 → wcwidth-0.8.2}/wcwidth/table_mc.py +0 -0
- {wcwidth-0.8.0 → wcwidth-0.8.2}/wcwidth/table_term_programs.py +0 -0
- {wcwidth-0.8.0 → wcwidth-0.8.2}/wcwidth/table_vs15.py +0 -0
- {wcwidth-0.8.0 → wcwidth-0.8.2}/wcwidth/table_vs16.py +0 -0
- {wcwidth-0.8.0 → wcwidth-0.8.2}/wcwidth/table_wide.py +0 -0
- {wcwidth-0.8.0 → wcwidth-0.8.2}/wcwidth/table_zero.py +0 -0
- {wcwidth-0.8.0 → wcwidth-0.8.2}/wcwidth/text_sizing.py +0 -0
- {wcwidth-0.8.0 → wcwidth-0.8.2}/wcwidth/textwrap.py +0 -0
- {wcwidth-0.8.0 → wcwidth-0.8.2}/wcwidth/unicode_versions.py +0 -0
- {wcwidth-0.8.0 → wcwidth-0.8.2}/wcwidth/wcwidth.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: wcwidth
|
|
3
|
-
Version: 0.8.
|
|
3
|
+
Version: 0.8.2
|
|
4
4
|
Summary: Measures the displayed width of unicode strings in a terminal
|
|
5
5
|
Project-URL: Homepage, https://github.com/jquast/wcwidth
|
|
6
6
|
Author-email: Jeff Quast <contact@jeffquast.com>
|
|
@@ -104,7 +104,7 @@ See also:
|
|
|
104
104
|
- `Grapheme Clusters and Terminal Emulators`_
|
|
105
105
|
- `terminal-unicode-core.tex`_
|
|
106
106
|
- `State of Terminal Emulators in 2025`_
|
|
107
|
-
- `
|
|
107
|
+
- `Perfecting Terminal Character Width Using Correction Tables (2026)`_
|
|
108
108
|
|
|
109
109
|
The `jquast/ucs-detect`_ project publishes automatic results of compliance to our standard for Wide
|
|
110
110
|
character, Languages, grapheme clustering, complex or combining scripts, emojis, zero-width joiner,
|
|
@@ -448,9 +448,10 @@ possible timeout, slow network, or non-response when working with "dumb terminal
|
|
|
448
448
|
Corrections
|
|
449
449
|
-----------
|
|
450
450
|
|
|
451
|
-
Corrections
|
|
451
|
+
Corrections may be automatically applied depending on the detected or given terminal software name
|
|
452
452
|
beginning with wcwidth release 0.8.0. This allows to correct widths for terminal software that
|
|
453
|
-
differs from the
|
|
453
|
+
differs from the python wcwidth specification_. These corrections are sourced from the
|
|
454
|
+
`jquast/ucs-detect`_ project.
|
|
454
455
|
|
|
455
456
|
The ``term_program`` parameter is available on all width-measuring functions: `wcstwidth()`_,
|
|
456
457
|
`width()`_, `ljust()`_, `rjust()`_, `center()`_, `wrap()`_, and `clip()`_.
|
|
@@ -684,10 +685,18 @@ languages:
|
|
|
684
685
|
History
|
|
685
686
|
=======
|
|
686
687
|
|
|
687
|
-
0.8.
|
|
688
|
+
0.8.2 *2026-06-29*
|
|
689
|
+
* **Bugfix** Do not raise IndexError when given legacy POSIX ``n`` argument to `wcswidth()`_ or
|
|
690
|
+
`wcstwidth()`_ exceed string length without raising IndexError
|
|
691
|
+
|
|
692
|
+
0.8.1 *2026-06-08*
|
|
693
|
+
* **Improved** `wcstwidth()`_ with new ``zeroer``, ``narrow_wider``, and ``narrow_zeroer``
|
|
694
|
+
Corrections_. `PR #226`_
|
|
695
|
+
|
|
696
|
+
0.8.0 *2026-06-05*
|
|
688
697
|
* **New** support for Variation Selector 15 Emojis as narrow, `Issue #211`_.
|
|
689
698
|
* **New** argument, ``term_program`` for `wcstwidth()`_, `width()`_, `clip()`_, `wrap()`_,
|
|
690
|
-
`ljust()`_, `rjust()`_, and `center()`_. ``False`` disables
|
|
699
|
+
`ljust()`_, `rjust()`_, and `center()`_. ``False`` disables Corrections_; ``True``
|
|
691
700
|
auto-detects by ``TERM_PROGRAM`` or ``TERM``; string values accept canonical names matching
|
|
692
701
|
`list_term_programs()`_. `wcstwidth()`_ defaults to ``True``; all other functions
|
|
693
702
|
default to ``False``.
|
|
@@ -932,6 +941,7 @@ https://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c::
|
|
|
932
941
|
.. _`PR #221`: https://github.com/jquast/wcwidth/pull/221
|
|
933
942
|
.. _`PR #223`: https://github.com/jquast/wcwidth/pull/223
|
|
934
943
|
.. _`PR #224`: https://github.com/jquast/wcwidth/pull/224
|
|
944
|
+
.. _`PR #226`: https://github.com/jquast/wcwidth/pull/226
|
|
935
945
|
.. _`Issue #101`: https://github.com/jquast/wcwidth/issues/101
|
|
936
946
|
.. _`Issue #155`: https://github.com/jquast/wcwidth/issues/155
|
|
937
947
|
.. _`Issue #190`: https://github.com/jquast/wcwidth/issues/190
|
|
@@ -1011,7 +1021,7 @@ https://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c::
|
|
|
1011
1021
|
.. _`Grapheme Clusters and Terminal Emulators`: https://mitchellh.com/writing/grapheme-clusters-in-terminals
|
|
1012
1022
|
.. _`terminal-unicode-core.tex`: https://github.com/contour-terminal/terminal-unicode-core/blob/master/spec/terminal-unicode-core.tex
|
|
1013
1023
|
.. _`State of Terminal Emulators in 2025`: https://www.jeffquast.com/post/state-of-terminal-emulation-2025/
|
|
1014
|
-
.. _`
|
|
1024
|
+
.. _`Perfecting Terminal Character Width Using Correction Tables (2026)`: https://www.jeffquast.com/post/perfecting-terminal-character-width-using-correction-tables/
|
|
1015
1025
|
.. _XTVERSION: https://vtdn.dev/docs/dcs/xtversion/
|
|
1016
1026
|
.. _ENQ: https://documentation.help/PuTTY/config-answerback.html
|
|
1017
1027
|
.. _detectable: https://ucs-detect.readthedocs.io/results.html#terminal-identification
|
|
@@ -1246,12 +1246,17 @@ def parse_wchar_codepoint(wchar: str) -> int:
|
|
|
1246
1246
|
|
|
1247
1247
|
@dataclass(frozen=True)
|
|
1248
1248
|
class TerminalOverrides:
|
|
1249
|
-
"""Per-terminal codepoint override ranges for narrower/wider measurements."""
|
|
1249
|
+
"""Per-terminal codepoint override ranges for narrower/wider/zeroer measurements."""
|
|
1250
1250
|
narrower: list[tuple[str, str, str]]
|
|
1251
1251
|
wider: list[tuple[str, str, str]]
|
|
1252
|
+
zeroer: list[tuple[str, str, str]]
|
|
1253
|
+
narrow_zeroer: list[tuple[str, str, str]]
|
|
1252
1254
|
|
|
1253
1255
|
def items(self) -> list[tuple[str, list[tuple[str, str, str]]]]:
|
|
1254
|
-
return [('narrower', self.narrower),
|
|
1256
|
+
return [('narrower', self.narrower),
|
|
1257
|
+
('wider', self.wider),
|
|
1258
|
+
('zeroer', self.zeroer),
|
|
1259
|
+
('narrow_zeroer', self.narrow_zeroer)]
|
|
1255
1260
|
|
|
1256
1261
|
|
|
1257
1262
|
@dataclass(frozen=True)
|
|
@@ -1269,7 +1274,9 @@ def dedup_override_table(
|
|
|
1269
1274
|
terminal_refs: dict[str, str] = {}
|
|
1270
1275
|
for term_name, overrides in table.items():
|
|
1271
1276
|
key = (tuple(overrides.narrower),
|
|
1272
|
-
tuple(overrides.wider)
|
|
1277
|
+
tuple(overrides.wider),
|
|
1278
|
+
tuple(overrides.zeroer),
|
|
1279
|
+
tuple(overrides.narrow_zeroer))
|
|
1273
1280
|
hash_key = hashlib.sha256(repr(key).encode()).hexdigest()[:8]
|
|
1274
1281
|
if hash_key not in shared_sets:
|
|
1275
1282
|
shared_sets[hash_key] = overrides
|
|
@@ -1405,11 +1412,14 @@ def make_single_override(
|
|
|
1405
1412
|
|
|
1406
1413
|
Returns a dict mapping canonical_name to 'TerminalOverrides'.
|
|
1407
1414
|
|
|
1415
|
+
- 'zeroer' means terminal measured 0, but wcwidth measured 2,
|
|
1408
1416
|
- 'narrower' means terminal measured 1, but wcwidth measured 2,
|
|
1409
1417
|
- 'wider' means terminal measured 2, but wcwidth measured 1.
|
|
1410
1418
|
"""
|
|
1419
|
+
zeroer: dict[str, set[int]] = {}
|
|
1411
1420
|
narrower: dict[str, set[int]] = {}
|
|
1412
1421
|
wider: dict[str, set[int]] = {}
|
|
1422
|
+
narrow_zeroer_map: dict[str, set[int]] = {}
|
|
1413
1423
|
|
|
1414
1424
|
for _, canonical, doc in load_ucs_detect_yaml():
|
|
1415
1425
|
test_results = doc.get('test_results', {})
|
|
@@ -1420,7 +1430,11 @@ def make_single_override(
|
|
|
1420
1430
|
ucs = parse_wchar_codepoint(wchar)
|
|
1421
1431
|
term_w = entry['measured_by_terminal']
|
|
1422
1432
|
wc_w = entry['measured_by_wcwidth']
|
|
1423
|
-
if term_w ==
|
|
1433
|
+
if term_w == 0 and wc_w == 2:
|
|
1434
|
+
zeroer.setdefault(canonical, set()).add(ucs)
|
|
1435
|
+
elif term_w == 0 and wc_w == 1 and category == 'narrow_results':
|
|
1436
|
+
narrow_zeroer_map.setdefault(canonical, set()).add(ucs)
|
|
1437
|
+
elif term_w == 1 and wc_w == 2:
|
|
1424
1438
|
narrower.setdefault(canonical, set()).add(ucs)
|
|
1425
1439
|
# 'wider' entries in emoji_vs16_results are from the vs16n baseline test
|
|
1426
1440
|
# (base character measured without VS16, expected width 1). Kitty rendering
|
|
@@ -1431,11 +1445,14 @@ def make_single_override(
|
|
|
1431
1445
|
wider.setdefault(canonical, set()).add(ucs)
|
|
1432
1446
|
|
|
1433
1447
|
result: dict[str, TerminalOverrides] = {}
|
|
1434
|
-
all_names = sorted(set(narrower.keys()) | set(wider.keys())
|
|
1448
|
+
all_names = sorted(set(zeroer.keys()) | set(narrower.keys()) | set(wider.keys())
|
|
1449
|
+
| set(narrow_zeroer_map.keys()))
|
|
1435
1450
|
for name in all_names:
|
|
1436
1451
|
result[name] = TerminalOverrides(
|
|
1437
1452
|
narrower=values_to_hex_ranges(narrower.get(name, set())),
|
|
1438
1453
|
wider=values_to_hex_ranges(wider.get(name, set())),
|
|
1454
|
+
zeroer=values_to_hex_ranges(zeroer.get(name, set())),
|
|
1455
|
+
narrow_zeroer=values_to_hex_ranges(narrow_zeroer_map.get(name, set())),
|
|
1439
1456
|
)
|
|
1440
1457
|
result = {
|
|
1441
1458
|
name: data for name, data in result.items()
|
|
@@ -1809,6 +1826,7 @@ def main(only_fetch: bool = False, fetch_all_versions: bool = False,
|
|
|
1809
1826
|
_make_merged_category('SFZ_OVERRIDES', make_single_override('sfz_results', kt)),
|
|
1810
1827
|
_make_merged_category('VS16_OVERRIDES', make_single_override('emoji_vs16_results', kt)),
|
|
1811
1828
|
_make_merged_category('VS15_OVERRIDES', make_single_override('emoji_vs15_results', kt)),
|
|
1829
|
+
_make_merged_category('NARROW_OVERRIDES', make_single_override('narrow_results', kt)),
|
|
1812
1830
|
])
|
|
1813
1831
|
yield from fetch_override_grapheme_data(kt)
|
|
1814
1832
|
yield TermProgramTableRenderDef.new()
|
|
@@ -7,7 +7,7 @@ Terminals: {{ terminals|join(', ') }}
|
|
|
7
7
|
"""
|
|
8
8
|
# pylint: skip-file
|
|
9
9
|
GRAPHEMES = {
|
|
10
|
-
{%- for grapheme_str, terminal_width in graphemes
|
|
10
|
+
{%- for grapheme_str, terminal_width in graphemes | dictsort %}
|
|
11
11
|
'{{ grapheme_str }}': {{ terminal_width }},
|
|
12
12
|
{%- endfor %}
|
|
13
13
|
}
|
|
@@ -5,7 +5,7 @@ This code generated by python wcwidth using ucs-detect project data.
|
|
|
5
5
|
"""
|
|
6
6
|
# pylint: skip-file
|
|
7
7
|
_REGISTRY = {
|
|
8
|
-
{%- for terminal, hash_key in registry
|
|
8
|
+
{%- for terminal, hash_key in registry | dictsort %}
|
|
9
9
|
{{ terminal.__repr__() }}: {{ hash_key.__repr__() }},
|
|
10
10
|
{%- endfor %}
|
|
11
11
|
}
|
|
@@ -4,30 +4,33 @@ Terminal override tables keyed by canonical terminal software name.
|
|
|
4
4
|
This code generated by python wcwidth using ucs-detect project data.
|
|
5
5
|
"""
|
|
6
6
|
# pylint: skip-file
|
|
7
|
+
from __future__ import annotations
|
|
7
8
|
{%- for category in categories %}
|
|
8
9
|
{%- set varname = category.variable_name -%}
|
|
9
10
|
{%- set shared_sets = category.shared_sets -%}
|
|
10
11
|
{%- set terminal_refs = category.terminal_refs -%}
|
|
11
12
|
{%- set set_terminals = category.set_terminals -%}
|
|
12
13
|
{%- if shared_sets %}
|
|
13
|
-
{%- for hash_key, overrides in shared_sets
|
|
14
|
+
{%- for hash_key, overrides in shared_sets | dictsort %}
|
|
14
15
|
{%- set terminals = set_terminals.get(hash_key, ()) %}
|
|
15
16
|
|
|
16
17
|
# For terminals: {{ terminals | join(', ') }}
|
|
17
|
-
_SET_{{ varname }}_{{ hash_key | upper }} = {
|
|
18
|
+
_SET_{{ varname }}_{{ hash_key | upper }}: dict[str, tuple[tuple[int, int], ...]] = {
|
|
18
19
|
{%- for direction, ranges in overrides.items() %}
|
|
20
|
+
{%- if ranges %}
|
|
19
21
|
'{{ direction }}': (
|
|
20
22
|
{%- for hex_start, hex_end, txt_description in ranges %}
|
|
21
23
|
({{ hex_start }}, {{ hex_end }},), # {{ txt_description }}
|
|
22
24
|
{%- endfor %}
|
|
23
25
|
),
|
|
26
|
+
{%- endif %}
|
|
24
27
|
{%- endfor %}
|
|
25
28
|
}
|
|
26
29
|
{%- endfor %}
|
|
27
30
|
{%- endif %}
|
|
28
31
|
|
|
29
|
-
{{ varname }} = {
|
|
30
|
-
{%- for term_name, hash_key in terminal_refs
|
|
32
|
+
{{ varname }}: dict[str, dict[str, tuple[tuple[int, int], ...]]] = {
|
|
33
|
+
{%- for term_name, hash_key in terminal_refs | dictsort %}
|
|
31
34
|
'{{ term_name }}': _SET_{{ varname }}_{{ hash_key | upper }},
|
|
32
35
|
{%- endfor %}
|
|
33
36
|
}
|
|
@@ -73,7 +73,7 @@ See also:
|
|
|
73
73
|
- `Grapheme Clusters and Terminal Emulators`_
|
|
74
74
|
- `terminal-unicode-core.tex`_
|
|
75
75
|
- `State of Terminal Emulators in 2025`_
|
|
76
|
-
- `
|
|
76
|
+
- `Perfecting Terminal Character Width Using Correction Tables (2026)`_
|
|
77
77
|
|
|
78
78
|
The `jquast/ucs-detect`_ project publishes automatic results of compliance to our standard for Wide
|
|
79
79
|
character, Languages, grapheme clustering, complex or combining scripts, emojis, zero-width joiner,
|
|
@@ -417,9 +417,10 @@ possible timeout, slow network, or non-response when working with "dumb terminal
|
|
|
417
417
|
Corrections
|
|
418
418
|
-----------
|
|
419
419
|
|
|
420
|
-
Corrections
|
|
420
|
+
Corrections may be automatically applied depending on the detected or given terminal software name
|
|
421
421
|
beginning with wcwidth release 0.8.0. This allows to correct widths for terminal software that
|
|
422
|
-
differs from the
|
|
422
|
+
differs from the python wcwidth specification_. These corrections are sourced from the
|
|
423
|
+
`jquast/ucs-detect`_ project.
|
|
423
424
|
|
|
424
425
|
The ``term_program`` parameter is available on all width-measuring functions: `wcstwidth()`_,
|
|
425
426
|
`width()`_, `ljust()`_, `rjust()`_, `center()`_, `wrap()`_, and `clip()`_.
|
|
@@ -653,10 +654,18 @@ languages:
|
|
|
653
654
|
History
|
|
654
655
|
=======
|
|
655
656
|
|
|
656
|
-
0.8.
|
|
657
|
+
0.8.2 *2026-06-29*
|
|
658
|
+
* **Bugfix** Do not raise IndexError when given legacy POSIX ``n`` argument to `wcswidth()`_ or
|
|
659
|
+
`wcstwidth()`_ exceed string length without raising IndexError
|
|
660
|
+
|
|
661
|
+
0.8.1 *2026-06-08*
|
|
662
|
+
* **Improved** `wcstwidth()`_ with new ``zeroer``, ``narrow_wider``, and ``narrow_zeroer``
|
|
663
|
+
Corrections_. `PR #226`_
|
|
664
|
+
|
|
665
|
+
0.8.0 *2026-06-05*
|
|
657
666
|
* **New** support for Variation Selector 15 Emojis as narrow, `Issue #211`_.
|
|
658
667
|
* **New** argument, ``term_program`` for `wcstwidth()`_, `width()`_, `clip()`_, `wrap()`_,
|
|
659
|
-
`ljust()`_, `rjust()`_, and `center()`_. ``False`` disables
|
|
668
|
+
`ljust()`_, `rjust()`_, and `center()`_. ``False`` disables Corrections_; ``True``
|
|
660
669
|
auto-detects by ``TERM_PROGRAM`` or ``TERM``; string values accept canonical names matching
|
|
661
670
|
`list_term_programs()`_. `wcstwidth()`_ defaults to ``True``; all other functions
|
|
662
671
|
default to ``False``.
|
|
@@ -901,6 +910,7 @@ https://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c::
|
|
|
901
910
|
.. _`PR #221`: https://github.com/jquast/wcwidth/pull/221
|
|
902
911
|
.. _`PR #223`: https://github.com/jquast/wcwidth/pull/223
|
|
903
912
|
.. _`PR #224`: https://github.com/jquast/wcwidth/pull/224
|
|
913
|
+
.. _`PR #226`: https://github.com/jquast/wcwidth/pull/226
|
|
904
914
|
.. _`Issue #101`: https://github.com/jquast/wcwidth/issues/101
|
|
905
915
|
.. _`Issue #155`: https://github.com/jquast/wcwidth/issues/155
|
|
906
916
|
.. _`Issue #190`: https://github.com/jquast/wcwidth/issues/190
|
|
@@ -980,7 +990,7 @@ https://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c::
|
|
|
980
990
|
.. _`Grapheme Clusters and Terminal Emulators`: https://mitchellh.com/writing/grapheme-clusters-in-terminals
|
|
981
991
|
.. _`terminal-unicode-core.tex`: https://github.com/contour-terminal/terminal-unicode-core/blob/master/spec/terminal-unicode-core.tex
|
|
982
992
|
.. _`State of Terminal Emulators in 2025`: https://www.jeffquast.com/post/state-of-terminal-emulation-2025/
|
|
983
|
-
.. _`
|
|
993
|
+
.. _`Perfecting Terminal Character Width Using Correction Tables (2026)`: https://www.jeffquast.com/post/perfecting-terminal-character-width-using-correction-tables/
|
|
984
994
|
.. _XTVERSION: https://vtdn.dev/docs/dcs/xtversion/
|
|
985
995
|
.. _ENQ: https://documentation.help/PuTTY/config-answerback.html
|
|
986
996
|
.. _detectable: https://ucs-detect.readthedocs.io/results.html#terminal-identification
|
|
@@ -19,7 +19,7 @@ its docstring and specifications of related control codes, `XTerm Control Sequen
|
|
|
19
19
|
Text Sizing Protocol`_.
|
|
20
20
|
|
|
21
21
|
Each string yielded by :func:`wcwidth.iter_graphemes` may be mapped to :func:`wcwidth.wcswidth` to
|
|
22
|
-
accurately measure the width of a
|
|
22
|
+
accurately measure the width of a grapheme. Although :func:`wcwidth.iter_graphemes` matches
|
|
23
23
|
behavior of Python 3.15 `uncodedata.iter_graphemes()`_ it differs in its return value,
|
|
24
24
|
:func:`wcwidth.iter_graphemes` yields only strings, while :func:`unicodedata.iter_graphemes` yields
|
|
25
25
|
``unicodedata.Segment`` class objects.
|
|
@@ -33,7 +33,7 @@ The following have a column width of -1 for function :func:`wcwidth.wcwidth`
|
|
|
33
33
|
- ``C1`` control characters and ``DEL`` (`U+007F`_ through `U+00A0`_).
|
|
34
34
|
|
|
35
35
|
If any character in sequence contains ``C0`` or ``C1`` control characters, the final
|
|
36
|
-
return value of
|
|
36
|
+
return value of :func:`wcwidth.wcswidth` is -1.
|
|
37
37
|
|
|
38
38
|
Width of 0
|
|
39
39
|
----------
|
|
@@ -4,7 +4,7 @@ requires = [ "hatchling" ]
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "wcwidth"
|
|
7
|
-
version = "0.8.
|
|
7
|
+
version = "0.8.2" # don't forget to also update wcwidth/__init__.py:__version__
|
|
8
8
|
description = "Measures the displayed width of unicode strings in a terminal"
|
|
9
9
|
readme = "README.rst"
|
|
10
10
|
keywords = [
|
|
@@ -497,6 +497,12 @@ def test_zwj_at_end_of_string():
|
|
|
497
497
|
assert wcwidth.wcswidth('a\u200D') == 1
|
|
498
498
|
|
|
499
499
|
|
|
500
|
+
def test_wcswidth_n_exceeds_length():
|
|
501
|
+
"""Verify wcswidth() with n > len(string) does not raise IndexError."""
|
|
502
|
+
assert wcwidth.wcswidth('hello', n=999) == 5
|
|
503
|
+
assert wcwidth.wcswidth('\u30B3\u30F3', n=999) == 4
|
|
504
|
+
|
|
505
|
+
|
|
500
506
|
def test_soft_hyphen():
|
|
501
507
|
# Test SOFT HYPHEN, category 'Cf' usually are zero-width, but most
|
|
502
508
|
# implementations agree to draw it was '1' cell, visually
|
|
@@ -8,7 +8,11 @@ import pytest
|
|
|
8
8
|
# local
|
|
9
9
|
import wcwidth
|
|
10
10
|
import wcwidth.table_grapheme_overrides as grapheme_overrides
|
|
11
|
-
from wcwidth._constants import
|
|
11
|
+
from wcwidth._constants import (_EMPTY_OVERRIDES,
|
|
12
|
+
_merge_ranges,
|
|
13
|
+
resolve_terminal,
|
|
14
|
+
get_term_overrides,
|
|
15
|
+
list_term_programs)
|
|
12
16
|
from wcwidth.table_overrides import VS15_OVERRIDES
|
|
13
17
|
|
|
14
18
|
|
|
@@ -362,6 +366,106 @@ def test_sfz_override_foot():
|
|
|
362
366
|
assert wcwidth.wcstwidth('\U0001F3FB', term_program='foot') == 1
|
|
363
367
|
|
|
364
368
|
|
|
369
|
+
@pytest.mark.parametrize('term_program,expected', [
|
|
370
|
+
('kitty', 0),
|
|
371
|
+
('bobcat', 0),
|
|
372
|
+
(False, 2),
|
|
373
|
+
])
|
|
374
|
+
def test_sfz_zeroer(term_program, expected):
|
|
375
|
+
"""Standalone Fitzpatrick modifiers zeroed per terminal."""
|
|
376
|
+
assert wcwidth.wcswidth('\U0001F3FB') == 2
|
|
377
|
+
assert wcwidth.wcstwidth('\U0001F3FB', term_program=term_program) == expected
|
|
378
|
+
|
|
379
|
+
|
|
380
|
+
@pytest.mark.parametrize('kwargs,expected', [
|
|
381
|
+
({}, 0),
|
|
382
|
+
({'control_codes': 'ignore'}, 0),
|
|
383
|
+
])
|
|
384
|
+
def test_width_zeroer(kwargs, expected):
|
|
385
|
+
"""Width() zeroes standalone Fitzpatrick modifiers for kitty."""
|
|
386
|
+
assert wcwidth.width('\U0001F3FB', term_program='kitty', **kwargs) == expected
|
|
387
|
+
|
|
388
|
+
|
|
389
|
+
def test_empty_overrides_includes_zeroer():
|
|
390
|
+
"""_EMPTY_OVERRIDES has six empty tuple fields."""
|
|
391
|
+
assert _EMPTY_OVERRIDES.narrower == ()
|
|
392
|
+
assert _EMPTY_OVERRIDES.vs16_narrower == ()
|
|
393
|
+
assert _EMPTY_OVERRIDES.vs15_wider == ()
|
|
394
|
+
assert _EMPTY_OVERRIDES.zeroer == ()
|
|
395
|
+
assert _EMPTY_OVERRIDES.narrow_wider == ()
|
|
396
|
+
assert _EMPTY_OVERRIDES.narrow_zeroer == ()
|
|
397
|
+
|
|
398
|
+
|
|
399
|
+
def test_get_term_overrides_returns_empty_when_no_overrides():
|
|
400
|
+
"""get_term_overrides returns _EMPTY_OVERRIDES when terminal has no override data."""
|
|
401
|
+
get_term_overrides.cache_clear()
|
|
402
|
+
overrides = get_term_overrides('no-such-terminal')
|
|
403
|
+
assert overrides is _EMPTY_OVERRIDES
|
|
404
|
+
|
|
405
|
+
|
|
406
|
+
def test_get_term_overrides_reads_narrow_zeroer_key():
|
|
407
|
+
"""get_term_overrides reads 'narrow_zeroer' key from NARROW_OVERRIDES."""
|
|
408
|
+
get_term_overrides.cache_clear()
|
|
409
|
+
overrides = get_term_overrides('kitty')
|
|
410
|
+
assert len(overrides.narrow_zeroer) == 9
|
|
411
|
+
assert overrides.narrow_zeroer[0] == (0x00AD, 0x00AD)
|
|
412
|
+
|
|
413
|
+
|
|
414
|
+
def test_get_term_overrides_narrow_wider_still_empty():
|
|
415
|
+
"""get_term_overrides narrow_wider is empty when no 'wider' entries exist."""
|
|
416
|
+
get_term_overrides.cache_clear()
|
|
417
|
+
overrides = get_term_overrides('konsole')
|
|
418
|
+
assert overrides.narrow_wider == ()
|
|
419
|
+
|
|
420
|
+
|
|
421
|
+
@pytest.mark.parametrize('func', [wcwidth.wcstwidth, wcwidth.width])
|
|
422
|
+
def test_narrow_wider_width(func):
|
|
423
|
+
"""Verify width() & wcstwidth() match result of narrow_wider overrides."""
|
|
424
|
+
assert wcwidth.wcswidth('\u261d') == 1
|
|
425
|
+
assert func('\u261d', term_program='kitty') == 2
|
|
426
|
+
|
|
427
|
+
|
|
428
|
+
@pytest.mark.parametrize('codepoint', [
|
|
429
|
+
'\u00ad',
|
|
430
|
+
'\u0600',
|
|
431
|
+
'\u0605',
|
|
432
|
+
'\u06dd',
|
|
433
|
+
'\u070f',
|
|
434
|
+
'\u0890',
|
|
435
|
+
'\u0891',
|
|
436
|
+
'\u08e2',
|
|
437
|
+
'\U000110bd',
|
|
438
|
+
'\U000110cd',
|
|
439
|
+
])
|
|
440
|
+
def test_narrow_zeroer_cf_codepoints(codepoint):
|
|
441
|
+
"""Cf format characters are zeroed by kitty/konsole/wezterm narrow_zeroer."""
|
|
442
|
+
assert wcwidth.wcswidth(codepoint) == 1
|
|
443
|
+
assert wcwidth.wcstwidth(codepoint, term_program='kitty') == 0
|
|
444
|
+
assert wcwidth.wcstwidth(codepoint, term_program='konsole') == 0
|
|
445
|
+
assert wcwidth.wcstwidth(codepoint, term_program='wezterm') == 0
|
|
446
|
+
|
|
447
|
+
|
|
448
|
+
@pytest.mark.parametrize('func', [wcwidth.wcstwidth, wcwidth.width])
|
|
449
|
+
def test_narrow_zeroer_not_applied_for_other_terminals(func):
|
|
450
|
+
"""Terminals without narrow overrides keep width 1 for Cf characters."""
|
|
451
|
+
assert func('\u0600', term_program='xterm') == 1
|
|
452
|
+
assert func('\u0600', term_program='ghostty') == 1
|
|
453
|
+
assert func('\u0600', term_program='') == 1
|
|
454
|
+
|
|
455
|
+
|
|
456
|
+
@pytest.mark.parametrize('func,term_program,expected', [
|
|
457
|
+
(wcwidth.wcstwidth, 'kitty', 0),
|
|
458
|
+
(wcwidth.width, 'kitty', 0),
|
|
459
|
+
(wcwidth.wcstwidth, 'konsole', 0),
|
|
460
|
+
(wcwidth.width, 'konsole', 0),
|
|
461
|
+
(wcwidth.wcstwidth, 'wezterm', 0),
|
|
462
|
+
(wcwidth.width, 'wezterm', 0),
|
|
463
|
+
])
|
|
464
|
+
def test_narrow_zeroer_width(func, term_program, expected):
|
|
465
|
+
"""Width() matches wcstwidth() for narrow_zeroer overrides."""
|
|
466
|
+
assert func('\u0600', term_program=term_program) == expected
|
|
467
|
+
|
|
468
|
+
|
|
365
469
|
@pytest.mark.parametrize('value,expected', [
|
|
366
470
|
(' KITTY ', 'kitty'),
|
|
367
471
|
(' ', None),
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
ambiguous_width: 1
|
|
2
|
-
datetime: 2026-06-
|
|
2
|
+
datetime: 2026-06-08 04:40:36 UTC
|
|
3
3
|
environment:
|
|
4
4
|
COLORTERM: truecolor
|
|
5
5
|
TERM: alacritty
|
|
@@ -8,40 +8,28 @@ preferred_encoding: UTF-8
|
|
|
8
8
|
python_version: 3.14.5
|
|
9
9
|
resource_profile:
|
|
10
10
|
cpu_pct:
|
|
11
|
-
-
|
|
12
|
-
- 1.0
|
|
11
|
+
- 16.0
|
|
13
12
|
- 0.0
|
|
14
|
-
-
|
|
15
|
-
-
|
|
16
|
-
-
|
|
17
|
-
- 51.9
|
|
18
|
-
- 69.7
|
|
19
|
-
- 45.9
|
|
13
|
+
- 1.0
|
|
14
|
+
- 63.9
|
|
15
|
+
- 78.9
|
|
20
16
|
elapsed_s:
|
|
21
|
-
- 1.
|
|
22
|
-
- 2.
|
|
23
|
-
- 3.
|
|
24
|
-
- 4.
|
|
25
|
-
- 5.
|
|
26
|
-
- 6.011714742984623
|
|
27
|
-
- 7.0173555499641225
|
|
28
|
-
- 8.019567951967474
|
|
29
|
-
- 9.023896721948404
|
|
17
|
+
- 1.0009446729673073
|
|
18
|
+
- 2.0028591490117833
|
|
19
|
+
- 3.004715724964626
|
|
20
|
+
- 4.006955301039852
|
|
21
|
+
- 5.008106541004963
|
|
30
22
|
hardware:
|
|
31
23
|
cpu_count: 12
|
|
32
24
|
cpu_model: AMD Ryzen 5 7640U w/ Radeon 760M Graphics
|
|
33
25
|
ram_total_kb: 13961408
|
|
34
26
|
rss_mb:
|
|
35
|
-
- 120.
|
|
36
|
-
- 120.
|
|
37
|
-
- 120.
|
|
38
|
-
-
|
|
39
|
-
-
|
|
40
|
-
|
|
41
|
-
- 130.4375
|
|
42
|
-
- 130.90234375
|
|
43
|
-
- 123.21484375
|
|
44
|
-
seconds_elapsed: 4.96278640901437
|
|
27
|
+
- 120.69140625
|
|
28
|
+
- 120.69140625
|
|
29
|
+
- 120.69140625
|
|
30
|
+
- 130.140625
|
|
31
|
+
- 133.27734375
|
|
32
|
+
seconds_elapsed: 1.9186390159884468
|
|
45
33
|
session_arguments:
|
|
46
34
|
all: false
|
|
47
35
|
limit_category_time: 0
|
|
@@ -8571,6 +8559,84 @@ test_results:
|
|
|
8571
8559
|
n_errors: 0
|
|
8572
8560
|
n_total: 8
|
|
8573
8561
|
pct_success: 100.0
|
|
8562
|
+
narrow_results:
|
|
8563
|
+
17.0.0:
|
|
8564
|
+
failed_codepoints:
|
|
8565
|
+
- measured_by_terminal: 0
|
|
8566
|
+
measured_by_wcwidth: 1
|
|
8567
|
+
wchar: \xad
|
|
8568
|
+
- measured_by_terminal: 0
|
|
8569
|
+
measured_by_wcwidth: 1
|
|
8570
|
+
wchar: \u0605
|
|
8571
|
+
- measured_by_terminal: 0
|
|
8572
|
+
measured_by_wcwidth: 1
|
|
8573
|
+
wchar: \u070f
|
|
8574
|
+
- measured_by_terminal: 0
|
|
8575
|
+
measured_by_wcwidth: 1
|
|
8576
|
+
wchar: \u0890
|
|
8577
|
+
- measured_by_terminal: 0
|
|
8578
|
+
measured_by_wcwidth: 1
|
|
8579
|
+
wchar: \u0891
|
|
8580
|
+
- measured_by_terminal: 0
|
|
8581
|
+
measured_by_wcwidth: 1
|
|
8582
|
+
wchar: \u08e2
|
|
8583
|
+
- measured_by_terminal: 0
|
|
8584
|
+
measured_by_wcwidth: 1
|
|
8585
|
+
wchar: \u0d4e
|
|
8586
|
+
- measured_by_terminal: 2
|
|
8587
|
+
measured_by_wcwidth: 1
|
|
8588
|
+
wchar: \u17a4
|
|
8589
|
+
- measured_by_terminal: 2
|
|
8590
|
+
measured_by_wcwidth: 1
|
|
8591
|
+
wchar: \u17d8
|
|
8592
|
+
- measured_by_terminal: 0
|
|
8593
|
+
measured_by_wcwidth: 1
|
|
8594
|
+
wchar: \ua8fa
|
|
8595
|
+
- measured_by_terminal: 0
|
|
8596
|
+
measured_by_wcwidth: 1
|
|
8597
|
+
wchar: \uff9e
|
|
8598
|
+
- measured_by_terminal: 0
|
|
8599
|
+
measured_by_wcwidth: 1
|
|
8600
|
+
wchar: \uff9f
|
|
8601
|
+
- measured_by_terminal: 0
|
|
8602
|
+
measured_by_wcwidth: 1
|
|
8603
|
+
wchar: \U000111c2
|
|
8604
|
+
- measured_by_terminal: 0
|
|
8605
|
+
measured_by_wcwidth: 1
|
|
8606
|
+
wchar: \U000111c3
|
|
8607
|
+
- measured_by_terminal: 0
|
|
8608
|
+
measured_by_wcwidth: 1
|
|
8609
|
+
wchar: \U0001193f
|
|
8610
|
+
- measured_by_terminal: 0
|
|
8611
|
+
measured_by_wcwidth: 1
|
|
8612
|
+
wchar: \U00011941
|
|
8613
|
+
- measured_by_terminal: 0
|
|
8614
|
+
measured_by_wcwidth: 1
|
|
8615
|
+
wchar: \U00011a84
|
|
8616
|
+
- measured_by_terminal: 0
|
|
8617
|
+
measured_by_wcwidth: 1
|
|
8618
|
+
wchar: \U00011a85
|
|
8619
|
+
- measured_by_terminal: 0
|
|
8620
|
+
measured_by_wcwidth: 1
|
|
8621
|
+
wchar: \U00011a86
|
|
8622
|
+
- measured_by_terminal: 0
|
|
8623
|
+
measured_by_wcwidth: 1
|
|
8624
|
+
wchar: \U00011a87
|
|
8625
|
+
- measured_by_terminal: 0
|
|
8626
|
+
measured_by_wcwidth: 1
|
|
8627
|
+
wchar: \U00011a88
|
|
8628
|
+
- measured_by_terminal: 0
|
|
8629
|
+
measured_by_wcwidth: 1
|
|
8630
|
+
wchar: \U00011a89
|
|
8631
|
+
- measured_by_terminal: 0
|
|
8632
|
+
measured_by_wcwidth: 1
|
|
8633
|
+
wchar: \U00011d46
|
|
8634
|
+
- measured_by_terminal: 0
|
|
8635
|
+
measured_by_wcwidth: 1
|
|
8636
|
+
wchar: \U00011f02
|
|
8637
|
+
n_errors: 24
|
|
8638
|
+
n_total: 187
|
|
8639
|
+
pct_success: 87.16577540106952
|
|
8574
8640
|
ri_results:
|
|
8575
8641
|
17.0.0:
|
|
8576
8642
|
failed_codepoints: []
|
|
@@ -8749,7 +8815,7 @@ test_results:
|
|
|
8749
8815
|
measured_by_wcwidth: 2
|
|
8750
8816
|
wchar: \U0001f1ff
|
|
8751
8817
|
n_errors: 26
|
|
8752
|
-
n_total:
|
|
8753
|
-
pct_success:
|
|
8754
|
-
wcwidth_version: 0.8.
|
|
8818
|
+
n_total: 506
|
|
8819
|
+
pct_success: 94.86166007905138
|
|
8820
|
+
wcwidth_version: 0.8.1
|
|
8755
8821
|
width: 80
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
ambiguous_width: 1
|
|
2
|
-
datetime: 2026-06-
|
|
2
|
+
datetime: 2026-06-08 04:39:53 UTC
|
|
3
3
|
environment:
|
|
4
4
|
COLORTERM: truecolor
|
|
5
5
|
TERM: xterm-256color
|
|
@@ -9,15 +9,18 @@ python_version: 3.14.5
|
|
|
9
9
|
resource_profile:
|
|
10
10
|
cpu_pct:
|
|
11
11
|
- 28.9
|
|
12
|
+
- 22.9
|
|
12
13
|
elapsed_s:
|
|
13
|
-
- 1.
|
|
14
|
+
- 1.0030964689794928
|
|
15
|
+
- 2.0049722640542313
|
|
14
16
|
hardware:
|
|
15
17
|
cpu_count: 12
|
|
16
18
|
cpu_model: AMD Ryzen 5 7640U w/ Radeon 760M Graphics
|
|
17
19
|
ram_total_kb: 13961408
|
|
18
20
|
rss_mb:
|
|
19
|
-
- 122.
|
|
20
|
-
|
|
21
|
+
- 122.04296875
|
|
22
|
+
- 123.1015625
|
|
23
|
+
seconds_elapsed: 2.1441276310943067
|
|
21
24
|
session_arguments:
|
|
22
25
|
all: false
|
|
23
26
|
limit_category_time: 0
|
|
@@ -9927,6 +9930,27 @@ test_results:
|
|
|
9927
9930
|
n_errors: 0
|
|
9928
9931
|
n_total: 8
|
|
9929
9932
|
pct_success: 100.0
|
|
9933
|
+
narrow_results:
|
|
9934
|
+
17.0.0:
|
|
9935
|
+
failed_codepoints:
|
|
9936
|
+
- measured_by_terminal: 0
|
|
9937
|
+
measured_by_wcwidth: 1
|
|
9938
|
+
wchar: \u0890
|
|
9939
|
+
- measured_by_terminal: 0
|
|
9940
|
+
measured_by_wcwidth: 1
|
|
9941
|
+
wchar: \u0891
|
|
9942
|
+
- measured_by_terminal: 0
|
|
9943
|
+
measured_by_wcwidth: 1
|
|
9944
|
+
wchar: \u08e2
|
|
9945
|
+
- measured_by_terminal: 0
|
|
9946
|
+
measured_by_wcwidth: 1
|
|
9947
|
+
wchar: \U000110bd
|
|
9948
|
+
- measured_by_terminal: 0
|
|
9949
|
+
measured_by_wcwidth: 1
|
|
9950
|
+
wchar: \U000110cd
|
|
9951
|
+
n_errors: 5
|
|
9952
|
+
n_total: 187
|
|
9953
|
+
pct_success: 97.32620320855615
|
|
9930
9954
|
ri_results:
|
|
9931
9955
|
17.0.0:
|
|
9932
9956
|
failed_codepoints:
|
|
@@ -10774,7 +10798,7 @@ test_results:
|
|
|
10774
10798
|
measured_by_wcwidth: 2
|
|
10775
10799
|
wchar: \U0001f3ff
|
|
10776
10800
|
n_errors: 11
|
|
10777
|
-
n_total:
|
|
10778
|
-
pct_success:
|
|
10779
|
-
wcwidth_version: 0.8.
|
|
10801
|
+
n_total: 506
|
|
10802
|
+
pct_success: 97.82608695652173
|
|
10803
|
+
wcwidth_version: 0.8.1
|
|
10780
10804
|
width: 80
|