--- /dev/null
+"""Generates a width table for Unicode characters.
+
+This script generates a width table for Unicode characters that are not
+narrow (width 1). The table is written to src/black/_width_table.py (note
+that although this file is generated, it is checked into Git) and is used
+by the char_width() function in src/black/strings.py.
+
+You should run this script when you upgrade wcwidth, which is expected to
+happen when a new Unicode version is released. The generated table contains
+the version of wcwidth and Unicode that it was generated for.
+
+In order to run this script, you need to install the latest version of wcwidth.
+You can do this by running:
+
+ pip install -U wcwidth
+
+"""
+
+import sys
+from os.path import basename, dirname, join
+from typing import Iterable, Tuple
+
+import wcwidth # type: ignore[import]
+
+
+def make_width_table() -> Iterable[Tuple[int, int, int]]:
+ start_codepoint = -1
+ end_codepoint = -1
+ range_width = -2
+ for codepoint in range(0, sys.maxunicode + 1):
+ width = wcwidth.wcwidth(chr(codepoint))
+ if width <= 1:
+ # Ignore narrow characters along with zero-width characters so that
+ # they are treated as single-width. Note that treating zero-width
+ # characters as single-width is consistent with the heuristics built
+ # on top of str.isascii() in the str_width() function in strings.py.
+ continue
+ if start_codepoint < 0:
+ start_codepoint = codepoint
+ range_width = width
+ elif width != range_width or codepoint != end_codepoint + 1:
+ yield (start_codepoint, end_codepoint, range_width)
+ start_codepoint = codepoint
+ range_width = width
+ end_codepoint = codepoint
+ if start_codepoint >= 0:
+ yield (start_codepoint, end_codepoint, range_width)
+
+
+def main() -> None:
+ table_path = join(dirname(__file__), "..", "src", "black", "_width_table.py")
+ with open(table_path, "w") as f:
+ f.write(f"""# Generated by {basename(__file__)}
+# wcwidth {wcwidth.__version__}
+# Unicode {wcwidth.list_versions()[-1]}
+from typing import Final, List, Tuple
+
+WIDTH_TABLE: Final[List[Tuple[int, int, int]]] = [
+""")
+ for triple in make_width_table():
+ f.write(f" {triple!r},\n")
+ f.write("]\n")
+
+
+if __name__ == "__main__":
+ main()